-1
\$\begingroup\$

I'm a bit confused about the proper way to send a matrix from my code (C++) into a GLSL shader. My matrix object is stored in row major format in memory. If I use the following shader code it works ok.

#version 400 core

layout(location=0) in vec2 VertexPosition;

uniform vec3        VertexColor;
uniform mat3 rotation;

layout(location=0) out vec3 VertexOutputColor;

void main() {
    const vec3 tf_pos = rotation * vec3(VertexPosition, 1.0f);
    gl_Position = vec4(tf_pos, 1.0f);
    VertexOutputColor = VertexColor;
}

I set the value from my application like this : glUniformMat3fv(location, 1, GL_TRUE, (const float*) &matrix);

However, if I put the matrix in a uniform block like this :

#version 400 core

layout(location=0) in vec2 VertexPosition;

uniform vec3        VertexColor;

layout(binding = 0) uniform transforms {
    mat3 rotation;
};

layout(location=0) out vec3 VertexOutputColor;

void main() {
    const vec3 tf_pos = rotation * vec3(VertexPosition, 1.0f);

    gl_Position = vec4(tf_pos, 1.0f);
    VertexOutputColor = VertexColor;
}

I get garbage output. For this, I create a uniform buffer object, I allocate a block of memory where I copy the matrix data, then when I draw the object I map the buffer with glMapBufferRange and memcpy the data from the memory block to the pointer returned by glMapBufferRange. I'm probably doing something wrong, but I cannot figure out what.

\$\endgroup\$
0
\$\begingroup\$

Ok, I've finally figured it out. After some digging through the OpenGL 4.4 Core Specification, I found this paragraph regarding glGetProgramResourceiv :

For the property MATRIX_STRIDE, a single integer identifying the stride between columns of a column-major matrix or rows of a row-major matrix is written to params. For active variables declared a single matrix or array of matrices, the value written is the difference, in basic machine units, between the offsets of consecutive columns or rows in each matrix. For active variables not declared as a matrix or array of matrices, zero is written to params. For active variables not backed by a buffer object, -1 is written to params, regardless of the variable type.

My code was not accounting for this stride between the columns/rows of the matrix. So basically the data needs to be laid like this in memory, before uploading it to the GPU :

const auto m = R3::rotation_z(radians(35.0f));

const float mtx_data[] = {
  m.a00, m.a01, m.a02, 0, // pad to stride of 16 bytes
  m.a10, m.a11, m.a12, 0, // pad to stride of 16 bytes
  m.a20, m.a21, m.a22, 0 // pad to stride of 16 bytes
};

auto ptr = glMapBufferRange(...);
memcpy(ptr, mtx_data, sizeof(mtx_data));

Now it works as expected.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.