Screen Space Texture Coordinates

2014/12/21 19:55

I am not sure what the correct title for this post should be, but I have been tinkering with some Deferred Shading stuff again recently. Anyway to keep things short, sometimes its handy to have the clip space vertex coordinates (which are usually in the range [-1,-1,-1] to [1,1,1]) remapped for use in texturing (which are usually in the range [0,0] to [1,1]).

Ignoring the Z component of the clip coordinate there are a couple of solutions, you can use the built in input gl_FragCoord variable in the fragment shader which ranges from [0,0] to [frame_buffer_size.x, frame_buffer_size.y]. A quick divide by the frame buffer size you are rending to should do the remapping for you:

//fragment shader
vec2 screencoord = vec2(gl_FragCoord.x/frame_buffer_size.x,
                        gl_FragCoord.y/frame_buffer_size.y);

where frame_buffer_size is a vec2 uniform set by the application.Another possible solution is:

//-------------------------------------
//vertex shader
out vec4 vScreenCoord;
 
void main()
{
    //uniModelViewProjectionMtx : MVP
    //inVertex : vertex attribute for vertex position
    ...
    vScreenCoord = uniModelViewProjectionMtx * inVertex;
    gl_Position = vScreenCoord;
     
}
 
//-------------------------------------
//fragment shader
in vec4 vScreenCoord;
 
void main()
{
    ...
    vec2 texcoord = vec2( ((vScreenCoord.x/vScreenCoord.w) +1.0)*0.5), ((vScreenCoord.y/vScreenCoord.w) +1.0)*0.5) )
    ...
}

because the clip coordinates are between [-1,-1,-1] and [1,1,1] we need to remap them to [0,0,0] and [1,1,1] after the perspective divide.

We can also move the perspective divide and remapping of the range shown above from the Fragment shader to the Vertex shader:

//-------------------------------------
//vertex shader
noperspective out vec2 vScreenCoord;
 
void main()
{
    //uniModelViewProjectionMtx : MVP
    //inVertex : vertex attribute for vertex position
    ...
    vec 4 temp = uniModelViewProjectionMtx * inVertex;
    gl_Position = vScreenCoord;
    vScreenCoord.x = ((temp.x/temp.w)+1.0)*0.5;
    vScreenCoord.y = ((temp.y/temp.w)+1.0)*0.5;
}
 
//-------------------------------------
//fragment shader
noperspective in vec2 vScreenCoord;
 
void main()
{
    ...
    vec2 texcoord = vec2( vScreenCoord.x, vScreenCoord.y);
    //we can actually now just use vScreencoord as the
    //texture coordinate directly
    ...
}

the noperspective qualifier causes the variable to have a linear interpolation across the triangle rather than a perspective correct one.