The best way to draw full-screen texture

What is the best way to draw full-screen textures in a fragment shader, for example, g-buffer in a deferred renderer or scene texture in a post-process shader?

I am currently using the following two methods:

  • Pass the screen size to the shader as a whole and calculate (u, v) from gl_FragCoord :

     vec2 texCoord = gl_FragCoord.xy / vScreenSize; vec3 c = texture( tex, texCoord ).rgb; 

    It doesn't seem ideal, because separation is required, and providing a shader with a screen size is cumbersome.

  • Convert gl_FragCoord.xy to ivec and use texelFetch :

     vec3 c = texelFetch( tex, ivec2(gl_FragCoord.xy), 0 ).rgb; 

    Also not ideal, because conversion from float to int is required.

So is there a better way? I just want to try the buffer at the exact point where my pixel shader is drawn.


// EDIT:


Well, with the sentences of the 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 mainly calculate the normalized device coordinates (NDC) from the position of the clip space with a split perspective and then compare the NDC (range from [-1.1]) to the interval [0.1]. This works great for full-screen quads (even without a split perspective, because the coordinates are so simple). Any arbitrary geometry I need to draw as the light geometry in my deferred renderer has some problems though. In the vertex shader, I vVertCoord as the 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 sphere with a spotlight, everything looks fine (black lines are highlighted specially):

All fine

However, if I approach light geometry, this is the result:

Not ok

What is this red spot in the upper left corner? You do not want to see the results in real color when the debug colors are turned off, because it is like an lsd ride, and everything happens when you move the camera. Is this accuracy related? Note that everything is fine when I use gl_FragCoord in the pixel shader instead.

+6
source share
1 answer

You don’t need to do any special math if you just pass the vertex interpolate coordinate from the vertex shader.

For example, if you draw a simple square of the unit that covered your screen, you could simply and then get a full-screen texture, you could just do something like this:

 vertex shader pseudocode: layout(position = 0) in vec3 in_vertex; out vec3 out_vertex; void main() { //Do your matrix multiplications to your in_vertex to get its final position... out_vertex = in_vertex; } 

Your vertex shader will correctly interpolate in_vertex to the range x: 0 ... 1, y: 0 ... 1 (while you are drawing a unit square) and pass it to the shader fragment. Then your fragment shader will use it like this:

 fragment shader pseudocode: in vec3 out_vertex; uniform sampler2D tex; void main() { gl_fragcolor = texture(tex,vec2(out_vertex.x,out_vertex.y)); } 

No other math is required if you make sure that out_vertex is always in the range 0 ... 1. To expand this example a bit, imagine our area:

(0,1)+-----------+(1,1) | | | | | | | | | | (0,0)+-----------+(0,1)

And we wanted to try this point in the exact center:

(0,1)+-----------+(1,1) | | | | | * | | | | | (0,0)+-----------+(0,1)

Our vertex shader will automatically interpolate this position from the other 4 positions and transfer the following vec3 to the fragment shader:

 out_vertex = vec3(0.5,0.5,0); 

which can then be used to successfully select a texture

+2
source

All Articles