I have an GLSL geometry shader that looks like the following:
#version 150
uniform mat4 p;
uniform mat4 mv;
uniform mat3 nm;
layout(points) in;
layout(triangle_strip, max_vertices = 200) out;
out vec4 test;
void main() {
for (int i = 0; i < gl_in.length(); i++) {
....
gl_Position = p * mv * gl_in[i].gl_Position;
test = vec4(1.0, 0.0, 0.0, 0.0);
EmitVertex();
....
EndPrimitive();
}
}
However when I try to access "test" in my fragment shader my application crashes. Here is my fragment shader:
#version 150
out vec4 fColor;
in vec4 test;
void main(void) {
fColor = vec4(test.x, 1.0, 0.4, 0);
}
Can someone help me to pass a variable from the geometry to the fragment shader? varying is deprecated in #version 150.
You need to declare test as input in your fragment shader (I wonder why the shader compiles):
in vec4 test;
Related
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;
I created a basic quad drawing shader using a single point and a geometry shader.
I've read many posts and articles suggesting that I would not need to use glProgramParameteriEXT and could use the layout keyword so long as I was using a shader #version 150 or higher. Some suggested #version 400 or #version 420. My computer will not support #version 420 or higher.
If I use only layout and #version 150 or higher, nothing draws. If I remove layout (or even keep it; it does not seem to care because it will compile) and use glProgramParameteriEXT, it renders.
In code, this does nothing:
layout (points) in;
layout (triangle_strip, max_vertices=4) out;
This is the only code that works:
glProgramParameteriEXT( id, GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS );
glProgramParameteriEXT( id, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP );
glProgramParameteriEXT( id, GL_GEOMETRY_VERTICES_OUT_EXT, 4 );
The alternative is to create a parser that creates the parameters via shader source.
Source for quad rendering via geometry shader:
#version 330
#ifdef VERTEX_SHADER
in vec4 aTexture0;
in vec4 aColor;
in mat4 aMatrix;
out vec4 gvTex0;
out vec4 gvColor;
out mat4 gvMatrix;
void main()
{
// Texture color
gvTex0 = aTexture0;
// Vertex color
gvColor = aColor;
// Matrix
gvMatrix = aMatrix;
}
#endif
#ifdef GEOMETRY_SHADER
layout (points) in;
layout (triangle_strip, max_vertices=4) out;
in vec4 gvTex0[1];
in vec4 gvColor[1];
in mat4 gvMatrix[1];
out vec2 vTex0;
out vec4 vColor;
void main()
{
vColor = gvColor[0];
// Top right.
//
gl_Position = gvMatrix[0] * vec4(1, 1, 0, 1);
vTex0 = vec2(gvTex0[0].z, gvTex0[0].y);
EmitVertex();
// Top left.
//
gl_Position = gvMatrix[0] * vec4(-1, 1, 0, 1);
vTex0 = vec2(gvTex0[0].x, gvTex0[0].y);
EmitVertex();
// Bottom right.
//
gl_Position = gvMatrix[0] * vec4(1, -1, 0, 1);
vTex0 = vec2(gvTex0[0].z, gvTex0[0].w);
EmitVertex();
// Bottom left.
//
gl_Position = gvMatrix[0] * vec4(-1, -1, 0, 1);
vTex0 = vec2(gvTex0[0].x, gvTex0[0].w);
EmitVertex();
EndPrimitive();
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D tex0;
in vec2 vTex0;
in vec4 vColor;
out vec4 vFragColor;
void main()
{
vFragColor = clamp(texture2D(tex0, vTex0) * vColor, 0.0, 1.0);
}
#endif
I am looking for suggestions as to why something like this might happen.
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().
I am using a vertex, geometry and fragment shader to render a scene with shadows:
Vertex Shader:
#version 400
layout(location=0) in vec3 position;
out vec4 vShadowCoord;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 shadowMatrix;
void main(void)
{
vShadowCoord = shadowMatrix * vec4(position, 1.0);
gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);
}
Geometry Shader:
#version 400
layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices = 3) out;
in vec4 vShadowCoord[];
out vec4 gShadowCoord;
uniform vec3 lightPosition;
void main()
{
gShadowCoord = vShadowCoord[0];
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gShadowCoord = vShadowCoord[2];
gl_Position = gl_in[2].gl_Position;
EmitVertex();
gShadowCoord = vShadowCoord[4];
gl_Position = gl_in[4].gl_Position;
EmitVertex();
EndPrimitive();
}
Fragment Shader:
#version 400
in vec4 shadowCoord;
out vec4 fColor;
uniform sampler2DShadow shadowMap;
void main(void)
{
float shadow = textureProj(shadowMap, shadowCoord);
fColor = (shadow > 0.0) ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.1, 0.1, 0.1, 1.0);
}
This successfully renders my scene with shadows. The cubes in my scene are lit and in shadow where I would expect them to be. The problem occurs when I try to pass one of the two colors in from the geometry shader. When I do this, my conditional statement always evaluates to false.
Geometry shader:
#version 400
layout(triangles_adjacency) in;
layout(triangle_strip, max_vertices = 3) out;
in vec4 vShadowCoord[];
out vec4 gShadowCoord; // Added
out vec4 gColorLit; // Added
uniform vec3 lightPosition;
void main()
{
gShadowCoord = vShadowCoord[0];
gColorLit = vec4(1.0, 1.0, 1.0, 1.0); // Added
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gShadowCoord = vShadowCoord[2];
gColorLit = vec4(1.0, 1.0, 1.0, 1.0); // Added
gl_Position = gl_in[2].gl_Position;
EmitVertex();
gShadowCoord = vShadowCoord[4];
gColorLit = vec4(1.0, 1.0, 1.0, 1.0); // Added
gl_Position = gl_in[4].gl_Position;
EmitVertex();
EndPrimitive();
}
Fragment Shader:
#version 400
in vec4 shadowCoord;
in vec4 gColorLit; // Added
out vec4 fColor;
uniform sampler2DShadow shadowMap;
void main(void)
{
float shadow = textureProj(shadowMap, shadowCoord);
// Changed
fColor = (shadow > 0.0) ? gColorLit : vec4(0.1, 0.1, 0.1, 1.0);
}
What could be causing this to happen?
This occurs on both Ubuntu 12.04 and Windows 7
Some of the code in my shaders might seem unnecessary, but that is because I have stripped as much as I could away while troubleshooting.
There's no reason for your second shaders to successfully link. Your geometry shader states that it's writing:
out vec4 gShadowCoord; // Added
But your fragment shader is expecting:
in vec4 shadowCoord;
You should have gotten a linker error.
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!