【问题标题】:Stable Shadow Mapping稳定的阴影贴图
【发布时间】:2015-04-10 09:21:02
【问题描述】:

我正在尝试稳定 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;
    }
}

这会有所不同,因为阴影现在游动得很慢,而不是弹跳得太快而无法注意到任何图案。但是,我很确定这只是偶然,而且我根本没有抓住正确的东西,甚至没有抓住正确的东西。

【问题讨论】:

    标签: c++ opengl shadow-mapping


    【解决方案1】:

    要解决这个问题,我需要在光照空间而不是世界空间中进行捕捉:

    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);
    

    编辑:不,那不好……我会继续努力的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 2015-06-22
      • 2013-04-21
      • 1970-01-01
      • 2016-02-03
      相关资源
      最近更新 更多