1

いくつかのバリエーションで MSAA のサポートを実装しました。

コンテキスト ベース (コンテキストを設定し、それに応じたパラメーター リストを渡すときに wglChoosePixelFormatARB を呼び出す) または FBO への MSAA レンダリングを有効にする (色と深度のレンダーバッファー アタッチメントを持つマルチサンプリング FBO と、カラー アタッチメントを持つ別の FBO を作成する) のいずれかを使用できます。解決のため)、アンチエイリアスは全体的に機能しているようです。

ただし、アンチエイリアシングを有効にすると、スペキュラー ライティングに関連すると思われるアーティファクトがいくつか見つかりました。コンテキストベースの CSAA では最悪であり、コンテキストベースの MSAA ではかなり悪いですが、FBO にレンダリングするときに MSAA を使用すると、はるかに改善されます。

私がテストに使用した航空機モデルの 1 つで、特にエンジン シリンダーといくつかの「ワイヤー」の周りで非常に目立ちます (実際には線ではなく、細いシリンダーです)。

結果比較

画像でわかるように、スペキュラ ライトをオフにすると、問題はほとんどなくなりましたが、何が原因なのかはよくわかりません。

上の画像では、次のシェーダー コードを使用して鏡面反射を計算しています (すべてのライトのループ内)。

if( matShininess > 0.0 )
{
    vec3 reflectionCamSpace = reflect(-lightDirectionCamSpace, faceNormal);
    vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
    float dotSpecular = max( 0.0, dot (reflectionCamSpace, surfToViewerCamSpace) );
    float specularFactor = pow( dotSpecular, matShininess );
    specularTerm += vec3(lgt.specular * specularFactor); 
}

また、異なる照明モデルの間にはかなりの違いがあるようです:

照明モデル

左側はスペキュラ ハイライト用に上記のコードを使用していますが、右側はこれを使用しています (すべてのライトを反復処理するメイン ライト ループ内)。

if( matShininess > 0.0 )
{
    vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
    vec3 halfAngle = normalize(lightDirectionCamSpace + surfToViewerCamSpace);
    float specularFactor = dot(faceNormal, halfAngle);
    specularFactor = clamp(specularFactor, 0, 1);
    specularFactor = lightDot != 0.0 ? specularFactor : 0.0;
    specularFactor = pow(specularFactor, matShininess);
    specularTerm += vec3(lgt.specular * specularFactor);
}

では、FBO ベースの MSAA とコンテキスト ベースの MSAA を使用する場合に、なぜそれほど大きな違いがあるのか​​ 疑問に思っています。また、そもそも問題を引き起こすために、スペキュラー ハイライトで何が間違っていたのでしょうか?

編集:以下の投稿で要求されたように、コンテキストと FBO を介して 16xQ CSAA の結果を比較するためのテストも追加しました (FBO の場合、glRenderbufferStorageMultisample の代わりに RenderbufferStorageMultisampleCoverageNV を使用しています)。ここでも、FBO の結果の方が優れているように見えます (ただし、まだ説得力はありません)。

16xQ CSAA Ctx 対 FBO

4

1 に答える 1

1

これは答えではありません。コメントの長いリクエストのようなものです。

サンプル シェーディングが役立つ場合があります。カバレッジでこの最適化が許可されている場合は、フラグメントごとに 1 回計算を行い、結果をすべてのサンプルに引き継ぐ代わりに、シェーダーを複数回評価するよう GL に指示できます。MSAA を使用すると、シェーダーは、プリミティブがピクセルを完全に覆うフラグメントに対して 1 回だけ評価されます。深度/ステンシル サンプルはサンプルごとに一意であり、これはエッジ エイリアシングに役立ちますが、シェーダー自体で発生するエイリアシング (テクスチャ エイリアシング、スペキュラー ハイライトなど) は、純粋な MSAA では修正されません。

サンプル シェーディングは、MSAA を MSAA (複数のサンプルを 1 回シェーディングすることができます) から SSAA (1:1 のサンプル: シェーディング比) まで効果的に変換します。あなたの問題が、デフォルトのフレームバッファによって実行される MSAA 解決を使用してのみ表示される理由はわかりません。しかし、サンプル シェーディングが役立つはずです。

CSAA に関しては、非拡張 GL が制御できる範囲外です。バニラ GL パイプラインのどこにも CSAA の概念はありません。NV_framebuffer_multisample_coverageただし、NV の拡張機能を使用する場合は、FBO を使用して実装できます。

正直に言うと、最近はほぼ常に FBO ベースのアンチエイリアシングを優先しています。これを行う場合、エンド ユーザーが AA 設定を変更するためにレンダー コンテキストを再作成する必要はありません。つまり、ユーザーがパフォーマンス/画質の構成設定を試し始めた場合に、リソースの再読み込みが大幅に少なくなります。これははるかに柔軟な設計であり、マルチサンプル テクスチャ フェッチのおかげで、最新のハードウェアで FBO を使用して MSAA ディファード シェーディングを実行することもできます (シェーダー レベルでリゾルブを実装できます)。

コンテキスト ベースの CSAA と FBO ベースの CSAA の間に違いがあったかどうか、またはシェーディング サンプルの最小数を明示的に設定すると何らかの影響があるかどうかを知りたいです。

于 2014-02-04T18:27:36.147 に答える