glsl pass through geometry shader issue - opengl

At this point I have a working vertex and fragment shader. If I remove my geometry shader completely, then I get the expected cube with colors at each vertex. But with the geometry shader added, no geometry shows up at all.
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
out VertexData
{
vec3 color;
} vertex;
uniform mat4 MVP;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
vertex.color = vertexColor;
}
Geometry Shader:
#version 330
precision highp float;
in VertexData
{
vec3 color;
} vertex[];
out vec3 fragmentColor;
layout (triangles) in;
layout (triangle_strip) out;
layout (max_vertices = 3) out;
void main(void)
{
for (int i = 0; i > gl_in.length(); i++) {
gl_Position = gl_in[i].gl_Position;
fragmentColor = vertex[i].color;
EmitVertex();
}
EndPrimitive();
}
Fragment Shader:
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
color = fragmentColor;
}
My graphics card supports OpenGL 3.3 from what I can tell. And, as I said. It works without the Geometry shader. As data, I am passing in two arrays of GLfloat's where each is a vertex or a vertex color respective.

for (int i = 0; i > gl_in.length(); i++) //note the '>'
This loop condition will be false right from the start, so you won't ever emit any vertices. What you most probably meant is i < gl_in.length().

Related

Why doesnt my passthrough geometry shader work?

I am making project of cubesphere Earth. I implemented vertex and fragment shaders for textures and it worked fine (with camera movement).
I wanted to add a passthrough geometry shader but i cant get it to work.
Vertex shader
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 textureCoords;
out vec2 textCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0);
textCoords = textureCoords;
}
Geometry shader
#version 450 core
layout (triangles) in;
layout (triangles, max_vertices = 3) out;
in vec2 textCoords[];
out vec2 TextCoords;
void main()
{
int i;
for(i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
TextCoords = textCoords[i];
EmitVertex();
}
EndPrimitive();
}
Fragment shader
#version 450 core
in vec2 TextCoords;
out vec4 fragmentColor;
uniform sampler2D earth;
void main()
{
fragmentColor = texture(earth, TextCoords);
}
I used shader class from learnopengl, and only thing i changed in Main was geometry shader path in Shader constructor.
BEFORE GEOMETRY SHADER
]
AFTER GEOMETRY SHADER
Issue was
layout (triangles, max_vertices = 3) out;
Should be
layout (triangle_strip, max_vertices = 3) out;

Can't get openGL's glDrawElements to work with geometry shader

i have attached the shader but i can't find any info on how to use glDrawElements with a goemetry shader attached to the shader program.
The program would output a quad on the screen without the geometry shader, now i'm trying to do the same but with a geometry shader attached.
//In my .cpp file
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Vertex shader
#version 440
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
uniform mat4 world_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec3 color;
void main() {
color = vertex_color;
gl_Position = projection_matrix*view_matrix* world_matrix *
vec4(vertex_position, 1.0);
}
// Geometry shader
#version 440 core
layout (triangle_strip) in;
layout (triangle_strip, max_vertices = 6) out;
layout(location = 1) in vec3 vertex_color;
out vec3 color;
void main()
{
for(int i = 0; i < gl_in.length(); i++)
{
// copy attributes
gl_Position = gl_in[i].gl_Position;
color=vertex_color;
// done with the vertex
EmitVertex();
}
EndPrimitive();
}
//Fragment shader
#version 440
in vec3 color;
out vec4 fragment_color;
void main () {
fragment_color = vec4 (color, 1.0);
}
See the handy OpenGL wiki site of Khronos Group for Shader stage inputs and outputs:
Global variables declared with the in qualifier are shader stage input variables. These variables are given values by the previous stage (possibly via interpolation of values output from multiple shader executions).
Global variables declared with the out qualifier are shader stage output variables. These values are passed to the next stage of the pipeline (possibly via interpolation of values output from multiple shader executions).
Geometry Shader inputs are aggregated into arrays, one per vertex in the primitive. The length of the array depends on the input primitive type used by the GS. Each array index represents a single vertex in the input primitive.
You have a vertex shader, a geometry shader and a fragment shader. In this case the vertex shader is the first shader stage, followed by the geometry shader and the last shader stage is the fragment shader.
So the input variables of the geometry shader have to match to the output variables of the vertex shader. The input variables of the fragment shader have to match to the output variables of the geometry shader.
Further note, that the possible input primitive specifier are points, lines, lines_adjacency, triangles and triangles_adjacency.
See also Geometry Shader - Primitive in/out specification.
This means you code has to look somehow like this:
Vertex shader:
#version 440
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec3 vertex_color;
uniform mat4 world_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec3 vert_stage_color;
void main()
{
vert_out_color = vertex_color;
gl_Position = projection_matrix*view_matrix* world_matrix * vec4(vertex_position, 1.0);
}
Geometry shader:
#version 440 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 6) out;
layout(location = 1) in vec3 vertex_color;
in vec3 vert_stage_color[];
out vec3 geo_stage_color;
void main()
{
for(int i = 0; i < gl_in.length(); i++)
{
// copy attributes
gl_Position = gl_in[i].gl_Position;
geo_stage_color = vert_stage_color[i];
// done with the vertex
EmitVertex();
}
EndPrimitive();
}
Fragment shader:
#version 440
in vec3 geo_stage_color;
out vec4 fragment_color;
void main ()
{
fragment_color = vec4(geo_stage_color, 1.0);
}

Do I need to pass color though my geometry shader to the fragment shader?

So I have three shaders in my program.
Vertex:
#version 330 core
in vec2 Inpoint;
in vec2 texCoords;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 projection;
void main()
{
TexCoords = texCoords;
gl_Position = projection * model * vec4(Inpoint, 0.0, 1.0);
}
Geometry:
#version 330 core
layout(triangles) in;
layout(triangle_strip, max_vertices = 4) out;
void main()
{
int i;
for (i = 0; i < gl_in.length(); i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
And finally the fragment shader:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D image;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.0) * texture(image, TexCoords);
}
Now without the geometry shader, everything displays just fine. But as soon as I include the geometry shader, everything goes ... bad.
It acts like its not getting chords for the textures.
So, the question is, does the geometry shader need to pass the data through itself to the fragment shader? I mean the geometry shader is basically doing nothing so it shouldn't. Unless there is some giant mistake I am missing.
I tried to add a pass-though but it complains that everything needs to be an array, and even when I did make it an array it didn't quite work right.
Quoting GLSL 3.30 specs 4.3.1 Inputs :
Fragment shader inputs get per-fragment values, typically interpolated
from a previous stage's outputs
Having a geometry shader is the previous stage. So yes, your FS uses inputs from your GS and only from it.

gl_VertexID always zero in any useful geometry shader

I am using indexed rendering and a geometry shader. If I pass gl_VertexID to the geometry shader, it works fine as long as I do not emit any vertices; if I emit one or more vertices, gl_VertexID (passed as any name) is zero. Why?
Using the shaders below, the geometry shader will put the correct indices into my feedback buffer, if and only if I comment out both EmitVertex calls. What am I missing?
(I can work around it, but it is bugging the hell out of me!)
VERTEX SHADER
#version 440
in vec4 position;
out VSOUT{
vec4 gl_Position;
int index;
} vsout;
uniform mat4 gl_ModelViewMatrix;
void main(){
gl_Position = gl_ModelViewMatrix * position;
vsout.index = gl_VertexID;
vsout.gl_Position = gl_Position;
}
GEOMETRY SHADER
#version 440
#extension GL_ARB_shader_storage_buffer_object : enable
layout (lines) in;
layout (line_strip) out;
in VSOUT{
vec4 gl_Position;
int index;
} vdata[];
layout (std430, binding=0) buffer FeedbackBuffer{
vec2 fb[];
};
void main(){
int i = vdata[0].index;
int j = vdata[1].index;
fb[gl_PrimitiveIDIn][0] = vdata[0].index;
fb[gl_PrimitiveIDIn][1] = vdata[1].index;
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
}
FRAGMENT SHADER
#version 430
out vec4 outputColor;
void main(){
outputColor = vec4(.5,.5,.5,.5);
}
So this looks like an nVidia implementation thing. If I run these shaders on a GeForce GTX580, behaviour is as described above. Using an AMD FirePro V5900, it behaves as I'd expect, with the correct values in the feedback buffer whether or not I emit vertices.

simple pass-through geometry shader with normal and color

I've written a very simple pass-through geometry shader. My input primitive is points and output primitive is also points. I also want to forward the color and normal from vertex shader to fragment shader through geometry shader. The shaders are compiled and linked flawlessly but the final color is very weird. I think there is something wrong with this forwarding. Can anyone point out the problem? Here are my shaders:
Vertex shader:
#version 330 compatibility
struct vData
{
vec3 normal;
vec4 color;
};
out vData vertex;
void main()
{
vertex.normal = gl_NormalMatrix * gl_Normal;
vertex.color = gl_Color;
gl_Position = ftransform();
}
Geometry shader:
#version 330
layout (points) in;
layout (points) out;
layout (max_vertices = 1) out;
struct vData
{
vec3 normal;
vec4 color;
};
in vData vertices[];
out vData frag;
void main()
{
int i;
for(i = 0;i < gl_in.length();i++)
{
frag.normal = vertices[i].normal;
frag.color = vertices[i].color;
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
Fragment shader:
#version 330
struct vData
{
vec3 normal;
vec4 color;
};
in vData frag;
void main()
{
gl_FragColor = frag.color;
}
I figured this out! the in/out variables must have same name i.e. vertices[] in geometry shader should be vertex[]. That's it!
My refined and working code goes as follows:
Vertex shader:
#version 330 compatibility
out vData
{
vec3 normal;
vec4 color;
}vertex;
void main()
{
vertex.normal = normalize(gl_NormalMatrix * gl_Normal);
vertex.color = gl_Color;
gl_Position = ftransform();
}
Geometry shader:
#version 330
layout (points) in;
layout (points) out;
layout (max_vertices = 1) out;
in vData
{
vec3 normal;
vec4 color;
}vertices[];
out fData
{
vec3 normal;
vec4 color;
}frag;
void main()
{
int i;
for(i = 0;i < gl_in.length();i++)// gl_in.length() = 1 though!
{
frag.normal = vertices[i].normal;
frag.color = vertices[i].color;
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
Fragment shader:
#version 330 compatibility
in fData
{
vec3 normal;
vec4 color;
};
void main()
{
gl_FragColor = frag.color;
}
Happy coding!