I am passing a line to the geometry shader and outputting a cuboid. I create 4 new points at each end of the line which was passed in by adding a constant "thickness" in the x or y direction. If I set the thickness in the geometry shader, it works fine, but when I tried to pass it to shaders as a part of the vertex data I can't seem to access it in the geometry shader. When I set
thickness = vThickness[0]
in the geometry shader, then nothing is drawn.
I can access the thickness data in the vertex shader and it seems to be valid (I set the output color to thickness and the cuboid was drawn white, which is fine since it should be an integer >= 1). The problem seems to be in the interface between vertex shader and the geometry shader.
Vertex shader:
#version 150 core
uniform vec3 uColor;
in vec3 position;
in int thickness;
out vec4 vColor;
out int vThickness;
void main() {
vColor = vec4(uColor, 1.0);
vThickness = thickness;
gl_Position = vec4(position, 1.0);
}
Geometry shader:
#version 150 core
uniform mat4 uProjection;
uniform mat4 uModel;
in vec4 vColor[];
in int vThickness[];
out vec4 gColor;
out vec3 normalV;
out vec3 points;
layout (lines) in;
layout (triangle_strip, max_vertices = 20) out;
void main() {
gColor = vColor[0];
vec3 z = (gl_in[1].gl_Position - gl_in[0].gl_Position).xyz;
vec3 x = cross(vec3(0.0, 1.0, 0.0), z);
float thickness = vColor[0];
// float thickness = 0.5; // This worked
x = thickness * normalize(x);
vec3 y = cross(z, x);
y = thickness * normalize(y);
vec4 endTL = uProjection * uModel * (gl_in[1].gl_Position - vec4(x, 0.0) + vec4(y, 0.0));
vec4 endTR = uProjection * uModel * (gl_in[1].gl_Position + vec4(x, 0.0) + vec4(y, 0.0));
vec4 endBL = uProjection * uModel * (gl_in[1].gl_Position - vec4(x, 0.0) - vec4(y, 0.0));
vec4 endBR = uProjection * uModel * (gl_in[1].gl_Position + vec4(x, 0.0) - vec4(y, 0.0));
vec4 begTL = uProjection * uModel * (gl_in[0].gl_Position - vec4(x, 0.0) + vec4(y, 0.0));
vec4 begTR = uProjection * uModel * (gl_in[0].gl_Position + vec4(x, 0.0) + vec4(y, 0.0));
vec4 begBL = uProjection * uModel * (gl_in[0].gl_Position - vec4(x, 0.0) - vec4(y, 0.0));
vec4 begBR = uProjection * uModel * (gl_in[0].gl_Position + vec4(x, 0.0) - vec4(y, 0.0));
gl_Position = begTL; // 0
points = begTL.xyz;
normalV = normalize(-x + y);
EmitVertex();
gl_Position = endTL; // 1
points = endTL.xyz;
normalV = normalize(-x + y);
EmitVertex();
gl_Position = begTR; // 2
points = begTR.xyz;
normalV = normalize(x + y);
EmitVertex();
gl_Position = endTR; // 3
points = endTR.xyz;
normalV = normalize(x + y);
EmitVertex();
gl_Position = begBR; // 4
points = begBR.xyz;
normalV = normalize(-x + y);
EmitVertex();
gl_Position = endBR; // 5
points = endBR.xyz;
normalV = normalize(x - y);
EmitVertex();
gl_Position = begBL; // 6
points = begBL.xyz;
normalV = normalize(x - y);
EmitVertex();
gl_Position = endBL; // 7
points = endBL.xyz;
normalV = normalize(-x - y);
EmitVertex();
gl_Position = begTL; // 8
points = begTL.xyz;
normalV = normalize(-x + y);
EmitVertex();
gl_Position = endTL; // 9
points = endTL.xyz;
normalV = normalize(-x + y);
EmitVertex();
}
Fragment Shader:
#version 150 core
vec3 intensities = vec3(0.2f,0.2f,0.2f);
in vec4 gColor;
in vec3 normalV;
in vec3 points;
out vec4 fColor;
void main() {
vec3 surfaceToLight = normalize(vec3(1,1,0));
float brightness = dot(normalV, surfaceToLight);
brightness = clamp(brightness, 0, 1);
vec4 surfaceColor = gColor;
fColor = vec4(brightness * intensities + surfaceColor.rgb * 0.5f, surfaceColor.a);
}
The data I am passing:
struct Vertex
{
Vector3 position;
uint32 thickness;
};
GLint positionAttribLocation = glGetAttribLocation(renderContext->branchesContext.program, "position");
glEnableVertexAttribArray(positionAttribLocation);
glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
GLint thicknessAttribLocation = glGetAttribLocation(renderContext->branchesContext.program, "thickness");
glEnableVertexAttribArray(thicknessAttribLocation);
glVertexAttribPointer(thicknessAttribLocation, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
You are using the incorrect function to establish a vertex attribute pointer for thickness
.
glVertexAttribPointer(thicknessAttribLocation, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
Thickness has type int
, and you are using glVertexAttribPointer (...)
. That function is designed to convert your vertex data to floating-point and is only suitable for float
, vec<N>
and matrix data types.
To correctly give your vertex attribute a data pointer, you need to use glVertexAttribIPointer (...)
. That will leave integer data alone and pass it directly to your shader, it is appropriate for {u}int
and [i|u]vec<N>
attributes.
glVertexAttribIPointer(thicknessAttribLocation, 1, GL_UNSIGNED_INT, sizeof(Vertex), (void*)(3 * sizeof(float)));
You will notice there is one less parameter in this function call, and that is because floating-point normalization is not an option for integer vertex attributes.