Deferred shader for depth, normals, and position

I’m trying to get a deferred shader working for depth, normals, and position. The first two seem to be working, but the last one is causing problems.

firstpass.vert:


varying float depth;
varying vec3 normal;
varying vec3 eye;

void main()
{
  // get the depth and eye position
  vec4 transformedVertex = gl_ModelViewMatrix * gl_Vertex;
  depth = -transformedVertex.z;
  eye = -transformedVertex.xyz;

  // transform normals to the current view
  normal = normalize(gl_NormalMatrix * normalize(gl_Normal));

  gl_Position = ftransform();
}

firstpass.frag:


varying float depth;
varying vec3 normal;
varying vec3 eye;

void main()
{
  float near = 1.3;
  float far = 2.5;

  // get shifted versions for better visualization
  float depthShift = (depth - near) / (far - near);
  vec3 normalShift = (normal + vec3(1.0)) * 0.5;

  gl_FragData[0] = vec4(normalShift, depthShift);
  gl_FragData[1] = vec4(normalize(eye), 1.0);
}

Side question for above: why is the depthShift and normalShift necessary?

secondpass.frag:


uniform sampler2D depthTexture;
uniform sampler2D eyeTexture;
uniform int renderType;

void main() 
{
  // pull everything we want from the textures
  float depth   = texture2D(depthTexture, gl_TexCoord[0].st).a; // depth in eye coordinates
  vec3 normal   = texture2D(depthTexture, gl_TexCoord[0].st).rgb; // normal in eye coordinates
  vec3 frag     = texture2D(eyeTexture,   gl_TexCoord[0].st).rgb; // position of frag in eye coordinates

  normal = normal * 2.0 - vec3(1.0);
  normal = normalize(normal);
  ...
  if(renderType == 1) // normals
    color = vec3(normal);
  else if(renderType == 2) // depth
    color = vec3(depth);
  else if(renderType == 3) // position
    color = vec3(frag);
  gl_FragColor = vec4(vec3(color), 1.0);
}

When I run this for renderType == 3 (position), all the objects in the scene are pure blue. The normals and the depths seem to both be working, but the position doesn’t work. Can someone point me in the right direction?

Your “position” channel logic is confusing. It is not an eye-space position. It’s a unit vector (not a position) in some negated EYE-SPACE.


vec4 transformedVertex = gl_ModelViewMatrix * gl_Vertex;
eye = -transformedVertex.xyz;
...

 gl_FragData[1] = vec4(normalize(eye), 1.0);

Also, you’ll notice that the “blue” in your bunny is not 100% blue but mostly blue. And if you adjust the contrast to focus in on the dynamic range of the blues, you’ll see a quantized radially-decreasing gradient, which you’d expect from an eye-space vector from the origin. Similarly, if you mask the blue and gain-up the red and green, you’ll see what you’d expect from a unit vector in negated eye-space (see below).

There are all kinds of ways to fry this “position from depth” fish, but suggest you just write an ordinary depth buffer (window-space depth), which the normal Z-buffer rendering pipeline will do for you, and then use the PositionFromDepth_DarkPhoton() method at the end of this post (or something similar) to reconstruct eye-space position. Matt Pettineo has a bunch more options in his blog with analysis.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.