Reputation: 55
I read many articles and posts about passing values like vectors and matrices from the vertex shader stage to the fragment shader. But I'm still not sure about this: If you have some out vars in the vertex shader (I'll call him vtxs) and some in vars in the fragment shader (frgs), how does OpenGl associate them so they refer to the same value (i neglect the fact that values passing to frgs are interpolated)? Must I write them down in the some order? And how does OpenGl interpret these variables if I write:
vtxs:
out float x;
out vec4 mvp;
frgs:
in vec4 mvp;
in float x;
in double newvar;
Note: I shuffled the var types and there is 1 more in var in frgs then out vars in vtxs.
I see that location spec in the layout list is a way to assign a ... address? ... to a variable but I have an ancient netbook doesnt supporting such a variable decorator.
and as a tip: do you know some sort of debugging shaders? i mean, in cpu programs you can add some printfs but i didnt see such a func in glsl...
So, summarized, that are my questions:
What the heck do you specify with the layout(location=...) what consequences are there concerning the shader?
How does the value matching/association between various shader stages work? With and without that "location="?
debugging glsl shaders
Upvotes: 0
Views: 3082
Reputation: 22890
By default the inputs and outputs are matched by name between interfaces. For the vertex shader inputs, the default 'automatic' assignment of indexes is arbitrary, in the sense that it may differ between implementations.
The layout
qualifier allow to explicitly specify both the storage type and location of a input\output. Because of the automatic assignment of vertex inputs is arbitrary, you should use the layout
location in GLSL or the function glBindAttribLocation
to guarantee that apples are apples and oranges oranges.
So the layout
specification is very common in vertex shaders. But it can be used between any interface. For instance, if you didn't used the same name for the vec4
and float
, you would have done
vtxs:
layout(location = 0) out float x;
layout(location = 1) out vec4 mvp;
frgs:
layout(location = 0) in float y;
layout(location = 1) in vec4 pvm;
Now any input which is not present in the interface will break the pipeline. if you use a new variable
in double newvar;
then glLinkProgram
will fail.
Debugging:
The first debugging step is to check the status shader compilation and linking. On failure you can retrieve the error using glGetShaderInfoLog
.
//compilation
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
GLchar infoLog[512];
glGetShaderInfoLog(shader, 512, NULL, infoLog);
}
//program
glLinkProgram(shaderProgram);
GLint success;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if(!success)
{
GLchar infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
}
You can also
Upvotes: 3
Reputation: 369
By default the variables between stages get matched by name.
For the location, you can conceptually look at the data passed between stages as an array of vec4's. Then location is the index of the array which we use to pass that variable.
Types larger than a vec4 get multiple consecutive locations. For newer opengl versions (or ARB_enhanced_layouts) these is also a component layout-qualifier to pack values more closely in that vec4 array.
I am not sure how locations get assigned when matching by name and location is mixed.
Upvotes: 1