我所在位置的快速背景(以确保我们在同一页面上,并检查我是否遗漏/假设一些愚蠢的事情):
和阴影贴图。
这是我目前正在做的事情:
在我的最终渲染 channel 的片段着色器(实际计算最终片段值的那个)中,我有来自灯光视角的 channel 的 MVP 矩阵,来自所述 channel 的深度纹理(又名“阴影贴图”),以及来自我的几何缓冲区的位置/法线/颜色纹理。
据我了解,我需要找到当前片段的位置对应的阴影贴图的UV。我通过以下方式做到这一点:
//Bring position value at fragment (in world space) to screen space from lights POV
vec4 UVinShadowMap = (lightProjMat * lightViewMat * vec4(texture(pos_tex, UV).xyz,1.0)).xy;
//Convert screen space to 'texture space' (from -1to1 to 0to1)
UVinShadowMap = (UVinShadowMap+1)/2;
现在我有了这个 UV,我可以从光的 pov 中获得感知的“深度”
float depFromLightPOV = texture2D(shadowMap, UVinShadowMap).r;
并将其与当前片段的位置与灯光之间的距离进行比较:
float actualDistance = distance(texture2D(pos_tex, UV).xyz, lightPos);
问题来自于“深度”存储在值 0-1 中,而实际距离在世界坐标中。我尝试手动进行该转换,但无法使其正常工作。在网上搜索时,看起来我应该这样做的方式是使用 sampler2DShadow ...
所以这是我的问题:
我需要做哪些更改才能使用 shadow2D? shadow2D 甚至可以做什么?它或多或少是从深度到世界的自动转换纹理吗?我可以使用相同的深度纹理吗?或者我是否需要以不同的方式渲染深度纹理?我传递给 shadow2D 的是什么?我要检查的片段的世界空间位置?还是和以前一样的紫外线?
如果所有这些问题都可以在一个简单的文档页面中得到解答,我希望有人能发布它。但是我发誓我已经搜索了几个小时,找不到任何可以简单说明 shadow2D 到底发生了什么的东西!
谢谢!
最佳答案
首先,您使用的是什么版本的 GLSL?
从 GLSL 1.30 开始,没有与 sampler2DShadow
一起使用的特殊纹理查找函数(无论如何都是名称)。 GLSL 1.30+ 使用了一堆 texture (...)
的重载,这些重载是根据传递的 sampler
的类型和坐标尺寸选择的。
其次,如果您确实使用 sampler2DShadow
,则需要以不同的方式做两件事:
GL_TEXTURE_COMPARE_MODE
= GL_COMPARE_REF_TO_TEXTURE
texture (...)
的坐标是 3D 而不是 2D。新的第三个坐标是您要比较的深度值。 最后,您应该了解使用
texture (...)
时 sampler2DShadow
返回的内容:如果比较通过,
texture (...)
将返回 1.0 ,如果失败则返回 0.0 1192 0.0 19 19如果你对你的深度纹理使用GL_LINEAR
纹理过滤,然后texture (...)
会在你的深度纹理进行使用4个最接近的深度值4个的深度比较和返回-之间的值某处 1.0 和 0.0 给的一个想法通过/失败的样本数。这是对阴影贴图进行硬件抗锯齿的正确方法。如果您尝试使用带有
sampler2D
的常规 GL_LINEAR
并自己实现深度测试,您将获得单个平均深度返回和 bool 值通过/失败结果,而不是上述 sampler2DShadow
的行为。至于从世界空间位置获取深度值进行测试,您走在正确的轨道上(尽管您忘记了透视划分)。
要从世界空间位置生成深度,您必须做三件事:
W
分量 最后一步假设您使用的是默认深度范围...如果您还没有调用
glDepthRange (...)
那么这将起作用。步骤3的最终结果作为既一个深度值(
R
)和纹理坐标(ST
),用于查找到您的深度图。这使得可以将这个值 直接传递给 到 texture (...)
。回想一下,纹理坐标的前 2 个分量和往常一样,第三个是要测试的深度值。关于opengl - glsl sampler2DShadow 和 shadow2D 说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22419682/