Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uniform Buffer Objects in oglplus? #112

Open
StepUpSenpai opened this issue Apr 29, 2015 · 8 comments
Open

Uniform Buffer Objects in oglplus? #112

StepUpSenpai opened this issue Apr 29, 2015 · 8 comments
Assignees

Comments

@StepUpSenpai
Copy link

Hi again,
I have a valid, minimal OpenGL code that produces desired results:

        float test[] = { 0.5f, 0.0f, 0.0f, 0.0f };
    GLint programID; 
    glGetIntegerv(GL_CURRENT_PROGRAM, &programID);

    GLuint blockIndex = glGetUniformBlockIndex( programID  , "MatrixBlock");
    glUniformBlockBinding(programID, blockIndex, 1);

    GLuint UBOindex;
    glGenBuffers(1, &UBOindex);
    glBindBuffer(GL_UNIFORM_BUFFER, UBOindex);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(test), test, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_UNIFORM_BUFFER, 1, UBOindex);

In the vertex shader code I simply translate the vertex position by that test vector that I've got in "MatrixBlock" uniform block.

The problems start when I try to express the same thing using oglplus:

        float test[] = {0.5f,0.0f,0.0f,0.0f};
        oglplus::UniformBlock uniblock(program, "MatrixBlock"); 
    uniblock.Binding(1);

       oglplus::Buffer UBO;
    UBO.Bind(oglplus::Buffer::Target::Uniform);
        oglplus::Buffer::Data(oglplus::Buffer::Target::Uniform, sizeof(test), test);
    UBO.BindBaseUniform(1);


When I switch to this oglplus-based code my geometry simply doesn't get translated at all in vertex shader (as if there are only zeroes in the test vector).

@matus-chochlik matus-chochlik self-assigned this Apr 30, 2015
@matus-chochlik
Copy link
Owner

You don't specify the BufferUsage parameter in the OGLplus code (but I'm not sure yet if this is the reason it does not work)

but try the following:

oglplus::Buffer::Data(oglplus::Buffer::Target::Uniform, sizeof(test), test, oglplus::BufferUsage::DynamicDraw);

@StepUpSenpai
Copy link
Author

Adding the usage didn't work.

Also, sorry if that's not the right place to ask this, but I couldn't find anything in the documentation.
One of the features of oglplus is supposed to be the interoperability with "raw" opengl instructions but I can't find any way to retrieve the "raw" program id that I would be able to pass to functions like above glUniformBlockBinding,
By this I mean something like:
glUniformBlockBinding(program.getID(), blockIndex, 1);
where "program" is of type oglplus::Program.

Of course I can do program.use() and then retrieve the id with a regular opengl call like above glGetIntegerv(GL_CURRENT_PROGRAM, &programID);
but it doesn't seem like a elegant and/or proper way to do this

It looks like this issue is related to binding operations so if there was a way to retrieve programID from oglplus::Program and bufferID from oglplus::Buffer than I could resolve this issue by using the Program and Buffer classes like normal, then getting IDs from them and passing them to raw binding instructions (glBindBufferBase and glUniformBlockBinding).

@matus-chochlik
Copy link
Owner

Hmm, OK I'll try to create a working code using UBOs and have a look at this.

In order to get the GL name of a wrapped object (program, shader, texture,...) You can use the GetGLName(program) or GetName(program) function.

@matus-chochlik
Copy link
Owner

I have a question: do you issue the GL draw calls in the same function where the code above is executed or somewhere else?

@StepUpSenpai
Copy link
Author

I was issuing the draw calls in separate function, of course after binding all the buffers first.
Currently my code looks like this:

void Camera::uploadMatrices()
{

    if (!Camera::initialized)
        throw new std::exception("Can't upload matrices when camera is not initialized.");

    oglplus::ModelMatrixf MVP = Camera::projection * Camera::zoomOut *  Camera::view *  Camera::baseTranslation;

    UBO->Bind(oglplus::Buffer::Target::Uniform);
    oglplus::Buffer::Data(oglplus::Buffer::Target::Uniform, sizeof(GLfloat)*MVP.Size(), MVP.Data(),oglplus::BufferUsage::DynamicDraw);  
    glBindBufferBase(GL_UNIFORM_BUFFER, 1, oglplus::GetGLName(*UBO));
}

and in my program class:

void GLSLProgram::bindUBO()
{
    GLint programID = oglplus::GetGLName(this->program);
    GLuint blockIndex = glGetUniformBlockIndex(programID, "MatrixBlock");
    glUniformBlockBinding(programID, blockIndex, 1);
}

Drawing with:

void Domain::draw()
{
    glLineWidth(2.0f);

    this->program.useThisProgram();
    this->VAO.Bind();
    this->VBO.Bind(oglplus::Buffer::Target::Array);
    this->IBO.Bind(oglplus::Buffer::Target::ElementArray);


    oglplus::Context().DrawElements(oglplus::PrimitiveType::Lines, 24, oglplus::DataType::UnsignedShort);

}

This way it works fine. Sorry, but I couldn't spend more time experimenting with binding in oglplus itself and ended up using raw opengl calls. I am also really sorry for replying so late.

@matus-chochlik
Copy link
Owner

Hi, sorry for the late response, I've been rather busy lately.

The problem was probably caused by the fact that You created a buffer object in one function, set it up and uploaded the data,

oglplus::Buffer UBO;
UBO.Bind(oglplus::Buffer::Target::Uniform);
oglplus::Buffer::Data(oglplus::Buffer::Target::Uniform, sizeof(test), test);
UBO.BindBaseUniform(1);

but when the process went out of scope of that function, the UBO buffer got destroyed and the underlying GL object deleted. There are some examples using UBOs and I've tested them on several machines and everywhere they work fine.

@jose-villegas
Copy link

Are there more examples of UniformBuffers except for examples/standalone/025_bitmap_font_text.cpp ?

I'm doing exactly the same but trying to update a more complex uniform block with a array of Light structs.

struct Attenuation
{
    float constant;
    float linear;
    float quadratic;
};

struct Light {
    float angleInnerCone;
    float angleOuterCone;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;

    vec3 position;
    vec3 direction;

    Attenuation attenuation;

    uint lightType;
};
...
layout (std140) uniform AvailableLights {
    Light light[N_LIGHTS];
};

I have in the C++ side a identical class to that struct, and a vector of that class. The rest is exactly the same, I bind the uniform buffer to the program, and use a uniform buffer object to pass the vector of Light using the same binding point but it is not working. I may end up using raw C OpenGL to do this or just standard uniforms.

@matus-chochlik
Copy link
Owner

Hi, there are several other examples using UBOs:

oglplus/021_overdraw.cpp
oglplus/029_gpu_sort_tfb.cpp
oglplus/032_bar_grid.cpp
oglplus/031_motion_blur.cpp
oglplus/014_multi_cube_ub.cpp
oglplus/031_neon.cpp
oglplus/031_fog.cpp
oglplus/032_object_tracking.cpp

HTH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants