【发布时间】:2016-12-22 01:07:59
【问题描述】:
所以在过去的一周里,我一直在尝试围绕 OpenGL 中的阴影贴图进行研究,但进展并不顺利。所以我希望这里有人可以帮助我。 我一直在学习使用正向渲染的 LearnOpenGL 的阴影映射教程中的阴影映射,从我收集的内容来看,似乎带有延迟的阴影映射有点不同。 首先是我的阴影贴图:
由于某种原因它是红色的,但据一位朋友说,这显然是可以的。但我仍然觉得我已经做错了什么。但假设不是,阴影贴图被正确渲染并到达延迟渲染的光照通道,没有任何问题。我还发送了一个缓冲区,其中包含我使用光空间变换矩阵转换的光空间中的所有片段。
//Create LSMatrix
GLfloat near_plane = 1.0f;
GLfloat far_plane = 10.0f;
glm::mat4 lightProjMat = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
glm::mat4 lightPerspective = glm::lookAt(glm::vec3(-2.0f, 6.0f, -1.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
shadowBuf.lightSpaceMat = lightProjMat * lightPerspective;
我现在没有定向灯,只有两个点灯。所以使用正交投影和所有这些都会给我一个不正确的阴影。但还是有阴影的。现在阴影从哪里来并不重要,我只想学习。然后我可以担心如何让它与光源匹配。
这里它被用在几何通道的 GLSL 顶点着色器中。 (LSMat)
void main()
{
gl_Position = vec4(position, 1.0f);
vs_out.uv = uv;
vs_out.normal = normal;
vs_out.FragPos = vec3(model * vec4(position, 1.0f));
vs_out.FragPosLS = LSMat * vec4(vs_out.FragPos, 1.0f); //Fragment position in light space
}
然后在片段着色器中将其保存到纹理并传送到光照通道。
所以现在我拥有了在光照通道中进行阴影计算所需的一切。 (希望至少)
这是我在光照通道中进行阴影计算的片段着色器部分:
float shadowCalc()
{
vec4 fragPosLS = texture(gFragPosLS, uvs); //Fetch the lightspace frag pos from the texture
vec3 projCoords = fragPosLS.xyz / fragPosLS.w; //Manually do perspective divison
projCoords = projCoords * 0.5 + 0.5; //Get the pos in [0,1] range
float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
return shadow;
}
最后我在漫反射和镜面反射值上使用了这个阴影值:
float shadowValue = shadowCalc();
diffuse = diffuse * (1.0 - shadowValue);
specular = specular * (1.0 - shadowValue);
return ((diffuse * vec4(gColor, 1.0f)) + specular + ambient);
然后我像往常一样输出结果颜色,结果是这样的:
糟糕的纹理只是我现在没有在 Maya 中使用 UV 贴图的结果。但除此之外,你可以清楚地看到它是一团糟。我什至尝试禁用其中一盏灯以确保它不会损坏,因为我有两盏灯在执行 shadowCalc 功能,但事实并非如此。但我不是 100% 确定这一点。
如果有人对为什么会发生这种情况有任何想法,那么我会全力以赴。一个星期以来我一直很困惑,我似乎无法弄清楚为什么会发生这种情况。我只知道当我使用阴影偏置时,地面上的条纹消失了,但金字塔后面的巨大阴影仍然存在。它不仅看起来很糟糕,而且如果将它与渲染阴影贴图的角度进行比较,它还指向完全错误的方向。所以它必须与坐标有关。我读过一些关于延迟渲染如何要求您以不同方式做一些事情的文章,但我还没有设法得到正确的答案。
这已经是一个非常庞大的帖子,但如果我忘记展示任何可能澄清问题的内容,那么请告诉。
【问题讨论】:
-
Grimm Shadowmapping?
-
没有讨论你的位置纹理(你应该考虑在未来通过使用重建来优化)是如何编码的。您已将用于对深度纹理进行采样的纹理坐标缩放为 [0.0, 1.0],但我不知道您的位置缓冲区。除非它是浮点数,否则您的位置既不规范也不保证为正的事实可能是一个非常大的问题。
-
您只从深度图中读取红色值,您确定在深度通道上正确地将值写入红色组件吗?您正在从 z 组件读取 currentDepth,您能否发布这些代码,以便我们检查其余代码。否则,我觉得很好
-
请在初始化深度图格式的地方添加代码。你在使用单通道缓冲区吗?
-
@codetiger:深度纹理只有一个组件,考虑到 GLSL 1.30+ 的行为,您可以调整任何您想要的组件,并且会得到相同的结果。
标签: opengl glsl rendering shader shadow-mapping