GLSL geometry shader using lines_adjacency - glsl

I am writing a GLSL geometry shader and I am trying to use the lines_adjacency input layout but it isn't working. My first pass-though test using the lines input layout works fine:
// GLSL GEOMETRY SHADER
#version 410
layout (lines) in;
layout (line_strip, max_vertices = 2) out;
void main ()
{
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
EndPrimitive();
}
but when I switch to lines_adjacency input it doesn't draw anything:
// GLSL GEOMETRY SHADER
#version 410
layout (lines_adjacency) in;
layout (line_strip, max_vertices = 2) out;
void main ()
{
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
I know I'm not actually using the adjacency points here but I will need them eventually. I am a GLSL novice so any help would be appreciated, thanks.

You did change your input vertices to provide adjacency data, right? Because OpenGL doesn't parse your vertex data to figure out what is adjacent to what. The adjacency types exist to allow you to tell the shader about adjacent info. So you must provide that data.
In short, you can't render with the exact same attributes and index data with an adjacency geometry shader. Nevermind the fact that your glDraw* calls need to use GL_LINES_ADJACENCY instead of GL_LINES.

Related

How does the shader know that I'm editing color and not something else

There's this fragment shader which does work, but I do not understand its logic:
#version 330 core
out vec4 FragColor;
// the input variable from the vertex shader (same name and same type)
in vec4 vertexColor;
void main()
{
FragColor = vertexColor;
}
So how does the shader know that FragColor is supposed to represent the color of the shader, there is no assignment anywhere.
I'm saying it because in the vertex shader it's clear what is happening:
#version 330 core
// the position variable has attribute position 0
layout (location = 0) in vec3 aPos;
// specify a color output to the fragment shader
out vec4 vertexColor;
void main()
{
// see how we directly give a vec3 to vec4's constructor
gl_Position = vec4(aPos, 1.0);
// set the output variable to a dark-red color
vertexColor = vec4(0.5, 0.0, 0.0, 1.0);
}
The fragment shader does not know that FragColor represent a "color". For the shader it is just a vector with 4 components. The output(s) of the fragment shader are written into the frambuffer. A fragment shader has no other output (except depth buffer and stencil buffer). Therefore the shader does not need to know that the output variable represents a color.
See also Fragment Shader - Output buffers.

Can I use an array of 6 int from Vertex Shader to Geometry Shader?

I am trying to generate OpenGL primitives out of a 6 integer Vertex.
I.E. the 6 integer value will generate 4 custom line_strip.
First I am trying to move the 6 integer array from Vertex to Shader and in order to do that I am doing a simple test as follows.
This is the code for the Vertex Shader:
#version 330
layout (location = 0) in int inVertex[6];
out int outVertex[6];
void main()
{
outVertex = inVertex;
}
And for the Geometry Shader, which hardcodes a segment:
#version 330
in int vertex[6];
layout (line_strip, max_vertices = 2) out;
void main()
{
gl_Position = vec4(-0.2, -0.2, 0.0, 1.0);
EmitVertex();
gl_Position = vec4(-0.2 +0.4, -0.2, 0.0, 1.0);
EmitVertex();
EndPrimitive();
}
But I get an empty screen.
If I modify the Vertex shader to this:
#version 330
layout (location = 0) in int inVertex[6];
out int outVertex[6];
void main()
{
//outVertex = inVertex;
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
}
and the Geometry Shader to this:
#version 330
//in int candle[6];
layout (points) in;
layout (line_strip, max_vertices = 2) out;
void main()
{
gl_Position = vec4(-0.2, -0.2, 0.0, 1.0);
EmitVertex();
gl_Position = vec4(-0.2 +0.4, -0.2, 0.0, 1.0);
EmitVertex();
EndPrimitive();
}
Then I get the segment in the screen:
Is it mandatory to use gl_Position? If so, How can I pass additional variables together to gl_Position to enrich my Vertex?
Vertex shaders operate on vertices (oddly enough). They have a 1:1 correspondance with vertex data: for each vertex in the rendering operation, you get one output vertex.
Geometry shaders operate on primitives. They have a 1:many relationship with their input primitives. A GS gets a single primitive and it outputs 0 or more primitives, within various restrictions.
A primitive is composed of one or more vertices. So a GS must be able to get multiple pieces of input data, as generated by the VSs that executed to generate the primitive the GS is processing. As such, all GS inputs are arrayed. That is, for any type T which the VS outputs, the GS takes a T[] (or equivalent). This is true even if your GS's input primitive type is points.
So if the VS has this as an output out int outVertex[6];, then the corresponding GS ought to be in int outVertex[][6];. Note that the indices of arrays of arrays are read left-to-right, so this is an array of primitive-count elements, where each element is an array of 6 ints. Also, note that the names need to match. You should have gotten a linker error for the name mismatch.
Alternatively, you can use an interface block, to make the arraying a bit easier:
//VS:
out Prim
{
int data[6];
};
//GS:
in Prim
{
int data[6];
} vsData[];
//Access with vsData[primIx].data[X];
The Vertex Shader is executed for each vertex, hence the inputs and outputs are not an arrays, they are single attribute:
#version 330
layout (location = 0) in vec3 inVertex;
out vec3 vertex;
void main()
{
vertex = inVertex;
}
The input to the Geometry shader is a primitive. All the outputs of the vertex shader which form a primitive are composed. Thus the inputs of the geometry shader are arrays.
The size of the input array depends on the input primitive type to the geometry shader. e.g for a line the input array size is 2:
#version 330
layout (lines) in;
layout (line_strip, max_vertices = 4) out;
in vec3 vertex[];
void main()
{
// [...]
}

Tessellation shader drawing issues

I am currently trying to add tessellation shaders to my program and I feel as though I'm at my wit's end. I have gone through several tutorials and delved into a lot of the questions here as well. Unfortunately I still do not understand what I am doing wrong after all of this. I will take any tips gladly, and do admit I'm a total novice here. My vertex and fragment shaders work, but no matter which tutorial I base my code off of, I can not get anything to display once I add tessellation shaders. I get no errors while loading, linking, or using the shaders/program either.
The four shaders in question:
Vertex:
layout (location = 0) in vec4 vertex;
out gl_PerVertex{
vec4 gl_Position;
};
void main()
{
gl_Position = gl_Vertex;
//note I have to multiply this by the MVP matrix if there is no tessellation
}
Tessellation Control Shader:
layout (vertices = 3) out;
out gl_PerVertex {
vec4 gl_Position;
} gl_out[];
void main()
{
if (gl_InvocationID == 0)
{
gl_TessLevelInner[0] = 3.0;
gl_TessLevelOuter[0] = 2.0;
gl_TessLevelOuter[1] = 2.0;
gl_TessLevelOuter[2] = 2.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
Tessellation Evaluation Shader:
layout(triangles, equal_spacing, ccw) in;
uniform mat4 ModelViewProjectionMatrix;
out gl_PerVertex{
vec4 gl_Position;
};
void main()
{
vec4 position = gl_TessCoord.x * gl_in[0].gl_Position +
gl_TessCoord.y * gl_in[1].gl_Position +
gl_TessCoord.z * gl_in[2].gl_Position;
gl_Position = ModelViewProjectionMatrix * position;
}
Fragment Shader:
void main()
{
gl_FragColor = vec4(0.1, 0.4, 0.0, 1.0);
}
I'm sure I'm overlooking some really simple stuff here, but I'm at an absolute loss here. Thanks for taking the time to read this.
When you draw using a Tessellation Control Shader (this is an optional stage), you must use GL_PATCHES as the primitive type.
Additionally, GL_PATCHES has no default number of vertices, you must set that:
glPatchParameteri (GL_PATCH_VERTICES​, 3);
glDrawElements (GL_PATCHES, 3, ..., ...);
The code listed above will draw a single triangle patch. Now, since geometry shaders and tessellation evaluation shaders do not understand GL_PATCHES, if you remove the tessellation control shader, the draw code will do nothing. Only the tessellation control shader can make sense out of GL_PATCHES primitive, and conversely it cannot make sense of any other kind of primitive.

GLSL 1.5 - rendering to different layers of texture array

I have GL_TEXTURE_2D_ARRAY and I do this:
1. Render everything I want to FBO to texture array
2. Sample that array in the "main stage" of rendering
To achieve the first goal I've added a little geometry shader with gl_Layer calls to each primitive. Also, I've implemented some, let me say, "translation" thing similar to this Nvidia tutorial in my shaders that I use for the second stage of rendering.
So, what's my problem :
Condition: same vertices, same FBO, same shaders, same texture array
1) Rebinding rendering target multiply times in my FBO with glFramebufferTextureLayer calls works fine.
2) Saving texture array as glFramebufferTexture and only changing gl_Layer value leads to unexpected behaviour (first layer (0 in the code) is correct, every layer I try render next is invalid).
3) I don't want to 1) , I want to do 2) . How do I do that?
My shaders I use when rendering the FBO.
//vertex shader
#version 150 core
uniform mat4 orthoView;
in vec4 in_Position;
void main(void) {
gl_Position = orthoView * in_Position;
}
//geometry
#version 150 core
uniform int lr;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
out int gl_Layer;
void main(void){
//pass-thru!
for(int i=0; i<3; i++)
{
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
gl_Layer = lr;
EndPrimitive();
}
//fragment is empty
EDIT:
Thanks to everyone for help! My problem is solved now, here is my geometry shader:
#version 150 core
uniform int lr;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main(void){
//pass-thru!
for(int i=0; i<3; i++)
{
gl_Layer = lr;
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
gl_Layer, like all geometry shader outputs is a per-vertex output. Which vertex controls the layer for a particular primitive is implementation-defined. In your case, there's no reason not to set it in your loop, before the EmitVertex call.
I haven't actually used gl_Layer before, but looking at the documentation, it sounds like it is a per-vertex attribute (which is odd...).
The actual layer used will come from one of the vertices in the primitive being shaded
So try to set the value inside the for loop, before the EmitVertex, maybe?

using geometry shader to create new primitives types

Is it possible to output new primitive type from geometry shader other than was input? I'd like to input a point and render a triangle. The point would be used just as center for this triangle. If not, is there other option to input just point and render some other piece of geometry defined by that point?
With the help from answer here is geometry shader doing just what I asked for (if anyone ever needed):
#version 120
#extension GL_EXT_geometry_shader4 : enable
layout(points) in;
layout(triangle_strip) out;
void main()
{
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[0].gl_Position+vec4(1,0,0,0);
EmitVertex();
gl_Position = gl_in[0].gl_Position+vec4(0, 1, 0, 0);
EmitVertex();
EndPrimitive();
}
Yes, this is perfectly possible, that's what the geometry shader is there for. Just specify the input primitive type as point and the output primitive type as triangle (or rather triangle strip, no matter if it's only a single triangle) using either glProgramParameteri in the application or using the more modern layout syntax directly in the shader.