glsl sampler2DShadow和shadow2D澄清

Phi*_*ldo 9 opengl glsl shadow-mapping

我所在的快速背景(确保我们在同一页面上,如果我失踪/假设有些愚蠢的话,进行健全检查):

  • 目标:我想使用延迟光照和阴影贴图渲染阴影场景.
  • 奋斗:找到有关如何使用shadow2D和sampler2DShadow的清晰一致的文档.

这是我目前正在做的事情:

在我最终渲染过程的片段着色器(实际计算最终碎片值的那个)中,我从光源的角度来看传递的MVP矩阵,来自所述传递的深度纹理(又名"阴影贴图"),和我的几何缓冲区中的位置/法线/颜色纹理.

据我所知,我需要找到当前片段位置对应的阴影贴图的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;
Run Code Online (Sandbox Code Playgroud)

现在我已经拥有了这个紫外线,我可以从光的pov中获得深刻的"深度"

float depFromLightPOV = texture2D(shadowMap, UVinShadowMap).r;
Run Code Online (Sandbox Code Playgroud)

并将其与当前片段的位置与光线之间的距离进行比较:

float actualDistance = distance(texture2D(pos_tex, UV).xyz, lightPos);
Run Code Online (Sandbox Code Playgroud)

问题来自于"深度"存储在值0-1中,实际距离是世界坐标.我试图手动进行转换,但无法让它工作.在网上搜索,看起来像我应该这样做的方式是使用sampler2DShadow ......


所以这是我的问题:

我需要做什么改变才能使用shadow2D?shadow2D甚至做了什么?它只是或多或少的自动转换 - 从深度到世界的纹理?我可以使用相同的深度纹理吗?或者我需要以不同的方式渲染深度纹理?我将什么传递给shadow2D?我想检查片段的世界空间位置?或者和以前一样的紫外线?

如果所有这些问题都可以在一个简单的文档页面中得到解答,我很乐意,如果有人可以发布这个问题.但我发誓,我一直在寻找几个小时,找不到任何简单的说什么与shadow2D发生了什么!

谢谢!

And*_*man 43

首先,您使用的是什么版本的GLSL?

从GLSL 1.30开始,没有特殊的纹理查找功能(无论如何名称)可供使用sampler2DShadow.GLSL 1.30+使用一系列重载,texture (...)这些重载是根据sampler传递的类型和坐标的尺寸选择的.

其次,如果你使用,sampler2DShadow你需要做两件事:

  1. 必须启用纹理比较,否则将得到未定义的结果

    • GL_TEXTURE_COMPARE_MODE = GL_COMPARE_REF_TO_TEXTURE?

  2. 传递给的坐标texture (...)是3D而不是2D.新的第3个坐标是您要比较的深度值.

最后,您应该了解texture (...)使用时返回的内容sampler2DShadow:

如果此比较通过,texture (...)将返回1.0,如果失败则返回0.0.如果GL_LINEAR在深度纹理上使用纹理滤镜,则将texture (...)使用深度纹理中最近的4个深度值执行4次深度比较,并在介于 1.00.0 之间的某处返回一个值,以便了解传递的样本数/失败.

这是对阴影贴图进行硬件消除锯齿的正确方法.如果你试图用一个普通sampler2DGL_LINEAR和实施深度测试自己,你会得到一个平均深度背部和一个布尔通过/失败结果,而不是上面所描述的行为sampler2DShadow.


至于从世界空间位置获得深度值来测试,你是在正确的轨道上(虽然你忘了透视划分).

从世界空间位置生成深度必须做三件事:

  1. 通过(光)投影和视图矩阵乘以世界空间位置
  2. 将结果坐标除以其W组件
  3. 缩放并将结果(将在[-1,1]范围内)偏置到[0,1]范围内

最后一步假设您正在使用默认深度范围...如果您还没有调用,glDepthRange (...)那么这将起作用.

步骤3的最终结果作为两个深度值(R)和纹理坐标(ST),用于查找到您的深度图.这使得有可能通过这个值直接texture (...).回想一下,纹理坐标的前2个分量与始终相同,第3个是要测试的深度值.

  • 我知道我不应该只评论"谢谢你",但要认真 - 谢谢!我一直在为这个问题苦苦挣扎一个月,这篇帖子终于让我度过了萧条!清晰,简洁,所有在一个地方.辉煌.:) (8认同)
  • 为什么textureLod(sampler2DShadow)调用需要一个vec4作为p参数?我期待(uv、深度)...你用 vec4 做什么? (2认同)