4

3D レンダラーで影を安定させようとしています。CSMを使用しています。

これが私が手に入れたコードで、安定化を試みていません。ただし、ワールド空間での投影のサイズは少なくとも一定である必要があります。

void SkyLight::update() {
    // direction is the direction that the light is facing
    vec3 tangent = sq::make_tangent(direction);

    for (int i = 0; i < 4; i++) {
        // .first is the far plane, .second is a struct of 8 vec3 making a world space camera frustum
        const std::pair<float, sq::Frustum>& csm = camera->csmArr[i];

        // calculates the bounding box centre of the frustum
        vec3 frusCentre = sq::calc_frusCentre(csm.second);

        mat4 viewMat = glm::lookAt(frusCentre-direction, frusCentre, tangent);
        mat4 projMat = glm::ortho(-csm.first, csm.first, -csm.first, csm.first, -csm.first, csm.first);
        matArr[i] = projMat * viewMat;
    }
}

それはうまくいきます。しかし、影はちらつき、狂ったように泳いでいます。したがって、どこでも推奨されているように見えますが、説明されていないように見えるように、テクセルサイズの増分にスナップしようとすることで、安定化を試みます。

void SkyLight::update() {
    vec3 tangent = sq::make_tangent(direction);

    for (int i = 0; i < 4; i++) {
        const std::pair<float, sq::Frustum>& csm = camera->csmArr[i];

        vec3 frusCentre = sq::calc_frusCentre(csm.second);

        double qStep = csm.first / 1024.0; // shadow texture size
        frusCentre.x = std::round(frusCentre.x / qStep) * qStep;
        frusCentre.y = std::round(frusCentre.y / qStep) * qStep;
        frusCentre.z = std::round(frusCentre.z / qStep) * qStep;

        mat4 viewMat = glm::lookAt(frusCentre-direction, frusCentre, tangent);
        mat4 projMat = glm::ortho(-csm.first, csm.first, -csm.first, csm.first, -csm.first, csm.first);
        matArr[i] = projMat * viewMat;
    }
}

これは、パターンに気付かないほど速くバウンスするのではなく、影がゆっくりと泳ぐという点で違いを生みます。しかし、それはたまたまのことであり、正しいものにまったくスナップしていないこと、または正しいものにスナップしていないことは確かです。

4

1 に答える 1

4

これを修正するには、ワールド空間ではなく、ライト空間でスナップを行う必要があります。

viewMat[3][0] -= glm::mod(viewMat[3][0], 2.f * split / texSize);
viewMat[3][1] -= glm::mod(viewMat[3][1], 2.f * split / texSize);
viewMat[3][2] -= glm::mod(viewMat[3][2], 2.f * split / texSize);

古い(間違った)答え:

それで、今日これを再訪し、約10分で解決することができました:D

frusCentre を次のように丸めます。

frusCentre -= glm::mod(frusCentre, 2.f * csm.first / 1024.f);

または、より一般的に:

frusCentre -= glm::mod(frusCentre, 2.f * split / texSize);

編集: いいえ、それはだめです.私は努力を続けます.

于 2015-05-03T08:24:16.657 に答える