1

クローズド ソースの 3D アプリケーションである Maya 内で実行されるプラグインの一部として GLSL プログラムを作成しています。私のプラグインは、カスタム ジオメトリを、アプリケーションがレンダリングするデフォルトのポリゴン ジオメトリと同じイメージ バッファにレンダリングします。アプリケーションはライティングとシェーディングに OpenGL 固定パイプラインを使用しますが、私は GLSL を使用してカスタム ジオメトリとマテリアルをレンダリングしています。

私の問題は、シェーダーで固定パイプライン ライトの動作を模倣したいということです。アプリケーションは均一にライトを定義しgl_LightSourceます。アプリケーションのデフォルトのポリゴン ジオメトリに割り当てられたときと同じカスタム ジオメトリに割り当てられたときに、同じ方向、強度などを持つようにします。

フィールドは明確に文書化されgl_LightSourceていますが、固定パイプラインがそれらのフィールドをどのように解釈するかについての決定的な文書は見つかりません。GLSL でポイント/ディレクショナル/スポット ライトをコーディングする方法の例は多数ありますが、固定パイプラインを正確に模倣しているようには見えません。たとえば、アプリケーションがそれらの組み合わせを定義している場合、ライトがポイント ライト、ディレクショナル ライト、スポット ライトのいずれであるかをどのように判断しますか? シェーダーに過度の分岐を導入することなく、ライト タイプの混合を処理できますか?

要するに、固定関数パイプラインがどのように評価されるかについての決定的なドキュメントまたは例はありますgl_LightSourceか?

4

3 に答える 3

2

私の問題は、フラグメント シェーダーで固定パイプライン ライトの動作を模倣したいということです。

「固定パイプラインライト」はフラグメントごとではなく頂点プロセッサに実装されているため、最初の問題があります。

要するに、固定関数パイプラインが gl_LightSource を評価する方法の決定的なドキュメントまたは例はありますか?

はい。それは「The OpenGL Graphics System: A Specification」と呼ばれています。OpenGL Registryからダウンロードできます。互換性プロファイルが必要です。4.2 互換性仕様のセクション 2.13 は、照明に使用されるすべての計算をカバーしています。それをGLSLコードに変換するだけです。

固定機能パイプラインを正確に模倣することはできないことに注意してください。つまり、シェーダーベースの照明と固定関数の照明の間の不変性を保証する方法はありません。近い値が得られますが、バイナリと同一の値は得られません。

シェーダーに過度の分岐を導入することなく、ライト タイプの混合を処理できますか?

「過剰」をどのように定義しますか?OpenGL の照明方程式には条件付きロジックが含まれているため、分岐する必要があります。

これが、人々がGL のライティングをシェーダーに再実装するだけではない理由の一部です。データ駆動型のアプローチを使用するのではなく、GLSL を記述するだけで、はるかに効率的になります。

于 2012-06-26T18:33:01.487 に答える
1

OpenGL ES 2.0 プログラミング ガイドには、固定関数パイプラインを実装する頂点シェーダーの完全なソース コードがあります。(固定関数パイプラインは頂点ごとのライティングのみであるため、ライティングの計算にフラグメント シェーダーは必要ないことに注意してください。)

固定関数モードの場合、OpenGL ドライバーはこの頂点シェーダーを内部的に使用していると思います。この本の第 8 章、頂点シェーダーを参照してください。

次のプロパティを持つライトの構造体を定義します。

  1. 位置、
  2. 周囲の色、
  3. 拡散色、
  4. スペキュラーカラー、
  5. スポット方向、
  6. 減衰係数 (定数、線形、四次)、
  7. スポット指数、
  8. スポット カットオフ角度、
  9. ComputeDistanceAttanuation (ブール値)

そして、各ライトは関数lighting_equation()で処理されます。

于 2012-06-27T23:59:29.443 に答える
0

OpenGL仕様ドキュメントに基づいて私が思いついたものは次のとおりです。

#version 410 compatibility

vec3 incedentLight (in gl_LightSourceParameters light, in vec3 position)
{
    if (light.position.w == 0) {
        return normalize (-light.position.xyz);
    } else {
        vec3 offset = position - light.position.xyz;
        float distance = length (offset);
        vec3 direction = normalize (offset);
        float intensity;
        if (light.spotCutoff <= 90.) {
            float spotCos = dot (direction, normalize (light.spotDirection));
            intensity = pow (spotCos, light.spotExponent) *
                    step (light.spotCosCutoff, spotCos);
        } else {
            intensity = 1.;
        }
        intensity /= light.constantAttenuation +
                light.linearAttenuation * distance +
                light.quadraticAttenuation * distance * distance;
        return intensity * direction;
    }
}

GLSLについて私が理解していることから、分岐は均一変数にのみ依存するため、かなり効率的であるはずです。

于 2012-07-05T20:06:48.147 に答える