PDA

View Full Version : Problems getting UniformBufferObject working



ParticlePeter
12-21-2011, 08:31 AM
Hi,

I don't manage to get UBOs to work. I think I set up everything properly as I don't get any GL Errors. In my update code I can query the value(s) of the uniform buffer, but my Shader does not react to this value(s). I am trying this with just one float, one VertexArrayObject and one program for debugging purpose, but I also failed with float[4] uniform and vec4 respectively ( just in case I am not getting std140 right ).
What do I miss ?


Vertex Shader:


#version 330 core
// Uniforms
layout( std140 ) uniform Common {
float Time ;
} ;

// Input Attribs
in vec3 inVertex ;

// Main
void main( void ) {
vec3 pos = inVertex ;
pos.x += sin( Time ) ;
gl_Position = vec4( pos , 1.0 ) ;
}


Setup:


// Time is a class member
glGenBuffers( 1 , & uboName );
glBindBuffer( GL_UNIFORM_BUFFER , uboName ) ;
glBufferData( GL_UNIFORM_BUFFER , sizeof( Time ) , NULL , GL_DYNAMIC_DRAW ) ;

// programName is a class member storing the compiled program id
GLint uboBlockIndex = glGetUniformBlockIndex( programName , "Common" ) ;
glUniformBlockBinding( programName , uboBlockIndex , uboName ) ;
glBindBufferRange( GL_UNIFORM_BUFFER , uboBlockIndex , uboName , 0 , sizeof( Time ) ) ;
glBindBuffer( GL_UNIFORM_BUFFER , 0 ) ;


Update:


Time = updateTime() ;
glBindBuffer( GL_UNIFORM_BUFFER , uboName ) ;
glBufferSubData( GL_UNIFORM_BUFFER , 0 , sizeof( Time ) , & Time ) ;

// Testing the Buffer Data
GLfloat progTime ;
glGetBufferSubData( GL_UNIFORM_BUFFER , 0 , sizeof( progTime ) , & progTime ) ;
glBindBuffer( GL_UNIFORM_BUFFER , 0 ) ;
std::cout << "Time in Shader : " << progTime << std::endl ; // Works

Alfonse Reinheart
12-21-2011, 10:35 AM
The easiest way to tell if something is working is to write it directly out to the screen.

That being said, your problem is right here:


glUniformBlockBinding( programName , uboBlockIndex , uboName ) ;
glBindBufferRange( GL_UNIFORM_BUFFER , uboBlockIndex , uboName , 0 , sizeof( Time ) ) ;

That's not how it works. You don't attach the buffer object to the program. Nor do you bind the buffer to the block index fetched from the program.

Here is an explanation of how this all works. (http://www.arcsynthesis.org/gltut/Positioning/Tut07%20Shared%20Uniforms.html)

ParticlePeter
12-21-2011, 11:22 AM
Hi,

thank you for your reply, but I fear I'm not getting you.
Funny thing is that I was following exactly this tutorial to build the uniform buffer in the first place, but I do not see the difference in code which you're pointing out. Both the command are used in the tutorial the same way I use them, unless I'm to blind to see already ( possible after one day staring into this few lines of code ).
What do you mean exactly ? And what do you mean with "write it out to the screen" ? I checked the values of the variables used in the gl calls, they seem alright and no Errors thrown.

ParticlePeter
12-21-2011, 11:40 AM
Sorry, I should have posted the original code her, maybe you ( anybody ) could explain me the proper usage:

Code from Tutorial (http://www.arcsynthesis.org/gltut/Positioning/Tut07%20Shared%20Uniforms.html):


glUniformBlockBinding(
data.theProgram,
data.globalUniformBlockIndex,
g_iGlobalMatricesBindingIndex );


and


glBindBufferRange(
GL_UNIFORM_BUFFER,
g_iGlobalMatricesBindingIndex,
g_GlobalMatricesUBO, 0, sizeof( glm::mat4 ) * 2 );

Alfonse Reinheart
12-21-2011, 03:18 PM
Both the command are used in the tutorial the same way I use them

Let's compare:



glUniformBlockBinding( data.theProgram, data.globalUniformBlockIndex, g_iGlobalMatricesBindingIndex );


And



glUniformBlockBinding( programName , uboBlockIndex , uboName ) ;


`data.theProgram` and `programName` are both program objects. `data.globalUniformBlockIndex` and `uboBlockIndex` are uniform block indices queried from `glGetUniformBlockIndex`.

But `g_iGlobalMatricesBindingIndex` is just a global index, while `uboName` is an OpenGL uniform buffer object. These aren't the same thing.

Perhaps you remember this statement from the tutorial:


Your first thought might be that there would be a function like glUniformBuffer that takes a program, a uniform block index, and the uniform buffer to associate that block with. But this is not the case; attaching a uniform buffer to a program's block is more complicated.

Emphasis added.

The association between program uniform block and OpenGL uniform buffers is made by proxy, through an intermediary. These intermediaries are buffer object binding points. You tell the program which binding point to find its buffer in, and you bind the uniform buffer to that binding point so that it can find it.


And what do you mean with "write it out to the screen" ?

The screen. You know, the output from the fragment shader. You can write the value as the color, and then see if what you get on screen is what you expect from your shader. This is the most basic tool of shader debugging.

ParticlePeter
12-22-2011, 12:21 PM
Hi,

Thank you very much, it works now :-)
Also the trick to debug with colors is very helpful.

Cheers, searching for the Pivot of my Soul, PP !