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

时间:2011-07-19 18:02:39

标签: c++ opengl shadow

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

我看到有一个GL_DEPTH_COMPONENT纹理内部格式,但它会将我想要的纹理缩放到[0,1]。我在创建阴影贴图时是否应该反转长度,然后在最终渲染期间第二次反转实际长度?这似乎没用!

有没有办法使用纹理存储长度而不反转它们2次? (一次在纹理创建时,一次在使用期间)。

1 个答案:

答案 0 :(得分:4)

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

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

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

可以通过使用光点距离的浮点纹理并将距离作为颜色通道写出来然后自己在最终传递中执行深度比较来防止划分(以及最大距离的知识)(使用正常sampler2D)。但线性过滤浮点纹理仅在较新的硬件上受支持,我不确定这是否比每个片段的单个分区更快。但是这种方式的优势在于,这为“方差阴影贴图”开辟了道路,这对于普通的ubyte纹理效果不佳(因为精度低),深度纹理也没有。

总而言之,GL_DEPTH_COMPONENT只是ubyte纹理(缺少必要的精度,因为GL_DEPTH_COMPONENT应该至少具有16位精度)和浮动纹理(不是那么快)之间的良好折衷或者在旧硬件上完全支持)。但是由于它的定点格式,你不会绕过[0,1] - 范围的变换(无论是线性的投影)。我不确定浮点纹理是否会更快,因为你只需要一个分区,但如果你在最新的硬件上支持浮动纹理和1或2个组件浮动纹理和渲染目标的线性(甚至三线性)过滤,值得一试。

当然,如果您使用的是固定功能管道,则只有GL_DEPTH_COMPONENT作为选项,但对于您的问题,我假设您使用的是着色器。