1
votes

I want to write the model-space vertex positions of a 3D mesh to a texture in OGL. Currently in order to write to a texture I set it to a fullscreen quad and write to it using a separate pass (based on tutorial seen here.)

The problem is that, from what I understand, I cannot pass more than one vertex list to the shader as the vertex shader can only be bound to one vertex list at a time, currently occupied by the screenspace quad.

Vertex Shader code:

layout(location = 0) in vec4 in_position; 
out vec4 vs_position;

void main() {
    vs_position  = in_position;
    gl_Position  = vec4(in_position.xy, 0.0, 1.0);
}

Fragment Shader code:

in vec4 position; // coordinate in the screenspace quad
out vec4 outColor;

void main() {
      vec2 uv = vec2(0.5, 0.5) * position.xy + vec2(0.5, 0.5);
      outColor = ?? // Here I need my vertex position
    }

Possible solution (?):

My idea was to introduce another shader pass before this to output the positions as r, g, b so that the position of the current texel can be retrieved from the texture (the only input format large enough to store many vertecies).

Although not 100% accurate, this image might give you an idea of what I want to do:

Model space coordinate map

Is there a way to encode the positions to the texture without using a fullscreen quad on the GPU?

Please let me know if you want to see more code.

1
You could draw the model vertices as points (so they are only processed once), then use gl_VertexID to calculate gl_Position. - GuyRT
Hm, could you please elaborate on that? At what stage in the pipeline should I do this and will this enable me to write the positions to an rgba texture? My problem is that I want to have both the fullscreen quad AND the model-space vertex data in the shader pipeline with the constraint of having one vertex array input. How does the gl_VertexID relate to the UV space in the output texture? @GuyRT - Antiiee
Using my idea, you wouldn't need to explicitly draw a quad, but the points generated from the vertex data would be drawn (in one draw call) into the texture. You'd use gl_VertexID something like: gl_Position.xy = vec2( mod(gl_VertexID, textureWidth), floor(gl_VertexID / textureWidth) * vec2( 2.0 / textureWidth, 2.0 / textureHeight) - 1.0. The second part maps to the -1 -> 1 clip space range. - GuyRT

1 Answers

1
votes

Instead of generating the quad CPU side I would attach a geometry shader and create the quad there, that should free up the slot for your model-geometry to be passed in.

Geometry shader:

layout(points) in;
layout(triangle_strip, max_vertices = 4) out;

out vec2 texcoord;

void main() 
{
    gl_Position = vec4( 1.0, 1.0, 0.5, 1.0 );
    texcoord = vec2( 1.0, 1.0 );
    EmitVertex();

    gl_Position = vec4(-1.0, 1.0, 0.5, 1.0 );
    texcoord = vec2( 0.0, 1.0 ); 
    EmitVertex();

    gl_Position = vec4( 1.0,-1.0, 0.5, 1.0 );
    texcoord = vec2( 1.0, 0.0 ); 
    EmitVertex();

    gl_Position = vec4(-1.0,-1.0, 0.5, 1.0 );
    texcoord = vec2( 0.0, 0.0 ); 
    EmitVertex();

    EndPrimitive(); 
}