PDA

View Full Version : Problem with passing matrices with Uniform Buffer to shader



kubusabadi
07-13-2015, 05:53 AM
Hi! I'm learning OpenGL from OpenGL SuperBible (6 ed.) and I tried to wrote some code to practice Uniform Buffer Objects. I have some troubles with very basic code, I just want to pass matrix to vertex shader.

Vertex Shader:


static const GLchar* vs[] = {
"#version 430 core \n"
" \n"
"layout (location=0) in vec4 position; \n"
" \n"
"layout (binding = 1) uniform TransformBlock \n"
"{ \n"
" float curTime; \n"
" float mvp[4]; \n"
"} transformBlock; \n"
" \n"
"out vec4 testColor; \n"
" \n"
"void main(void) \n"
"{ \n"
" testColor = vec4(0.0, transformBlock.mvp[0], 0.0, 1.0);\n"
" gl_Position = position; \n"
"} \n"
};


Fragment Shader:


static const GLchar* fs[] = {
"#version 430 core \n"
" \n"
"in vec4 testColor; \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = testColor; \n"
"} \n"
};


And buffers initialization:

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

vector<GLfloat> vertices = {
-0.5f, -0.5f, -0.1f, 1.0f,
0.5f, 0.5f, -0.1f, 1.0f,
0.5f, -0.5f, -0.1f, 1.0f
};

glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);

program = createShaderProgram();

glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);

static const char* uniformNames[2] = {
"TransformBlock.curTime",
"TransformBlock.mvp"
};

GLuint uniformIndices[2];

glGetUniformIndices(program, 2, uniformNames, uniformIndices);

GLint uniformOffsets[2];
GLint arrayStrides[2];
GLint matrixStrides[2];

glGetActiveUniformsiv(program, 2, uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets);
glGetActiveUniformsiv(program, 2, uniformIndices, GL_UNIFORM_ARRAY_STRIDE, arrayStrides);
glGetActiveUniformsiv(program, 2, uniformIndices, GL_UNIFORM_MATRIX_STRIDE, matrixStrides);

GLubyte* buffer = new GLubyte[2048];

*((float*)(buffer + uniformOffsets[0])) = 1.0f;

GLfloat vec[] = { 1.0f, 0.0f, 1.0f, 1.0f};

GLuint offset = uniformOffsets[1];
for (int i = 0; i < 4; i++)
{
*((float*)(buffer + offset)) = vec[i];
offset += arrayStrides[1];
}

glBufferData(GL_UNIFORM_BUFFER, sizeof(buffer), buffer, GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo);

//delete[] buffer;

mvp meant to be a 4x4 matrix, but no triangle was displayed, so I switched to an array to do some testing.

When I changed passing data to glSubBufferData I could pass vector or single float as they don't use strides and triangle was rendered. When I used matries or array of floats, nothing was rendered.

Could you help?

Alfonse Reinheart
07-13-2015, 09:02 AM
`buffer` is a pointer. If you ask for the size of a pointer, you get the size of a pointer. Just use a `std::vector` if you want to keep track of the size of the array.

kubusabadi
07-13-2015, 10:37 AM
Thanks alot! I'm pretty sure I wouldn't find this mistake for many hours. Cheers!