opengl - glsl sampler2DShadow 和 shadow2D 说明

标签 opengl glsl shadow-mapping

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

  • 目标:我想使用延迟光照渲染我的场景
    和阴影贴图。
  • 奋斗:找到关于如何使用 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 .如果您使用 GL_LINEAR对您的深度纹理进行纹理过滤,然后 texture (...)将使用深度纹理中 4 个最接近的深度值执行 4 次深度比较,并返回一个介于 之间的值。 1.0 0.0 给出通过/失败的样本数量的概念。

    这是对阴影贴图进行硬件抗锯齿的正确方法。如果您尝试使用常规 sampler2DGL_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/

    相关文章:

    c++ - 沿 3d 曲线渲染圆

    c++ - 颜色类型 3 的 PNG 图像纹理格式

    c++ - opengl 3d 空间平面上的程序网格

    c++ - 级联阴影贴图无法按预期工作

    c++ - 使用立方体贴图在 Opengl-es 2.0 中进行阴影映射

    opengl - 现代 OpenGL 着色器应该如何编写才能相互兼容?

    c - GLUT不会画画

    opengl-es - 在 glsl es 2.0、Gamemaker Studio 2.0 中获取渐变方 block 的问题

    opengl - GLSL Gif 抖动效果 : Optimization

    opengl-es - 阴影映射 - 与光正交的薄壁上的伪影