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;
Related
I have a vertex shader that takes in position, texture coordinates, normals and some uniforms:
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normal;
//MVP
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Proj;
//Lighting
uniform mat4 u_InvTranspModel;
uniform mat4 u_LightMVP;
out DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_out[];
void main()
{
gl_Position = u_Model * position;
data_out.v_TexCoord = texCoord;
data_out.v_Normal = mat3(u_InvTranspModel) * normal;
data_out.v_Proj = u_Proj * u_View * u_Model;
//Light
data_out.v_FragPos = vec3(u_Model*position);
data_out.v_LightSpacePos = u_LightMVP * position;
}
I'm passing into my geometry shader:
#version 330 core
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_in[];
out vec2 g_TexCoord;
out vec3 g_Normal;
out vec3 g_FragPos;
out vec4 g_LightSpacePos;
void main()
{
gl_Position = data_in[0].v_Proj * gl_in[0].gl_Position;
g_Normal = data_in[0].v_Normal;
g_FragPos = data_in[0].v_FragPos;
g_TexCoord = data_in[0].v_TexCoord;
g_LightSpacePos = data_in[0].v_LightSpacePos;
EmitVertex();
gl_Position = data_in[1].v_Proj * gl_in[1].gl_Position;
g_Normal = data_in[1].v_Normal;
g_FragPos = data_in[1].v_FragPos;
g_TexCoord = data_in[1].v_TexCoord;
g_LightSpacePos = data_in[1].v_LightSpacePos;
EmitVertex();
gl_Position = data_in[2].v_Proj * gl_in[2].gl_Position;
g_Normal = data_in[2].v_Normal;
g_FragPos = data_in[2].v_FragPos;
g_TexCoord = data_in[2].v_TexCoord;
g_LightSpacePos = data_in[2].v_LightSpacePos;
EmitVertex();
EndPrimitive();
}
However I get the errors:
ERROR: 0:28: '.' : dot operator to an array only takes length()
ERROR: 0:28: 'assign' : cannot convert from 'attribute 2-component vector of highp float' to 'varying unknown-sized array of highp block'
ERROR: 0:29: '.' : dot operator to an array only takes length()
ERROR: 0:29: 'assign' : cannot convert from '3-component vector of highp float' to 'varying unknown-sized array of highp block'
................ Etc
I get these errors for every variable in the vertex shader that is passed to the geometry shader.
This shader works when its in a form without geometry shader, and should be setup currently to do nothing, so what have I done wrong?
The output of the vertex shader is not an array, even if the next stage is a Geometry shader. The Vertex shader processes a single vertex, and therefore the outputs are always single values related to that vertex. The geometry shader's input interface is an array because the geometry shader takes a primitive (multiple vertices) as input rather than a single vertex. Remove [] in the vertex shader:
out DATA
{
vec2 v_TexCoord;
vec3 v_Normal;
vec3 v_FragPos;
vec4 v_LightSpacePos;
mat4 v_Proj;
} data_out; // <--- remove []
I'm trying to make 2 objects in OpenGL with 2 diffrent textures and one of them should moving.
I make 2 shader program and sign it to diffrent indicates tabs. Parameters of shader programs looking but program draws only one obejct (which I use later). Is it correctly if I make .frag and .vert file same structure and name of in/out vectors but change only texture and delete transformation from static object?
//fragment of moving object
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 vecColor;
out vec2 TexCoord;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection*view* transform * vec4(position, 1.0f);
vecColor = color;
TexCoord = texCoord;
}
// fragment of static object
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 vecColor;
out vec2 TexCoord;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection*view * vec4(position, 1.0f);
vecColor = color;
TexCoord = texCoord;
}
// code of Use()
void Use() const
{
glUseProgram(get_programID());
}
// Drawing elements in main event loop whiile()
// Draw first object
theProgram_stelaz.Use();
glBindVertexArray(VAO_stelaz);
glDrawElements(GL_TRIANGLES, _countof(indices_stelaz), GL_UNSIGNED_INT,
0);
glBindVertexArray(0);
// Draw second object
theProgram.Use();
glBindVertexArray(VAO_wings);
glDrawElements(GL_TRIANGLES, _countof(indices_wings), GL_UNSIGNED_INT,
0);
glBindVertexArray(0);
Now program draws only secon object from indices_wings. I want to draw two elements and just object from indices_wings should move.
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);
}
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.
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().