3

Ok。それで、私は先週、自分のゲーム エンジンで影をいじっていました。私は主にカスケード シャドウ マップ (CSM) を実装しましたが、解決できないように見えるシャドウイングに少し問題があります。

このシーンの唯一のライトはディレクショナル ライト (太陽) で、{-0.1 -0.25 -0.65} を指しています。次のコードを使用して、CSM の 4 つの分割に対して 4 セットの錐台境界を計算します。

// each projection matrix calculated with same near plane, different far
Frustum make_worldFrustum(const glm::mat4& _invProjView) {
    Frustum fr; glm::vec4 temp;
    temp = _invProjView * glm::vec4(-1, -1, -1, 1);
    fr.xyz = glm::vec3(temp) / temp.w;
    temp = _invProjView * glm::vec4(-1, -1,  1, 1);
    fr.xyZ = glm::vec3(temp) / temp.w;
    ...etc 6 more times for ndc cube
    return fr;
}

ライトの場合、次のようなビュー マトリックスを取得します。

glm::mat4 viewMat = glm::lookAt(cam.pos, cam.pos + lightDir, {0,0,1});

次に、各錐台の境界から各オルソ マトリックスを作成します。

lightMatVec.clear();
for (auto& frus : cam.frusVec) {
    glm::vec3 arr[8] {
        glm::vec3(viewMat * glm::vec4(frus.xyz, 1)),
        glm::vec3(viewMat * glm::vec4(frus.xyZ, 1)),
        etc...
    };

    glm::vec3 minO = {INFINITY, INFINITY, INFINITY};
    glm::vec3 maxO = {-INFINITY, -INFINITY, -INFINITY};
    for (auto& vec : arr) {
        minO = glm::min(minO, vec);
        maxO = glm::max(maxO, vec);
    }

    glm::mat4 projMat = glm::ortho(minO.x, maxO.x, minO.y, maxO.y, minO.z, maxO.z);
    lightMatVec.push_back(projMat * viewMat);
}

非常に単純な頂点シェーダー (フラグ無効またはパンチスルー アルファ) を使用してシーンを描画する 4 つのフレームバッファーにバインドされた 4 レイヤーの TEXTURE_2D_ARRAY があります。

その後、最後のシーンを描きます。頂点シェーダーは、4 つのシャドウ texcoords を出力します。

out vec3 slShadcrd[4];
// stuff
for (int i = 0; i < 4; i++) {
    vec4 sc = WorldBlock.skylMatArr[i] * vec4(world_pos, 1);
    slShadcrd[i] = sc.xyz / sc.w * 0.5f + 0.5f;
}

そして、使用する分割を決定するフラグメント シェーダー:

int csmIndex = 0;
for (uint i = 0u; i < CameraBlock.csmCnt; i++) {
    if (-view_pos.z > CameraBlock.csmSplits[i]) index++;
    else break;
}

そして、この関数でシャドウ マップ配列をサンプリングします。

float sample_shadow(vec3 _sc, int _csmIndex, sampler2DArrayShadow _tex) {
    return texture(_tex, vec4(_sc.xy, _csmIndex, _sc.z)).r;
}

そして、これが私が得たシーンです (各分割がわずかに着色され、4 つの深度レイヤーがオーバーレイされています) 格好良い 。いいね。

しかし、カメラを少し右に向けると、 見栄えがよくない 影が消え始めます (角度によっては、影があるべきでない場所に現れます)。

GL_DEPTH_CLAMP を有効にしているので、それは問題ではありません。私は前面をカリングしていますが、それをオフにしてもこの問題に違いはありません。

私は何が欠けていますか?私の予測の 1 つに問題があるように感じますが、それらはすべて私には正しく見えます。ありがとう!

編集: 描画されたライトの錐台の 4 つすべて。それらはすべてそこにありますが、カメラに対して相対的に変化しているのは z だけです (以下のコメントを参照)。光錐台

編集: おそらくもっと便利です。これは、カメラが (0,0,0) にあり、前方 (0,1,0) を指しているときに、一度だけ更新したときに視錐台がどのように見えるかです。今回もデプステストで描きました。 別の場所からのフラスタム

重要な編集: この問題は、現在、ライトのビュー マトリックスに直接関連しているようです。

glm::mat4 viewMat = glm::lookAt(cam.pos, cam.pos + lightDir, {0,0,1});

目とターゲットの値を変更すると、バグのある影に影響するようです。しかし、実際にこれを何に設定すればよいかわかりませんか?私よりも理解している人にとっては簡単なはずです:D

4

1 に答える 1