0

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?

Ivan Caravanio
  • 597
  • 1
  • 7
  • 20
  • I'd suggest that you post contents of the question here. :) – GoBusto Jan 19 '15 at 19:12
  • Your approach of hard coding those coords into the shader seems strange and i am not sure what exactly you want to accomplish. If you simply want a texture containing values interpolated from (0,0) to (1,1) i could imagine a few ways to do this, but yours is not among them ;) (however i don't want to presume that your approach may not be a valid test for sth else or just an experiment). Nevertheless i wonder what you mean by 16x16 mesh? With 256 vertices gl_VertexID as an index wont work anymore. Do you check for glError's and shader logs and FBO-completeness? – Thomas Jan 19 '15 at 20:38
  • I check everything. Each gl* call is checked for error and the error is dumped if there's any. I've hardcoded those coords for simplicity and compactness, since several shader programs are using the same vertex shader. By M x N mesh, I mean that I resize the output texture and set the viewport's size to M x N, so that on the rendering pass that is coming next would use the filled texture with geometry data. gl_VertexID here is from 0 - 3 here. Is there a limitation or? Is gl_VertexID an unsigned 8-bit integer? I am using VAOs all over the place but for this simple vertex shader omitted them. – Ivan Caravanio Jan 19 '15 at 22:02
  • @Ivan i thought by mesh size you meant the vertex count in rows and columns. If you always have 4 vertices you are alright as long as you do not draw them with any vbo-offset with might be added to the id if i remember correctly. – Thomas Jan 21 '15 at 12:03

1 Answers1

3

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);
GoBusto
  • 4,632
  • 6
  • 28
  • 45
pixcel
  • 66
  • 5