遅延シェーディング-複数のライトを組み合わせる方法は?


9

私はGLSLから始めて、位置、法線、およびアルベドでGバッファーを出力する単純な遅延シェーディングを実装しました。

簡単なポイントライトシェーダーも作成しました。

次に、ポイントライトの球を描画し、出力をライティングバッファーに入れます。

問題は、複数のライトを描画するときに、ライティングバッファの結果をどのように組み合わせるかです。

たとえば、ポイントライトシェーダーを使用して2番目のライトをライトバッファーに描画する場合、最初のライトをライティングバッファーの2番目のライトに追加するにはどうすればよいですか。つまり、同じ出力バッファから読み書きすることはできませんか?

回答:


12

加法混合、つまりglBlendFunc(GL_ONE、GL_ONE)とglEnable(GL_BLEND)。


このため、深度テストを無効にする必要がありますか?
woojoo666

1
@ woojoo666いいえ。実際には、前のパスと正確に一致するサーフェスが通過するように、深度テストを不等に設定して有効にする必要があります。深度テストがオフの場合、サーフェスは背後にあるものからの光を誤って蓄積します。:)
ネイサンリード

うーん、それはまさに何が起こっているかのようです。ブレンドをオンにすると、深度テストを有効にしていても、前面と背面がブレンドされます。デプスマスクでも何かする必要がありますか?
woojoo666

もう少しテストを行いました。描画順序が重要なようです(前面から背面に描画すると深度テストが正しく機能し、面が等平面である場合にのみブレンドが行われ、背面から前面に向かってすべてがブレンドされます)。すべてをソートせずにこれを行う方法はありますか?
woojoo666

2
@ woojoo666あは、自分で解決したようですね。はい、あらゆる種類のブレンドを使用する前に、不透明なパスに深度を設定する必要があります。これは、カラー書き込みを無効にしたz-prepassにすることも、ブレンドなしの最初のパスでアンビエント/ディレクショナルライトを実行してから、ブレンドを使用して後のパスでポイント/スポットライトを追加することもできます。
ネイサンリード

2

据え置きレンダラーでは、gバッファーからの情報を使用してすべてのライトを1つのライトレンダーターゲットに集約し、最終的なバックバッファーイメージを作成しながら、そのレンダーターゲットを光の強度でサンプリングします。

したがって、基本的には、すべてのゲームジオメトリをジオメトリパスに通して、gバッファを構築します。そこから、g-バッファをライトパスシェーダに送ります。各ライトは、フルスクリーンクワッドを使用してパスを通過します。このようにして、ピクセルシェーダーは、gバッファーからのすべての可視サーフェスの光の強度を計算し、それらをライトレンダーターゲットに追加できます。各ライトのライト強度をライトバッファーに追加するだけですが、強度を0から1にクランプしてください。

さまざまな種類のライト(ポイント、スポットライト、パラレル)を処理するために必要なことは、実行するライティングプロシージャを指定するために定数バッファを使用することにより、ライトパスをより堅牢にすることです。


ええ、そして問題は-ライトレンダーターゲットにどのように追加するのですか?ネイサンリードの提案どおりにアルファブレンディングを使用していますか?私の知る限り、同じ出力バッファー(この場合はライトバッファー)からの読み取りと書き込みができないためです。
JBeurer 2012年

おっと、そう。私は出力マージに加法ブレンディングでそれを処理させました。最終的な画像のサンプリングは、表面が受け取ることができる最大の光強度として機能する値にクランプしたい場合です。そこから、必要に応じてライトをスケーリングできます。
KlashnikovKid

ライトが壁の後ろにあり、壁の反対側にあるものを照らしてはいけない場合にどのように対処しますか?
jjxtra 2013

@PsychoDad影の領域です。これは...より複雑なトピックです。:)
ネイサンリード

0

おそらくこれよりも良い答えがありますが、シェーダーで2番目のライトを実行するために必要なコードを繰り返すと、1つのオブジェクトではなく2つのライトを1つのオブジェクトで処理できるようになります。2番目のライトの多くのコードをダブリングする必要があり、継ぎ目は少し冗長ですが、動作することはわかっています。ただし、誰かがうまくいけば指摘してくれるので、もっとエレガントな解決策があるかもしれません。


いいえ、そのようには機能しません。各ポイントライトに球を描画します。2番目のポイントライトが最初のライトの影響範囲内にない限り、2番目のライトは単純に描画されません。すべてのポイントライトにフルスクリーンクワッドを描画すると、この方法は機能しますが、フルスクリーンクワッドはグローバルイルミネーションに使用されるため、これは適切なアプローチではありません。小さなポイントライトが16個あるとします。これにより、ピクセルが照らされていない場合でも、ピクセルごとにライトを通過する必要があります。通常、各ピクセルは1つまたは2つのライトで照らされます。また、100個のライトがある場合はどうなりますか?いいえ
JBeurer

私がこれを述べた主な理由は、2つまたはいくつかのライトのみを使用している場合に役立ちます。特に、多くのオブジェクトをレンダリングする場合、ブレンドを使用すると、ライトごとにシーンを再描画する必要があるため、100万、1千万、10億など、多くのシェイプがある場合、描画ごとに多くのコストがかかります。 。シェーダーでそれを行うと、多くのライトが必要な場合は問題が発生しますが、ブレンドが多くの形状が必要な場合は問題が発生します。両方がたくさんある場合は、中間点を見つける必要がありますが、通常、ゲームにはいくつかのライトとたくさんのオブジェクトがあります。
CodeNeko

いいえ、遅延シェーディングはそのようには機能しません。一度だけシーンを描き、関連情報をG-Bufferに保存します。次に、各ライトの影響範囲をライトバッファとブレンドします。最後に、ライトバッファーとカラーバッファーを組み合わせて、最終的なシェーディングされたカラーバッファーを取得します。照明計算の量は、シーンの複雑さに依存しません。それがそもそも遅延シェーディングの主な利点です。
JBeurer 2012年

ああ、それはもっと理にかなっていて、かなり良いでしょう。
CodeNeko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.