シーンに少なくとも 20 個のライトが必要なため、ディファード シェーディングの実装に取り組んでいます。私はそれを十分に速くするのに問題を抱えていました(そして今でもそうです)が、遅くなると思っていた変更を加えましたが、実際にはフレームレートがほぼ2倍になりました.
初期コード:
geometryPassFBO = createFBO(); // position texture, normal texture, colour texture and depth buffer
while (1)
{
bind geometryPassFBO.
allObjects.draw();
bind systemFBO();
for each light
send light info
draw light sphere sampling from position, normal and colour textures.
blit depth buffer from geometryFBO to systemFBO
for each light
light.draw(); // draw a cube to represent the light
2DObjects.draw(); // frame rate, etc...
}
ジオメトリ パス中にピクセルが設定されている場合 (つまり、法線 = 0,0,0、位置 = 0,0,0、色 = 0 の背景) にのみライティング パスを実行するようにステンシル テストをセットアップしていました。 ,0,0.
ただし、結合された深度/ステンシル バッファーをデフォルトの深度/ステンシル バッファーにコピーするのは困難でした。システムの深度/ステンシル バッファがどのような形式になるかがわからないため、これはうまく機能しないようです。そのため、深度/ステンシル バッファ フォーマットを指定し、これにレンダリングしてから、スクリーン クワッドをブリットまたはレンダリングして画面に出力できる別の FBO をセットアップする方がよいと読んでいました。
そのため、ステンシルを追加する前に、新しい FBO を追加して、そのビットが機能するようにしました。
私の新しいコードは次のようになります。
geometryPassFBO = createGeometryFBO(); // position texture, normal texture, colour texture and depth buffer
lightingPassFBO = createLightingFBO(); // colour texture and depth buffer
while (1)
{
bind geometryPassFBO.
allObjects.draw();
bind lightingPassFBO();
for each light
send light info
draw light sphere sampling from position, normal and colour textures.
blit depth buffer from geometryFBO to lightingPassFBO
for each light
light.draw(); // draw a cube to represent the light
2DObjects.draw(); // frame rate, etc...
bind systemFBO;
render screen quad sampling from colour texture.
}
これは期待どおりに機能します。予想外だったのは、フレーム レートが 25 FPS から 45 FPS に急上昇したことです。
どうしてこれなの?スクリーン クワッドに追加のシェーダー パスを実行しなければならないことは、実行しないよりも効率的ですか?
簡単なフォローアップの質問。シンプルな頂点シェーダーとフラグメント シェーダーを使用して gl_FragCoord に基づいてテクスチャをサンプリングすることと、カラー アタッチメントをシステム FBO に直接ブリットすることのどちらが効率的ですか?