What is the best way to sample fullscreen textures in a fragment shader, so for example the g-buffer in a deferred renderer, or the scene texture within a postprocess shader?
At the moment I use the following two ways:
Pass the screen size to the shader as a uniform and calculate (u,v) from
gl_FragCoord:vec2 texCoord = gl_FragCoord.xy / vScreenSize; vec3 c = texture( tex, texCoord ).rgb;Does not seem to be ideal since a division is required and supplying the shader with the screen size is cumbersome.
Convert
gl_FragCoord.xyinto anivecand usetexelFetch:vec3 c = texelFetch( tex, ivec2(gl_FragCoord.xy), 0 ).rgb;Also not ideal because the conversion from
floattointis required.
So is there a better way? I really just want to sample a buffer at the exact point where my pixel shader is drawing.
// EDIT:
Ok, with the suggestions of interpolated texture-coordinates that come from the vertex shader I managed to figure out the following code:
Vertex shader:
#version 150
uniform mat4 im_ModelViewProjectionMatrix;
in vec3 iv_Vertex;
noperspective out vec2 vVertCoord;
void main( void )
{
gl_Position = im_ModelViewProjectionMatrix * vec4(iv_Vertex, 1.0);
vVertCoord = (gl_Position.xy / gl_Position.w) * (0.5) + vec2(0.5);
}
I basically calculate normalized device coordinates (NDC) from the clip space position with the perspective division and then map the NDCs (that range from [-1,1]) into the interval [0,1]. This works great for fullscreen quads (even without the perspective division because coordinates are so simple). The arbitrary geometry I need to draw as light-geometry in my deferred renderer has some problems though. In the vertex shader I output vVertCoord as a color for red=x and green=y:
#version 150
noperspective in vec2 vVertCoord;
out vec4 colorOut;
void main( void )
{
colorOut = vec4(vVertCoord.x, vVertCoord.y, 0, 1);
}
This is the result when I am inside a point-light-sphere, everything looks fine (the black lines are rendered on purpose):

However, if I move closer to the light-geometry this is the result:

What is that red patch in the top left corner doing there? You don't want to see the results in real-color with the debugging colors disabled because it looks like an lsd-trip, everything warps around when you move the camera. Is this precision related? Note that all is fine when I use gl_FragCoord in the pixel shader instead.