3

スポット ライトのシャドウ マッピングを管理する 3D アプリケーションをコーディングしました。これを行うには、従来のシャドウ マッピング手法を使用します (最初のレンダー パスで深度テクスチャを塗りつぶし、2 番目のレンダー パスで、ライトから最初のオクルーダーまでの距離とライトから頂点位置までの距離を比較して、フラグメントが影にあるかどうか)。

スクリーンショットを次に示します (スポット ライト/2D 深度テクスチャ シャドウ マッピング)。

ここに画像の説明を入力

この例では、関数「textureProjOffset」を使用して PCF シャドウ マッピング手法を使用します。私のフラグメントシェーダーのコードは次のとおりです。

使用したサンプラー:

sampler2DShadow Shadow2DSampler[MAX_LIGHTS_COUNT];

ハード シャドウの場合:

shadowFactor = textureProj(Shadow2DSampler[idx], ShadowCoords[idx]);

PCF ソフト シャドウの場合:

for (int idy = offset; idy >= -offset; idy--)
                for (int idx = -offset; idx <= offset; idx++)
                    shadowFactor += textureProjOffset(
                        Shadow2DSampler[idz], ShadowCoords[idz], ivec2(idx, idy)); 

また、ポイント ライトに現在適用されている全方向シャドウ マッピングを管理するために、基本的なキューブマップ シャドウ マッピングも管理しました。最初のレンダー パスでこれを行うには、ジオメトリ シェーダーを使用して、6 つのシャドウ錐台によって提供される投影マトリックスとビュー マトリックスの両方をディスパッチします (すべて 1 つのパスで! 今回は 6 つのレンダリング ステートで 6 つの別個のテクスチャを埋めるためのテクニックとは異なります) )。

スクリーンショットは次のとおりです (スポット ライト/キューブ深度テクスチャ シャドウ マッピング)。

ここに画像の説明を入力

ご覧のとおり、ハード シャドウ マッピングのみです。キューブマップにエンコードされた深度値を復元するには、今回は関数 'texture' を使用する必要があります ('samplerCube' と 'samplerCubeShadow' には textureProj は存在しません)。次に、ワールド空間でのライト位置と頂点位置の間の距離を計算し、それをクリップ空間に変換する必要があります。これは、テクスチャに含まれる深度値が既にクリップ空間にあるためです。

プロセスを確認するためのフラグメント シェーダーのコードを次に示します。

使用したサンプラー:

samplerCubeShadow ShadowCubeSampler[MAX_LIGHTS_COUNT];

ハード シャドウの場合:

float ConvertDistToClipSpace(vec3 lightDir_ws)
{
    vec3 AbsVec = abs(lightDir_ws);
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));

    float NormZComp = (NearFar.y + NearFar.x)/(NearFar.y - NearFar.x)
        - (2.0f * NearFar.y * NearFar.x)/(LocalZcomp * NearFar.y - NearFar.x);

    return ((NormZComp + 1) * 0.5f);
}

float GetBiased_Cube_Hard_ShadowFactor(vec3 vertexPosition_ws, int idx)
{
    vec3 lightToVertexDir_ws = vertexPosition_ws - LightPos_ws.xyz;
    float LightToVertexClipDist = ConvertDistToClipSpace(lightToVertexDir_ws);

    float LightToOccluderClipDist = texture(
        ShadowCubeSampler[idx], vec4(lightToVertexDir_ws, LightToVertexClipDist));

    if (LightToOccluderClipDist < LightToVertexClipDist)
        return (0.0f);
    return (1.0f);
}

そして、 cubemap を使用した PCF SOFT シャドウはどうですか? 私はいくつかの調査を行いましたが、単純な 2D テクスチャを使用し、フラグメント シェーダーでキーワード「sampler2DShadow」を使用して可能なように、テクスチャ オフセットを回復する関数は明らかに存在しません。私が間違っている ?(そうだといい!)。

私は解決策を持っていると思います(もちろん、キューブマップを使用した解決策が存在しない場合):

どうやら、テクスチャ オフセットを回復するには、6 つの個別のテクスチャを使用する必要があります (したがって、「samplerCubeShadow」ではなく、サイズが 6 の「sampler2DShadow」の配列)。したがって、最初のケースでスポット ライト シャドウ マッピングで行ったように、ライト空間での世界の表現を表す matrix4x4 の配列を均等に均一にします。そして、6 つのテクスチャに対してメソッド「textureProjOffset」を使用します。

それで、あなたはどう思いますか?キューブマップを使用して PCF ソフト シャドウを作成することは可能ですか? そうでない場合、私の解決策は正しいですか? 「samplerCube」または「samplerCubeShadow」を使用して「textureProjOffset」のような関数を使用することは可能ですか? または、代替手段はありますか?

ご協力いただきありがとうございます。

4

1 に答える 1

3

キューブマップの PCF ソフト シャドウを実現する唯一の方法は、小さなオフセットでテクスチャを複数回クエリすることです。この方法は、たとえば、このGPU Gems の記事 (12.4)で説明されています。

于 2014-09-28T16:19:40.293 に答える