在opengl阴影映射中存储纹理中的顶点深度信息



我目前正在编程阴影映射(级联阴影映射,准确地说)到我的c++ opengl引擎。因此,我想要一个包含光源和阴影贴图中每个像素之间距离的纹理。我应该使用哪种纹理类型?

我看到有一个GL_DEPTH_COMPONENT纹理内部格式,但它缩放数据,我想给纹理[0,1]。当我创建阴影贴图时,我是否应该反转我的长度,然后在我最终渲染时第二次得到真实的长度?看起来没什么用!

是否有一种方法可以使用纹理来存储长度而不反转它们2次?(一次是在纹理创建时,一次是在纹理使用时)。

我不确定你的意思是反转(我肯定你不能意味着反转距离,因为这将不起作用)。你要做的是将到光源的距离转换成[0,1]范围。

这可以通过为光源视图构建一个通常的投影矩阵并将其应用于阴影贴图构建通道中的顶点来完成。这样,它们到光源的距离被写入深度缓冲区(您可以通过glCopyTexSubImage或FBOs将纹理与GL_DEPTH_COMPONENT格式连接到该缓冲区)。在最后的过程中,你当然使用相同的投影矩阵来计算阴影贴图的纹理坐标,使用投影纹理(使用GLSL时使用sampler2DShadow采样器)。

但这种转换不是线性的,因为深度缓冲在观察者(或光源)附近具有更高的精度。另一个缺点是你必须知道距离值的有效范围(光源影响的最远点)。使用着色器(我假设你这样做),你可以通过将到光源的距离除以这个最大距离并手动将其分配给片段的深度值(GLSL中的gl_FragDepth)来进行线性转换,这就是你可能指的"反转"。

分割(和最大距离的知识)可以通过使用浮点纹理来防止光距离,只是将距离作为颜色通道写出来,然后在最后一关中自己执行深度比较(使用正常的sampler2D)。但是线性过滤浮点纹理只支持在较新的硬件上,我不确定这是否会比单个分割每个片段更快。但这种方法的优点是,它为"方差阴影地图"这样的东西打开了道路,这对普通的ubyte纹理(因为精度低)和深度纹理都不起作用。

综上所述,GL_DEPTH_COMPONENT只是ubyte纹理(缺乏必要的精度,因为GL_DEPTH_COMPONENT应该至少有16位精度)和float纹理(在旧硬件上不是那么快或完全支持)之间的一个很好的折衷。但是由于它的定点格式,您将无法绕过转换到[0,1]-范围(无论是线性还是射影)。我不确定浮点纹理是否会更快,因为你只需要一个除法,但如果你在最新的硬件上支持浮动纹理和1或2组件浮动纹理的线性(甚至三线性)过滤和渲染目标,它可能值得一试。

当然,如果你使用的是固定函数管道,你只有GL_DEPTH_COMPONENT作为一个选项,但关于你的问题,我假设你正在使用着色器。

最新更新