0

我试图减少我必须在场景中绘制的后期处理纹理的数量。最终目标是支持 SSAO 着色器。着色器需要深度、位置和法线数据。目前,我将深度和法线存储在 1 个浮动纹理中,并将位置存储在另一个中。

我一直在做一些阅读,您似乎可以通过简单地使用存储在正常纹理中的深度来获得位置。您必须取消投影 x 和 y 并将其乘以深度值。然而,我似乎无法做到这一点,这可能是由于我缺乏理解......

所以目前我的位置被绘制到位置纹理。这就是它的样子(目前工作正常) 将位置绘制到纹理

我的新方法也是如此。我传递了在 RGB 通道中存储法线 x、y 和 z 以及在 w 中存储深度的法线纹理。在 SSAO 着色器中,我需要获取位置,所以我就是这样做的:

//viewport is a vec2 of the viewport width and height
//invProj is a mat4 using camera.projectionMatrixInverse (camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );)

vec3 get_eye_normal()
{
    vec2 frag_coord = gl_FragCoord.xy/viewport;
    frag_coord = (frag_coord-0.5)*2.0;
    vec4 device_normal = vec4(frag_coord, 0.0, 1.0);
    return normalize((invProj * device_normal).xyz);
}

...

float srcDepth = texture2D(tNormalsTex, vUv).w;
vec3 eye_ray = get_eye_normal();
vec3 srcPosition = vec3( eye_ray.x * srcDepth , eye_ray.y * srcDepth , eye_ray.z * srcDepth );

//Previously was doing this:
//vec3 srcPosition = texture2D(tPositionTex, vUv).xyz;

但是,当我渲染位置时,它看起来像这样:

不一样 - 导致问题

使用新方法的 SSAO 看起来非常混乱。任何帮助将不胜感激。

4

1 回答 1

0

我能够找到解决方案。您需要将光线法线乘以相机远 - 近(我使用的是标准化深度值 - 但您需要世界深度值。)

我创建了一个函数来从法线/深度纹理中提取位置,如下所示:

首先在深度捕获通道(片段着色器)

float ld = length(vPosition) / linearDepth; //linearDepth is cam.far - cam.near
gl_FragColor = vec4( normalize( vNormal ).xyz, ld );

现在在着色器中试图提取位置......

/// <summary>
/// This function will get the 3d world position from the Normal texture containing depth in its w component
/// <summary>
vec3 get_world_pos( vec2 uv )
{
    vec2 frag_coord = uv;   
    float depth = texture2D(tNormals, frag_coord).w;    
    float unprojDepth = depth * linearDepth - 1.0;      
    frag_coord = (frag_coord-0.5)*2.0;
    vec4 device_normal = vec4(frag_coord, 0.0, 1.0);
    vec3 eye_ray = normalize((invProj * device_normal).xyz);
    vec3 pos = vec3( eye_ray.x * unprojDepth, eye_ray.y * unprojDepth, eye_ray.z * unprojDepth );
    return pos;
}
于 2013-09-13T13:17:40.753 回答