我正在尝试稳定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;
}
}
这有所不同,因为阴影现在游得很慢,而不是弹跳太快而无法注意到任何模式。但是,我很确定这只是偶然的,而且我根本不会找到正确的东西,甚至不是正确的东西。
答案 0 :(得分:3)
要解决这个问题,我需要在光照空间进行捕捉,而不是世界空间:
length-1
旧(错)回答:
所以,我今天重新审视了这一点,并在大约10分钟内设法解决了这个问题:D
就像这样围绕着frusCentre:
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);
或者更一般地说:
frusCentre -= glm::mod(frusCentre, 2.f * csm.first / 1024.f);
编辑:不,那不好......我会继续努力。