PDA

View Full Version : How to pass an array to a shader?



Patsch
08-22-2017, 01:33 PM
I try this for 3 days now and spend about 6 hours searching the net for a simplistic and working example:

How on earth, can I pass an array to my shader by uniform? Can someone give me a brief example of how the syntax in C++ AND GLSL is supposed to look like?

I only succeed in setting the first element of the Array, but cant set any higher indices.

Dark Photon
08-23-2017, 05:14 AM
See:
* GLSL_Uniform#Uniform_management (https://www.khronos.org/opengl/wiki/GLSL_Uniform#Uniform_management)
* GLSL_:_common_mistakes#How_to_use_glUniform (https://www.khronos.org/opengl/wiki/GLSL_:_common_mistakes#How_to_use_glUniform)

Note the use of functions which set multiple elements which end with a "v" (e.g. glUniform4fv (https://www.khronos.org/opengl/wiki/GLAPI/glUniform)).

Alfonse Reinheart
08-23-2017, 08:45 AM
I try this for 3 days now and spend about 6 hours searching the net for a simplistic and working example:

How on earth, can I pass an array to my shader by uniform? Can someone give me a brief example of how the syntax in C++ AND GLSL is supposed to look like?

I only succeed in setting the first element of the Array, but cant set any higher indices.

You've asked this question several times in different locations. Are you sure you're not encountering a driver bug? What hardware are you using?

Patsch
08-23-2017, 06:08 PM
You've asked this question several times in different locations. Are you sure you're not encountering a driver bug? What hardware are you using?

I asked a somewhat related question on the stack. But the question on the stack was about my specific code, and all suggestions about fixing it did not work. Thats why I wanted to ask for a simple working example, since I didnt find any way of fixing my own code. Since Stack does basically not allow that kind of question, I asked it here. Hope that was okay.
The problem is most probably not related to my hardware, since I tried it on my GeForce GTX 1050Ti, my Intel Onboard something, and made a friend check for the behaviour with the same unpleasent results on a GeForce GTX 960. I recognized different behaviour with different shader versions (330 made all vertices multiplied by the undefined array entries stuck on the middle of the screen, 220 rendered the whole model in another position and 420 didnt render it at all)



See:
* GLSL_Uniform#Uniform_management
* GLSL_:_common_mistakes#How_to_use_glUniform

Note the use of functions which set multiple elements which end with a "v" (e.g. glUniform4fv).



I did read both documents multiple time, yet I cant get it to work.

If I change the shader to multiple uniforms and asign each uniform a mat4 it works though, giving expected results, so my input code is most probably alright.

Dark Photon
08-24-2017, 05:26 AM
If I change the shader to multiple uniforms and asign each uniform a mat4 it works though, giving expected results, so my input code is most probably alright.

...for the case where you're using non-array uniforms, yes. Probably so.

However, it doesn't establish that for the array uniform case.

Post a short, standalone GLUT test program which illustrates your problem here. That'll make it easy for a number of folks to try your code, give you results feedback, and probably tell you how to fix your problem. Here's a shell to copy/paste your code into:


//-----------------------------------------------------------------------
// Stand-alone GLUT test program
//-----------------------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>

//-----------------------------------------------------------------------

void checkGLError( const char hdr[] )
{
int err = glGetError();
if( err )
{
fprintf(stderr, "ERROR %s: %s\n", hdr, gluErrorString(err));
exit(1);
}
}

//-----------------------------------------------------------------------

void init()
{
//------------------------------------------------------------
// Put your GL init code here.
//------------------------------------------------------------

// glGenBuffers( 1, &Vbo_handle );
// etc.

checkGLError( "init" );
}

//-----------------------------------------------------------------------

void reshape( int width, int height )
{
glViewport(0, 0, width, height);
}

//-----------------------------------------------------------------------

void display()
{
// Clear screen
glClearColor( 0.1f, 0.1f, 0.43f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

//------------------------------------------------------------
// Put your GL draw code here.
//------------------------------------------------------------

// Swap
glutSwapBuffers();

// Cause display() to be called again.
glutPostRedisplay();
checkGLError( "End of display()" );
}

//-----------------------------------------------------------------------

void keyboard( unsigned char key, int x, int y )
{
switch (key)
{
case 27: // ESC quits
exit(0);
break;
}
}

int main( int argc, char** argv )
{
// Init GLUT
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutCreateWindow( argv[0] );

glutKeyboardFunc( keyboard );
glutDisplayFunc( display );
glutReshapeFunc( reshape );

glutReshapeWindow( 400,400 );

// Init GLEW
GLenum err = glewInit();
if ( err != GLEW_OK )
{
// Problem: glewInit failed, something is seriously wrong.
fprintf( stderr, "Error: %s\n", glewGetErrorString(err) );
exit(1);
}

printf( "GL_RENDERER = %s\n", glGetString( GL_RENDERER) );

init();

glutMainLoop();
return 0;
}

Patsch
08-24-2017, 04:02 PM
...for the case where you're using non-array uniforms, yes. Probably so.

However, it doesn't establish that for the array uniform case.

Post a short, standalone GLUT test program ...


Thanks a lot for your advice! I actually got the test program up and running with the very same syntax I am using in my other project. Everything works fine, all array slots are set. Yet, the other project still doesnt work, double checked pretty much everything, "cout"ed my matrices, checked again with unique non-array uniforms:


int jointLoc1 = glGetUniformLocation(shaderID, "jointTransforms1");
glUniformMatrix4fv(jointLoc1, 1, GL_FALSE, &finalBoneTransformContainer[0].mat[0][0]);

int jointLoc2 = glGetUniformLocation(shaderID, "jointTransforms2");
glUniformMatrix4fv(jointLoc2, 1, GL_FALSE, &finalBoneTransformContainer[1].mat[0][0]);
works.



glUniformMatrix4fv(jointLoc, 20, GL_FALSE, &finalBoneTransformContainer[0].mat[0][0]);

still doesnt, while it does in the test program.


Is it actually possible, that there is a difference in using GLFW and GLAD (my project which doesnt work), and using GLEW and GLUT? Thats pretty much the last possible difference I can find.

Edit: Tried to substitute GLAD for GLEW, didnt change anything.

john_connor
08-24-2017, 05:23 PM
did you read the article DarkPhoton liked to in his post above ?
https://www.khronos.org/opengl/wiki/GLSL_:_common_mistakes#How_to_use_glUniform

did you read the function's description (completely) ?
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml

did you check for GL errors ? do you get any ?
what error(s) ? which function throws the error ?

did you try to create a debug context ? maybe the GL debug callback gives you a hint in case you're doing something wrong ...

Patsch
08-24-2017, 05:53 PM
I finally(!!!) solved this enigma :D
I realized, that my joint indices were messed up by glVertexAttribPointer(4, 4, GL_INT... expected the GL_INT to define the type, missing the I in the function call. While at the same time using ivec4 as shader input. Changing shader input to vec4 made things work out. Trying to set the VAP to int though.

Thanks for everyones attempt to give me a hand!

mhagain
08-24-2017, 10:28 PM
This is why it's important to say what you're trying to do as well as how you're trying to do it. If your OP had told us this was happening when indexing into an array of bone matrices, you would have probably had the solution within the first 2 replies, because this is actually an extremely common mistake.