3

我正在调试 SSAO 的问题并尝试可视化我的深度缓冲区。结果如下: 在此处输入图像描述 我将深度和法线存储在单个 16 位 RGBA 纹理中。这是我的深度通道着色器:

// Vertex shader
#version 150 core
#extension GL_ARB_explicit_attrib_location : enable

uniform mat4 _ViewMatrix;
uniform mat4 _ViewProjectionMatrix;
uniform mat4 modelMatrix;

layout (location = 0) in vec4 aPosition;
layout (location = 2) in vec3 aNormal;

out vec4 vPosition;
out vec3 vNormal;

void main()
{
    gl_Position = _ViewProjectionMatrix * modelMatrix * aPosition;

    mat4 modelViewMatrix = _ViewMatrix * modelMatrix;

    vPosition = modelViewMatrix * aPosition;
    vNormal = mat3( modelViewMatrix ) * aNormal;
}

// Fragment shader.
#version 150 core

// Calculated as 1.0 / (far - near)
uniform float uLinearDepthConstant;

in vec4 vPosition;
in vec3 vNormal;

out vec4 outDepthNormal;

void main()
{
    float linearDepth = -vPosition.z * uLinearDepthConstant;

    outDepthNormal = vec4( linearDepth, normalize( vNormal ) );
}

然后我在渲染纹理的着色器中可视化深度(我已经硬编码了近平面和远平面的距离):

void main()
{
    float depth = texture( depthNormalMap, vTexCoord ).r;
    fragColor = vec4((2.0 * 1.0) / (200.0 + 1.0 - depth * (200.0 - 1.0)));
}

结果应该看起来很顺利还是可能是什么问题?我正在创建这样的纹理:

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_HALF_FLOAT, 0 );
4

1 回答 1

1

如果考虑到实际上没有硬件提供 16 位浮点深度缓冲区这一事实,这看起来是正确的。

一些控制台(例如Xbox 360)公开了一个 24 位浮点深度缓冲区,但通常要进行可移植的操作,您必须使用 32 位深度缓冲区才能使其以浮点表示。如果您需要模板缓冲区和浮点深度缓冲区,这需要一个丑陋的 64 位打包深度 + 模板格式,这是 D3D 和 Xbox 360 中的 ATI 硬件提供 24 位浮点 + 的部分原因OpenGL 中不可用的 8 位深度 + 模板格式。如果 GL 有这个,它将被称为GL_DEPTH24F_STENCIL8.

现在,虽然 16 位浮点值不足以存储您的深度,但以这种格式存储您的法线可能会浪费空间/内存带宽。您应该尝试使用 RGBA 10:10:10:2(定点)或 RGB 11:11:10(浮点)之类的格式来存储您的法线(如果 RGBA8 实际上不够用),然后使用您保存的空间您可以负担得起 32 位浮点深度缓冲区。

就目前而言,您实际上并没有首先使用浮点深度缓冲区。您正试图将您的深度打包到一个 16 位每组件颜色缓冲区的一个通道中。如果您当前的解决方案没有切割它,我建议您使用实际深度附件并使用 24 位定点或 32 位深度图像格式。无论如何,您已经必须在正常渲染期间将某些内容输出到专用的深度缓冲区。

通过使用浮点格式来存储您的深度,您立即失去 1 位精度,因为它必须存储一个相当无意义的符号位(定点深度缓冲区没有)。此外,由于深度值通常已经在 0-1 范围内,因此浮点数的增强范围实际上并不适用。在 16 位上,通过以浮点格式存储深度,您失去的比获得的多。当您使用较少的位来存储深度时,定点深度确实是最好的方法。

于 2014-02-09T22:21:58.813 回答