我所在位置的快速背景(以确保我们在同一页面上,并检查我是否遗漏/假设一些愚蠢的事情):

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

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

    在我的最终渲染 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 的行为。

    至于从世界空间位置获取深度值进行测试,您走在正确的轨道上(尽管您忘记了透视划分)。

    要从世界空间位置生成深度,您必须做三件事:
  • 将世界空间位置乘以您的(光的)投影和 View 矩阵
  • 将结果坐标除以它的 W 分量
  • 将结果(将在 [-1,1] 范围内)缩放并偏置到 [0,1] 范围内

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

    步骤3的最终结果作为一个深度值(R)和纹理坐标(ST),用于查找到您的深度图。这使得可以将这个值 直接传递给 texture (...) 。回想一下,纹理坐标的前 2 个分量和往常一样,第三个是要测试的深度值。

    关于opengl - glsl sampler2DShadow 和 shadow2D 说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22419682/

    10-13 06:54