级联阴影贴图不太正确

贾戈利

好的。因此,上周我一直在游戏引擎中摸索阴影。我主要实现了级联阴影贴图(CSM),但是阴影方面存在一些我似乎无法解决的问题。

该场景中唯一的光是指向{-0.1 -0.25 -0.65}的定向光(太阳)。我使用以下代码为我的CSM的四个分割计算了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,我可以使用一个非常简单的顶点着色器(禁用片段或穿透Alpha)将场景绘制到其中。

然后,我绘制最终场景。顶点着色器输出四个阴影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,所以这不是问题。我正在筛选正面,但是将其关闭对这个问题没有影响。

我想念什么?我觉得这是我的一个预测问题,但对我来说,它们都不错。谢谢!

编辑:绘制了所有四个光的视锥。它们都在那里,但只有z相对于相机改变(请参阅下面的评论):轻的平截头体

编辑:可能更有用,这是当我仅更新一次视锥,相机处于(0,0,0)并指向前方(0,1,0)时的样子。我这次也用深度测试来吸引他们。来自其他地方的视锥

重要编辑:看来这个问题与灯光的视图矩阵直接相关,目前:

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

更改眼睛和目标的值似乎会影响阴影。但我不知道该将其设置为什么?对比我有更好理解的人应该很容易:D

贾戈利

解决了!确实是光源的视点矩阵存在问题!我要做的就是用camPos每个视锥的中心点代替这意味着每个拆分的光矩阵需要一个不同的视图矩阵。所以我只是像这样创建每个视图矩阵...

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

并简单地获取frusCentre ...

glm::vec3 calc_frusCentre(const Frustum& _frus) {
    glm::vec3 min(INFINITY, INFINITY, INFINITY);
    glm::vec3 max(-INFINITY, -INFINITY, -INFINITY);
    for (auto& vec : {_frus.xyz, _frus.xyZ, _frus.xYz, _frus.xYZ,
                      _frus.Xyz, _frus.XyZ, _frus.XYz, _frus.XYZ}) {
        min = glm::min(min, vec);
        max = glm::max(max, vec);
    }
    return (min + max) / 2.f;
}

和ba!一切正常!

编辑(最后一个!):我当时做的不太正确。视图矩阵实际上应该是:

glm::lookAt(frusCentre-lightDir, frusCentre, {0,0,1});

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

R regex不太正确

来自分类Dev

JSONArray中的JSONObject不太正确

来自分类Dev

JSONArray中的JSONObject不太正确

来自分类Dev

级联阴影贴图无法正常工作

来自分类Dev

php中我的array_diff不太正确

来自分类Dev

View.setEnabled(false)在android中不太正确

来自分类Dev

Python中的Kruskels MST算法似乎不太正确

来自分类Dev

循环不太正常的java

来自分类Dev

我的VBA更改文件夹名称不太正确,我缺少什么?

来自分类Dev

安装并删除Kubuntu Desktop-现在Ubuntu / Unity看起来不太正确

来自分类Dev

在全新的笔记本电脑中字体看起来不太正确。请帮忙

来自分类Dev

如何正确制作用于阴影贴图的深度立方体贴图?

来自分类Dev

阴影贴图工件

来自分类Dev

OpenGL中的阴影贴图

来自分类Dev

opengl-es 2.0正常对我来说不太正常

来自分类Dev

GLSL 1.20阴影贴图,使阴影变形

来自分类Dev

OpenGL阴影贴图-阴影位置错误

来自分类Dev

阴影贴图和深度值混淆

来自分类Dev

OpenGL阴影贴图几乎可以正常工作

来自分类Dev

OpenGL Variance阴影贴图倒置衰减

来自分类Dev

具有延迟渲染的阴影贴图

来自分类Dev

阴影贴图的位置和分辨率

来自分类Dev

巴比伦JS中的阴影贴图

来自分类Dev

阴影贴图和深度值混淆

来自分类Dev

如何使用phong阴影实现凹凸贴图

来自分类Dev

聚光灯阴影贴图的计算偏差

来自分类Dev

SSAO 和阴影贴图 | 阴影不适用于 SSAO

来自分类Dev

阴影贴图-将视图空间位置转换为阴影贴图空间

来自分类Dev

阴影贴图:整个网格都在阴影中,根据深度贴图应该没有光线的地方