OpenGL - glUniformBlockBinding after or before glLinkProgram? - c++

I'm trying to use Uniform Buffer Objects to share my projection matrix accross different shaders (e.g., Deferred pass for solid objects and Forward pass for transparent ones). I think that I'll add more data to the UBO later on, when the complexity grows up. My problem is that the Red Book says:
To explicitly control a uniform block's binding, call glUniformBlockBinding() before calling glLinkProgram().
But the online documentation says:
When a program object is linked or re-linked, the uniform buffer object binding point assigned to each of its active uniform blocks is reset to zero.
What am I missing? Should I bind the Uniform Block after or before the linking?
Thanks.

glUniformBlockBinding​ needs the program name and the index where to find the block in this particular program.
void glUniformBlockBinding​( GLuint program​, GLuint uniformBlockIndex​, GLuint uniformBlockBinding​ );
uniformBlockIndex​ can be obtained by calling glGetUniformBlockIndex on the program.
GLuint glGetUniformBlockIndex​( GLuint program​, const char *uniformBlockName​ );
From the API (http://www.opengl.org/wiki/GLAPI/glGetUniformBlockIndex):
program​ must be the name of a program object for which the command glLinkProgram​ must have been called in the past, although it is not required that glLinkProgram​ must have succeeded. The link could have failed because the number of active uniforms exceeded the limit.
So the correct order is:
void glLinkProgram(GLuint program​);
GLuint glGetUniformBlockIndex​( GLuint program​, const char *uniformBlockName​ );
void glUniformBlockBinding​( GLuint program​, GLuint uniformBlockIndex​, GLuint uniformBlockBinding​ );

Related

How to get shader storage block's variable offset when using layout(packed) or layout(shared) in OpenGL?

If I have a shader storage block defined in GLSL like this:
buffer test_block
{
type1 var1;
type2 var2;
type3 var3;
};
How to get the offset of one of the variable in this block?
We know that if it is a uniform block just like this:
uniform test_block
{
type1 var1;
type2 var2;
type3 var3;
};
we can get offset in this way, for example get the offset of var2:
char[] var2_name = "var2";
int var2_index;
glGetUniformIndices(program_id, 1, &var2_name, &var2_index);
int var2_offset;
glGetActiveUniformsiv(program_id, 1, &var2_index, GL_UNIFORM_OFFSET, &var2_offset);
// then var2_offset is what you want
This is for uniform block. But I can't find any tutorial of getting offset of shader storeage block variable's offset.
(Don't tell me to use std140 or std430, I know this way. I want to write program don't depend on specific memory layout. Just get the offset programmatically.)
I tried to find functions jusk like glGetUniformIndices and glGetActiveUniformsiv which is suite for shader storage block. But there is no such functions.
I expect one way to get shader storage block variable's offset programmatically just like getting uniform block variable's offset.
The program interface query API is a generic tool for querying any of the external interface components of a program. Inputs, outputs, uniforms, and yes, storage buffers. There are separate APIs for many of these interfaces (like glGetUniformIndices), but a generic one was created that accounts for all of the existing ones.
As well as SSBOs.
The different kinds of queryable properties are called "interfaces". Properties about uniform blocks are queried through the GL_UNIFORM_BLOCK interface, but the members of a uniform block are queried through the GL_UNIFORM interface. Similarly, the GL_SHADER_STORAGE_BLOCK is for querying properties of a storage block, but properties of the actual members of the block are queried through the GL_BUFFER_VARIABLE interface.
So the program interface query equivalent of your uniform querying code would be:
GLuint var2_index = glGetProgramResourceIndex(program_id, GL_UNIFORM, "var2");
GLenum props[] = {GL_OFFSET};
GLint var2_offset;
glGetProgramResourceiv(program_id, GL_UNIFORM, var2_index, 1, props, 1, nullptr, &var2_offset);
The SSBO equivalent would be:
GLuint var2_index = glGetProgramResourceIndex(program_id, GL_BUFFER_VARIABLE, "var2");
GLenum props[] = {GL_OFFSET};
GLint var2_offset;
glGetProgramResourceiv(program_id, GL_BUFFER_VARIABLE, var2_index, 1, props, 1, nullptr, &var2_offset);

How do I pass uniforms between different shader programs in OpenGL?

I'm wondering if there is a way to communicate data between two separate shader programs.
I have one geometry shader that uses a uniform float, and I would like to send the value of that float to a fragment shaders that is used by another program.
Is this possible? I know that OpenGL uses pre-defined global variables, but is there a way to create my own?
Geometry shader from program 1:
uniform float uTime;
Fragment shader from program 2:
if (uTime > 0.){
...
}
I would like to send the value of that float to a fragment shaders that is used by another program. Is this possible?
There is no "interface" between different shader programs.
If you want to use the same uniform in your second shader program, then you simply need to declare and upload that same uniform in your second shader program, just like you did it for your first shader program.
(I am not getting into uniform buffer objects for the rest of this answer, since you used top-level uniform variables in the unnamed block. But, you can use a uniform buffer object holding your uniform values, which you then bind to both shader programs.)
So: Declare the uniform in the fragment shader of your second shader program just like you did with the geometry shader of your first shader program:
uniform float uTime;
void main(void) {
...
if (uTime > 0.){
...
}
...
}
Then, as usual, compile and link that program and obtain the location of the uniform in that second shader program via glGetUniformLocation() once:
// do once:
GLint uTimeLocationInSecondShaderProgram = glGetUniformLocation(yourSecondShaderProgram, "uTime");
and then send a value to the uniform via e.g. glUniform1f() whenever the value changes (e.g. once per render loop iteration):
// do before drawing:
float time = ...; // <- whatever time you also used in your first shader program
glUseProgram(yourSecondShaderProgram);
glUniform1f(uTimeLocationInSecondShaderProgram, time);

accessing Objects in Multiple Functions C++

I was seperating my main function from it's loop by creating a new function loop. Now I got the problem that some objects I created in main can't be accessed in loop. Creating multiple function parameters in loop is not an option because it will end in like 30 parameters and more for each Shader and other objects. So I made the objects global:
main.cpp
Shader light("Shaders/light.shader");
Shader depth("Shaders/depth.shader");
Shader.cpp
Shader::Shader(const std::string& filePath)
{
source = parseShader(filePath);
if (shaderGeometry)
ID = createShader(source.vertexSource, source.fragmentSource, source.geometrySource);
else
ID = createShader(source.vertexSource, source.fragmentSource);
use();
}
The problem here is that parsing the file paths outside of a function causes an exception at:
int Shader::createShader(const std::string& vertexShader, const std::string& fragmentShader)
{
program = glCreateProgram(); //<-- HERE
//some further code...
}
The vertexShader and fragmentShader are parsed correctly, so there is no problem.
I guess the exception is thrown because the Shaders need to be created inside a function where the GL function pointers are loaded before.
I tried to play around with extern. But something like this just leaves a compiling error:
global variable
extern Shader light;
extern Shader depth;
in the function
int main()
{
Window wnd(width, height);
Shader light("Shaders/light.shader");
Shader depth("Shaders/depth.shader");
wnd.loop();
//some further code
return 0;
}
Swithing The extern Shader light to the Metod and reversed would end up in the same error from before.
I maybe could access the shader with a getter Method and some kind of Array that safes every vertex, fragment and geometry Shader but maybe there is a more simple way and i just missed something.

OpenglES 2.0 Vertex Shader Attributes

I've read in tutorials that the bare minimum a vertex shader needs is define below:
attribute vec3 v3_variable;
attribute vec3 v3Pos;
void main()
{
gl_Position = v3Pos;
}
OpenglES passes to the shader vertex data to v3Pos but the name of this variable can actually be anything, other tutorials name it a_Position, a_Pos, whatever~.
So my question is, how does OpenglES know that when I call glVertexAttribPointer() it knows that it should put that data into v3Pos instead of v3_variable?
There are two methods of identifying which attributes in your shaders get 'paired' with the data you provide to glVertexAttribPointer. The only identifier you get with glVertexAttribPointer is the index (the first parameter), so it must be done by index somehow.
In the first method, you obtain the index of the attribute from your shader after it is compiled and linked using glGetAttribLocation, and use that as the first parameter, eg.
GLint program = ...;
GLint v3PosAttributeIndex = glGetAttribLocation(program, "v3Pos");
GLint v3varAttributeIndex = glGetAttribLocation(program, "v3_variable");
glVertexAttribPointer(v3PosAttributeIndex, ...);
glVertexAttribPointer(v3varAttributeIndex, ...);
You can also explicitly set the layout of the attributes when authoring the shader (as #j-p's comment suggests), so you would modify your shader like so:
layout(location = 1) in vec3 v3_variable;
layout(location = 0) in vec3 v3Pos;
And then in code you would set them explicitly:
glVertexAttribPointer(0, ...); // v3Pos data
glVertexAttribPointer(1, ...); // v3_variable data
This second method only works in GLES 3.0+ (and OpenGL 3.0+), so it may not be applicable to your case if you are only using GLES 2.0. Also, note that you can use both of these methods together. Eg. even if you explicitly define the layouts, it doesn't restrict you from querying them later.
Okay, so on the app side you will have a call that looks like either
glBindAttribLocation(MyShader, 0, "v3Pos");
(before you link the shader) or
vertexLoc = glGetAttribLocation(MyShader, "v3Pos");
After you link the program.
Then the first element of the glVertexAttribPointer call will either be 0 or vertexLoc.
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, sizeof(MyVertex), BUFFER_OFFSET(0));
In short, the gl linker is going to either assign v3Pos it's own location in memory, or go off of what you tell it. Either way you are going to have to perform some interaction with the shader in order to interact with the attribute.
Hope that helps

OpenGL 3.3 - How to change tesselataionlevel during run time?

How can I change the tesselation leveln during runtime?
My only idea is to create a bufferobject with only one variable, which I have to pass through... Are there any better solutions?
I have a tesselation control shader file which works fine:
[...]
void main()
{
if(gl_InvocationID==0)
{
gl_TessLevelInner[0]= 5.0;
gl_TessLevelOuter[0]=5.0;
gl_TessLevelOuter[1]=5.0;
gl_TessLevelOuter[2]=5.0;
}
gl_out[gl_InvocationID].gl_Position =gl_in[gl_InvocationID].gl_Position;
}
You can pass the tessellation values as uniforms or (as the values are constant for each draw call) bypass the tessellation control shader altogether. If no TCS is linked to your shader program, the values supplied with -
GLfloat outer_values[4];
GLfloat inner_values[2];
// outer_values and inner_values should be set here
glPatchParameterfv​(GL_PATCH_DEFAULT_OUTER_LEVEL​, outer_values​​);
glPatchParameterfv​(GL_PATCH_DEFAULT_INNER_LEVEL​, inner_values​​);
will be used instead. In this case the tessellation evaluation shader uses the values output from the vertex shader.