从深度纹理获取位置

时间:2013-09-11 11:03:07

标签: three.js

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

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

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

我的新方法也是如此。我传递正常纹理,该纹理存储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;

然而,当我渲染出位置时,它看起来像这样:

Not the same - causing problems

使用新方法,SSAO看起​​来很乱。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分: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;
}