proper glUniform use

Started by
9 comments, last by krienie 12 years, 7 months ago
Hey all,

I'm kind of new to openGL and GLSL, so I"m not that familiar with all the proper uses yet. Like glUniform.

So here's my sitiuation: I'm currently working on a game engine that uses openGL.
I've made a DisplayObject that can render out 3D object from data stored in VBO's and a GLSL shader. It also uses a home-made matrix class for storing model-view, normal and modelview-projection matrices which the GLSL shader can use.

I"m currently reading through the OpenGL Shading Language book (orange book) and in there the writers state that uniform attributes should only be used with data that doesn't change frequently. So what I did is declare the matrices in the shader as uniforms and made a neat updateMatrices() function for my DisplayObject class that is called everytime a transformation is done to the object (for example when it translates or rotates). This function updates the matrices and then sends the new information to the GLSL shader using glUniform. Now this all works just fine when using one object, but when I introduce a second object or more, all the objects are snapped to the coordinates and orientation of the object that did the last transformation.
After some time of debugging I was able to fix this by calling chop the glUniform calls out of updateMatrices and call just before every object is drawn instead. Even though this works, I'm really doubting if I did the right thing here, because what I'm now doing is sending matrix data to the shader even though the values didn't change.

void DisplayObject::render()
{
if ( readyToRender )
{
glBindVertexArray(vaoName);

/* send new matrices to the shaderprogram */
glUniformMatrix4fv(glGetUniformLocation(program, "mvMatrix"), 1, GL_FALSE, modelmatrix.data);
glUniformMatrix4fv(glGetUniformLocation(program, "normMatrix"), 1, GL_FALSE, normalMatrix.data);

/* send new modelview-projection matrix to the shaderprogram */
modelmatrix = modelmatrix * *projectionmatrix;
glUniformMatrix4fv(glGetUniformLocation(program, "mvpMatrix"), 1, GL_FALSE, modelmatrix.data);

glDrawElements(GL_TRIANGLES, bufferSize[index], GL_UNSIGNED_INT, 0);
}
}


So my question now is: am I doing the right thing and if not: how do you guys suggest I should send the matrix data to the shader?

Many thanks in advance ;)
Advertisement
I suppose using build-in OpenGL uniform variables is much better one ("mvMatrix" -> "gl_ModelViewMatrix", "normMatrix" - > "gl_NormalMatrix",...).where "gl_ModelViewMatrix" holds GL_MODELVIEW matrix state and so on 





I suppose using build-in OpenGL uniform variables is much better one ("mvMatrix" -> "gl_ModelViewMatrix", "normMatrix" - > "gl_NormalMatrix",...).where "gl_ModelViewMatrix" holds GL_MODELVIEW matrix state and so on


Those built-ins are deprecated in 4.2+....
So what I did is declare the matrices in the shader as uniforms and made a neat updateMatrices() function for my DisplayObject class that is called everytime a transformation is done to the object (for example when it translates or rotates).[/quote]

You're probably running into the problem of two objects using the same shader. If you use more than one object with a given shader, then you need to update the matrices each time you change between one and the other.


After some time of debugging I was able to fix this by calling chop the glUniform calls out of updateMatrices and call just before every object is drawn instead. Even though this works, I'm really doubting if I did the right thing here, because what I'm now doing is sending matrix data to the shader even though the values didn't change.
[/quote]
This sounds like a reasonable thing to do to me. Obviously you don't want to send data that you don't have to, but I can't imagine many cases where a single object gets a shader all to itself. I think just updating the matrices before drawing is not a big deal, unless you have unusual use case where it becomes impractical.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

...
This sounds like a reasonable thing to do to me. Obviously you don't want to send data that you don't have to, but I can't imagine many cases where a single object gets a shader all to itself. I think just updating the matrices before drawing is not a big deal, unless you have unusual use case where it becomes impractical.


That's what I thought. It seems a bit stupid to have two objects have it's own shader, each doing the exactly the same thing.
I'll leave it the way it is then. Thanks for the replies everyone ;)
Don't call glGetUniformLocation. It is probably slow.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
[font="Arial"]You probably misinterpreted the "not changing frequently" part, uniforms are described as not changing frequently because they're the same for the whole draw call unlike vertex attributes which change every vertex. Also in reply to v-man calling glGetUnitformLocation is a call you are suggested to do load time rather than run time, you want to profile this on your target platform though, in my case it's lots faster to just make the calls than to map them.[/font]

[quote name='FXACE' timestamp='1314137786' post='4852989']
I suppose using build-in OpenGL uniform variables is much better one ("mvMatrix" -> "gl_ModelViewMatrix", "normMatrix" - > "gl_NormalMatrix",...).where "gl_ModelViewMatrix" holds GL_MODELVIEW matrix state and so on


Those built-ins are deprecated in 4.2+....
[/quote]
There are many things deprecated in newest versions from classic GLSL. I'm old man if I don't know what's new in latest version of GLSL... 




Also, I'm agree with V-Man.


[font="Arial"]You probably misinterpreted the "not changing frequently" part, uniforms are described as not changing frequently because they're the same for the whole draw call unlike vertex attributes which change every vertex. [/font]


The term 'not changing frequently' applies just as well to something you set once during all your draw calls in a scene as it would to per-object.

In fact if your MVP matrix is only set once and never update during a scene/frame render setting it multiple times per scene/frame is wasteful and something which should be avoided (CPU time and GPU time overhead).

Now, I'm not saying there IS a way to use GLSL like that, although I hope there is because if not then that's a *facepalm* right there, but there really should be a way of doing it. My GLSL is just too rusty right now to point out that method if it exists :)

[quote name='Murdocki' timestamp='1314209993' post='4853319']
[font="Arial"]You probably misinterpreted the "not changing frequently" part, uniforms are described as not changing frequently because they're the same for the whole draw call unlike vertex attributes which change every vertex. [/font]


The term 'not changing frequently' applies just as well to something you set once during all your draw calls in a scene as it would to per-object.

In fact if your MVP matrix is only set once and never update during a scene/frame render setting it multiple times per scene/frame is wasteful and something which should be avoided (CPU time and GPU time overhead).

Now, I'm not saying there IS a way to use GLSL like that, although I hope there is because if not then that's a *facepalm* right there, but there really should be a way of doing it. My GLSL is just too rusty right now to point out that method if it exists :)
[/quote]

Of course there is. UBO = Uniform buffer object
Which is basically a VBO for uniform values.
You need to make a GL 3.1 context to use it. Just shuv a GL_UNIFORM_BUFFER into your VBO function calls and get the location from your shader object.
http://www.opengl.or...entation/specs/

and you update the whole fucking uniform block inluding your MVP matrix in one go.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

This topic is closed to new replies.

Advertisement