Reputation:
I have a shader storage block in the vertex shader, like this:
layout(std430,binding=0) buffer buf {mat3 rotX, rotY, rotZ; } b;
I initialized those 3 matrices with identity matrix like this:
float mats[]={ 1,0,0,0,1,0,0,0,1,
1,0,0,0,1,0,0,0,1,
1,0,0,0,1,0,0,0,1 };
GLuint ssbos;
glGenBuffers(1,&ssbos);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,ssbos);
glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(mats),mats,GL_DYNAMIC_DRAW);
But it doesn't seem to work (I'm using Opengl 4.3 core profile). Am I doing something wrong?
Upvotes: 1
Views: 2180
Reputation: 473407
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,ssbos); glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(mats),mats,GL_DYNAMIC_DRAW);
glBindBufferBase
binds the entire range of the buffer. But it's not a magic "bind whatever the buffer happens to store" function. It binds the entire range of the buffer as it currently exists.
And since you haven't allocated any storage for that buffer object, its current state is empty: a size of 0. And that's what you bind: a range of 0 bytes of memory.
Oh sure, in the next statement, you give the buffer memory. But that doesn't change the fact that it didn't have memory when you bound it.
So you need to create storage for the buffer before binding a range of it.
Also, don't use vec3
or any types related to vec3
in buffer-backed interface blocks. And you really shouldn't be passing axial rotation matrices like that.
Upvotes: 2
Reputation: 10390
The std430 layout is essentially std140 with tighter packing of structs and arrays. The data you are supplying does not respect the layout rules.
From section 7.6.2.2 Standard Uniform Block Layout of the OpenGL spec:
- If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The array may have padding at the end; the base offset of the member following the array is rounded up to the next multiple of the base alignment.
- If the member is a column-major matrix with C columns and R rows, the matrix is stored identically to an array of C column vectors with R components each, according to rule (4).
So your mat3
matrices are treated as 3 vec3
each (one for each column). According to the rule (4), a vec3
is padded to occupy the same memory as a vec4
.
In essence, when using a mat3
in an SSBO, you need to supply the same amount of data as if you were using a mat4
mat3x4
with the added benefit of a more confusing memory layout. Therefore, it is best to use mat3x4
(or mat4
) in an SSBO and only use its relevant portions in the shader. Similar advice also stands for vec3
by the way.
It is easy to get smaller matrices from a larger one:
A wide range of other possibilities exist, to construct a matrix from vectors and scalars, as long as enough components are present to initialize the matrix. To construct a matrix from a matrix:
mat3x3(mat4x4); // takes the upper-left 3x3 of the mat4x4 mat2x3(mat4x2); // takes the upper-left 2x2 of the mat4x4, last row is 0,0 mat4x4(mat3x3); // puts the mat3x3 in the upper-left, sets the lower right // component to 1, and the rest to 0
This should give you proper results:
float mats[]={ 1,0,0,0, 0,1,0,0, 0,0,1,0,
1,0,0,0, 0,1,0,0, 0,0,1,0,
1,0,0,0, 0,1,0,0, 0,0,1,0, };
Upvotes: 0