Webgl 遅延レンダラーをハイ ダイナミック レンジを使用するレンダラーに変換中です。私はオンラインのさまざまな情報源からこの件について多くのことを読みましたが、いくつかの質問があります。私が行った読書のほとんどは HDR 画像のレンダリングに関するものですが、私の質問は、HDR をサポートするためにレンダラーをどのように変更する必要があるかに関するものです。
私が理解しているように、HDR は基本的に、非常に明るいシーンでも暗いシーンでも詳細を確認できるように、より高い光の範囲をキャプチャしようとしています。通常、ゲームでは強度 1 を使用して白色光と 0 黒を表します。しかし、HDR / 現実世界では、範囲ははるかに多様です。つまり、エンジン内の太陽は、10 の電球よりも 10000 倍明るいかもしれません。
これらのより大きな範囲に対処するには、レンダラーを変換して、ライト パスに浮動小数点レンダー ターゲット (またはメモリ使用量が少ないので理想的には半分の浮動小数点数) を使用する必要があります。
私の最初の質問は、照明についてです。浮動小数点のレンダー ターゲットに加えて、これは単純に、以前は強度 1 の太陽を表すライトがあった場合、10000 として表すことができる/表す必要があるということですか? いえ
float spec = calcSpec();
vec4 diff = texture2D( sampler, uv );
vec4 color = diff * max(0.0, dot( N, L )) * lightIntensity + spec; //Where lightIntensity is now 10000?
return color;
ライティング システムにその他の基本的な変更はありますか (float テクスチャとより高い範囲を除く)?
これに続いて、(説明したように高い範囲で) すべてのライト値を加算的に蓄積した float レンダー ターゲットができました。この時点で、レンダー ターゲットでブルームなどの後処理を行う場合があります。完了したら、画面に送信する前にトーン マッピングする必要があります。これは、光の範囲をモニターの範囲に戻す必要があるためです。
したがって、トーン マッピング フェーズでは、おそらくポスト プロセスを使用し、トーン マッピング式を使用して HDR 照明を低ダイナミック レンジに変換します。私が選んだテクニックは、Uncharted 2 の John Hables でした。
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
const float W = 11.2;
vec3 Uncharted2Tonemap(vec3 x)
{
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
... // in main pixel shader
vec4 texColor = texture2D(lightSample, texCoord );
texColor *= 16; // Hardcoded Exposure Adjustment
float ExposureBias = 2.0;
vec3 curr = Uncharted2Tonemap( ExposureBias * texColor.xyz );
vec3 whiteScale = 1.0 / Uncharted2Tonemap(W);
vec3 color = curr * whiteScale;
// Gama correction
color.x = pow( color.x, 1.0 /2.2 );
color.y = pow( color.y, 1.0 /2.2 );
color.z = pow( color.z, 1.0 /2.2 );
return vec4( color, 1.0 );
2 番目の質問は、このトーン マッピング フェーズに関連しています。単にこのテクニック以上のものがあるのでしょうか? HDR と見なすために必要なのは、より高い光強度を使用して露出を微調整することだけですか? 一部のゲームには平均発光を計算するための自動露出機能があることは理解していますが、最も基本的なレベルでこれは必要ですか? おそらく、露出を手動で微調整するだけで使用できますか?
多くのドキュメントで議論されている他のことは、ガマ補正のことです。ガマ補正は2箇所で行われているようです。最初にテクスチャが読み取られるとき、次に画面に送信されるときにもう一度実行されます。テクスチャを読み込むときは、単に次のように変更する必要があります。
vec4 diff = pow( texture2D( sampler, uv), 2.2 );
次に、上記のトーン マッピング手法では、出力補正は次のように行われます。
pow(color,1/2.2);
John Hables のプレゼンテーションから、すべてのテクスチャをこのように修正する必要があるわけではないと述べています。拡散テクスチャは必須ですが、法線マップなどは必ずしも必須ではありません。
3 番目の質問は、このガマ補正についてです。これは機能するために必要ですか?拡散反射光マップが読み込まれるすべての場所でエンジンを変更する必要があるということですか?
それが、この変換に関係するものについての私の現在の理解です。それは正しいですか、私が誤解したり間違ったりしたことはありますか?