GLSLには複数の光源に関するすばらしい記事があります
http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Multiple_Lights
しかし、シェーダーコードで記述されているlight0とlight1のパラメーターは、フレアガンショットを描画する必要がある場合はどうなりますか。それは位置、色を所有し、周囲を照らさなければなりません。未知の(画面上の最大フレアには制限があります)位置、フレアの色を処理するために、他のオブジェクトシェーダーをどのように管理しますか?たとえば、画面には最大8つのフレアが表示されますが、現時点で存在しない場合でも、8 * 2のユニフォームを渡すには何が必要ですか?
または、レベルエディタを作成していると想像してください。ユーザーはランプを配置できます。他のオブジェクトは、新しい光源について「認識」してレンダリングし、新しいランプが追加されます。
賢い解決策があるに違いないと思いますが、私はそれを見つけることができません。
1 に答える
照明の方程式は通常、加法色に依存しています。したがって、出力は、ライト1の色+ライト2の色+ライト3の色などになります。
OpenGLが提供するフレームバッファ内ブレンディングモードの1つは、加法ブレンディングです。したがって、描画した新しいもののカラー出力は、すでにバッファにあるものに追加されます。
したがって、最も単純な解決策は、正確に1つのライトを実行するようにシェーダーを作成することです。複数のライトがある場合は、シーンを何度も描画します。そのたびに、異なる指定線を使用します。これはマルチパスレンダリングの例です。
より良い解決策は、2、4、8、または任意のライトを一度に実行するシェーダーを作成することです。たとえば、15ライトを8ライトドロー、4ライトドロー、2ライトドロー、1ライトドローとして実行します。パスを実行するときに、各ライトの手の届く範囲にあるジオメトリのみを含みます。これは、地域ごとにライトをグループ化するインテリジェントな方法を見つけることを意味する傾向があります。
編集:もう少し考えて、遅延シェーディングには別のオプションがあることを追加する必要がありますが、出力バッファーのオプションが限られているため、現時点ではほとんどのGLESデバイスで完全には役立ちません。
理論的には、ジオメトリを1回だけレンダリングし、ピクセルごとに必要なものを保存できると仮定します。したがって、色を出力するだけでなく、たとえば、3D空間内の位置、法線、拡散色、鏡面反射色、および鏡面反射光の指数を出力します。これらはすべて、ピクセルごとのバッファにあります。
次に、(i)スクリーンに投影されたときに占有できる最大のスペース(つまり、ピクセルに直接関連する2D長方形)を計算することにより、各ライトをレンダリングできます。(ii)ライトをそのサイズの単一のクワッドとしてレンダリングし、各ピクセルに対して、設定したバッファから関連する値を読み取り、適切に点灯した色を出力します。
次に、シーン内のすべての実際のジオメトリを1回だけ実行すると、追加のライトごとに、最大で1つのフルスクリーンクワッドのコストがかかります。
実際には、ESで使用できる傾向のある出力バッファーが提供するストレージが少なすぎるため、実際にはそれを行うことはできません。ただし、通常できることは、デプスバッファが接続された32ビットカラーバッファにレンダリングすることです。したがって、深度を深度バッファに保存し、そこからワールド(x、y、z)に加えて、ライトシェーダ内のカメラの[均一]位置を計算することができます。通常のxとyの8ビットバージョンをカラーバッファに格納して、16ビットを使用し、カラーバッファでzを計算することができます。これは、通常が常に単位長であることがわかっているためです。次に、具体的な例をランダムに選択するために、16ビットバージョンの拡散色を残りのスペースに、おそらくY用の追加のストレージを備えたYCrCbに格納できます。
主な欠点は、ハードウェアのアンチエイリアシングが、透過性や深度バッファとほとんど同じ種類の懸念によるものではないことです。ただし、照明を大幅に節約できるようになった場合でも、シーンの大きなバージョンをレンダリングし、最後のパスで縮小することで、手動のアンチエイリアスを実行するのが理にかなっている場合があります。