c++gpgpufbooff-screen

FBO + texture: strange results from offscreen generation of geometry data


I have 2+ pass rendering where the first stage generates the positions of the vertices of a rectangular mesh and stores them in a 2D float texture. The shaders look this way:

vertex:

#version 330 core
out vec2 vfTexCoords;

const float halfSide = 1.0f;
const vec2[] pos = vec2[ 4 ]
(
    vec2( -halfSide, -halfSide ),
    vec2(  halfSide, -halfSide ),
    vec2(  halfSide,  halfSide ),
    vec2( -halfSide,  halfSide )
);

const vec2[] tex = vec2[ 4 ]
(
    vec2( 0.0f, 0.0f ),
    vec2( 1.0f, 0.0f ),
    vec2( 1.0f, 1.0f ),
    vec2( 0.0f, 1.0f )
);

void main()
{
    vfTexCoords = tex[ gl_VertexID ];
    gl_Position = vec4( pos[ gl_VertexID ], 0.0f, 1.0f );
}

fragment:

in vec2 vfTexCoords;

layout (location = 0) out vec3 pos;

void main()
{
    pos = vec3( vfTexCoords, 0.0f );
}

The output 2D float texture is resized to the dimensions of the rectangular vertices mesh and is bind it to one of the color attachments of the FBO. Thus the FBO size is inherited from the texture size.

The viewport is setup to have the same dimensions as the size of the rectangular mesh:

glViewport( 0, 0, horizontalVerticesCount, verticalVerticesCount );

So, now both the viewport and the texture have the same size and after:

glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );

... the output vertices' positions should range from vec3(0.0, 0.0, 0.0) to vec3(1.0, 1.0, 0.0), since texture coords vary from 0.0, 0.0 to 1.0, 1.0.

What is strange is that the x and y values of the output vertex positions from the fragment shader start from non-zero and their max value is below 1.0. For a 2 x 2 mesh: bottom-left: vec3( 0.25, 0.25, 0.0 ) ( 0.5 / mesh_side = 0.5 / 2 = 0.25 ) top-right: vec3( 0.75, 0.75, 0.0 )

For a 16 x 16 mesh: bottom-left: vec3( 0.03125, 0.03125 , 0.0 ) ( 0.5 / mesh_side = 0.5 / 16 = 0.03125 ) top-right: vec3( 0.96875, 0.96875, 0.0 )

Having the vertex shader positions set from vec3(-1.0, -1.0, 0.0) to vec3(1.0, 1.0, 0.0) should mean that I am "drawing" over the entire viewport. Modifying the vertex shader's positions results in different output values from the fragment shader.

What is wrong with the code above and why the drawing starts from 0.5 / rect_mesh_side_length?

Here's the originally posted question.

Any suggestions?


Solution

  • The fragment shader inputs are being interpolated at pixel centers. Section 15.2.2 of the OpenGL 4.5 specification (https://www.opengl.org/registry/doc/glspec45.core.pdf) "Shader Inputs" provides a detailed description of this behaviour and how it can be controlled.

    Here's a diagram I drew up quickly just for illustration purposes.

    Diagram

    Since you already have the dimensions of the grid known, you could pass them in as uniform variables and use the following code in your fragment shader. This will give you coordinates from 0.0 to 1.0 inclusive.

    vec2 coord = floor(gl_FragCoord.xy) / vec2(horizontalVerticesCount - 1.0, verticalVerticesCount - 1.0);