3

私はOpenGLを使用してゲームを作成しており、シャドウボリュームを実装しようとしています。

頂点シェーダーを介してGPU上にモデルのシャドウボリュームを構築したいと思います。そのために、モデルをVBOで表します。

  • 各三角形が独自の3つの頂点を持つように、頂点が複製されます。
  • 各頂点には、その三角形の法線があります
    • 入らない理由で、とにかく上記の2つのポイントを実際にやっていたので、頂点の重複についてはあまり心配していません。
  • 縮退した三角形が追加され、「通常の」三角形の各ペア間のエッジの内側に四角形が形成されます。

このモデル形式を使用して、頂点シェーダー内で、ライトの反対側を向いている三角形の一部である頂点を見つけ、それらを後ろに移動してシャドウボリュームを形成することができます。

私が理解するために残したのは、後ろ向きの頂点に正確にどのような変換を適用する必要があるかです。

頂点がライトの反対側を向いていることを検出することはできますが、どの変換を適用する必要があるのか​​わかりません。これは私の頂点シェーダーがこれまでのように見えるものです:

uniform vec3 lightDir; // Parallel light.
                       // On the CPU this is represented in world
                       // space.  After setting the camera with
                       // gluLookAt, the light vector is multiplied by
                       // the inverse of the modelview matrix to get
                       // it into eye space (I think that's what I'm
                       // working in :P ) before getting passed to
                       // this shader.

void main()
{
    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
    vec3 realLightDir = normalize(lightDir);

    float dotprod = dot(eyeNormal, realLightDir);

    if (dotprod <= 0.0)
    {
        // Facing away from the light
        // Need to translate the vertex along the light vector to
        // stretch the model into a shadow volume

        //---------------------------------//
        // This is where I'm getting stuck //
        //---------------------------------//
        // All I know is that I'll probably turn realLightDir into a
        // vec4

        gl_Position = ???;
    }
    else
    {
        gl_Position = ftransform();
    }
}

単純にに設定gl_positionしてみましftransform() - (vec4(realLightDir, 1.0) * someConstant)たが、これにより、ある種の深度テストのバグが発生し(ボリュームをカラーでレンダリングすると、一部の面が他の面の後ろに見えるように見えました)someConstant、背面がどこまで伸びるかには影響しなかったようです。 。

更新-1月22日

私がおそらくどのスペースにいるかについての質問を明確にしたかっただけです。私がどのスペースにいるかを追跡することは、私のシェーダーの頭痛の最大の原因であると言わなければなりません。

シーンをレンダリングするとき、私は最初にを使用してカメラをセットアップしましたgluLookAt。カメラは固定されている場合もあれば、動き回っている場合もあります。それは問題ではないはずです。glTranslated次に、モデルを配置するなどの変換関数を使用します。

プログラム(つまりCPU上)では、世界空間(3つのフロート)で光ベクトルを表します。開発中に、この光ベクトルをシェーダーの適切なスペースに配置するには、カメラを設定した後、モデルを配置する前に、モデルビューマトリックスの逆数を掛ける必要があることがわかりました。したがって、私のプログラムコードは次のようになります。

  • ポジショニングカメラ(gluLookAt
  • ワールド空間にある光ベクトルを取得し、それを現在のモデルビューマトリックスの逆行列で乗算して、シェーダーに渡します。
  • 位置モデルへの変換
  • モデルの描画

これは何かを明確にしますか?

4

1 に答える 1

1

ftransform の結果はクリップ スペースにあります。したがって、これは realLightDir を適用したい空間ではありません。ライトがどの空間にあるかはわかりませんが (あなたのコメントは私を混乱させます)、確かなことは、同じ空間にあるベクトルを追加したいということです。

CPU では、これはワールド空間で表されます。gluLookAt でカメラを設定した後、このシェーダーに渡される前に、ライト ベクトルにモデルビュー マトリックスの逆数が乗算されて、目の空間に取り込まれます (これが私が作業しているものだと思います :P )。

ベクトルに mv 行列の逆数を掛けると、ビュー空間からモデル空間にベクトルがもたらされます。つまり、(ワールド空間での) 光ベクトルにビュー - >モデルを実行する変換が適用されていると言っているのです。私にはほとんど意味がありません。

4つのスペースがあります:

  • モデル空間: gl_Vertex が定義されている空間。
  • ワールド空間: GL が一般的に気にしない空間で、モデルを配置するための任意の空間を表します。通常、3D エンジンが動作する空間です (世界座標の一般的な理解にマップされます)。
  • ビュー空間: 見る人の指示に対応する空間。0,0,0 は、ビューアーが Z を見下ろす場所です。gl_Vertex にモデルビューを掛けて得られます。
  • クリップ スペース: マトリックス プロジェクションがもたらす魔法のスペース。 ftransform の結果はこのスペースにあります ( gl_ModelViewProjectionMatrix * gl_Vertex も同様です)。

光の方向がどの空間にあるかを正確に明確にできますか?

ただし、モデル、ワールド、またはビュー空間のいずれかでライト ベクトルを追加する必要があります。操作のすべてのビットを同じ空間に移動します。たとえば、モデル空間の場合、CPU のモデル空間で光の方向を計算し、次のことを行います。

vec3 vertexTemp = gl_Vertex + lightDirInModelSpace * someConst

次に、その新しい頂点位置をクリップ空間に持ち込むことができます

gl_Position = gl_ModelViewProjectionMatrix * vertexTemp

最後に、クリップ スペースでベクトルの追加を適用しようとしないでください。その時点では、必然的に不均一な wで同次座標を扱っているため、一般的には、あなたがすべきだと思うことはしません。

于 2010-01-22T09:30:47.967 に答える