我在顶点着色器中有一个着色器存储块,如下所示:
layout(std430,binding=0) buffer buf {mat3 rotX, rotY, rotZ; } b;
我用这样的单位矩阵初始化了这3个矩阵:
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);
但它似乎不起作用(我正在使用Opengl 4.3核心配置文件)。我做错了吗?
答案 0 :(得分:2)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,ssbos); glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(mats),mats,GL_DYNAMIC_DRAW);
glBindBufferBase
绑定缓冲区的整个范围。但它不是一个神奇的“绑定任何缓冲区恰好存储”功能。它绑定了当前存在的缓冲区的整个范围。
由于您尚未为该缓冲区对象分配任何存储空间,因此其当前状态为空:大小为0.这就是您绑定的内容:0字节内存的范围。
哦,确定,在下一个语句中,您给出了缓冲区内存。但这并没有改变它绑定它时没有记忆的事实。
因此,您需要在绑定其范围之前为缓冲区创建存储空间。
另外,don't use vec3
or any types related to vec3
in buffer-backed interface blocks.而你确实不应该像这样传递轴向旋转矩阵。
答案 1 :(得分:0)
std430 layout is essentially std140结构和数组的包装更紧密。您提供的数据不符合布局规则。
从第7.6.2.2节OpenGL规范的标准统一块布局:
- 如果成员是标量或向量的数组,则根据规则(1),(2)和(3),将基本对齐和数组步长设置为匹配单个数组元素的基本对齐,并且四舍五入到vec4的基线对齐。阵列末端可能有填充;数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。
- 如果该成员是具有C列和R行的列主矩阵,则根据规则(4),矩阵与C列向量的数组相同地存储,每个R成分,根据规则(4)。
醇>
因此,您的mat3
矩阵每个被视为3 vec3
(每列一个)。根据规则(4),vec3
被填充以占用与vec4
相同的记忆。
实质上,在SSBO中使用mat3
时,您需要提供与使用 mat4
mat3x4
时相同数量的数据具有更混乱的内存布局的额外好处。因此,最好在SSBO中使用mat3x4
(或mat4
),并仅在着色器中使用其相关部分。顺便说一下,类似的建议也代表vec3
。
从较大的矩阵中获取较小的矩阵很容易:
存在广泛的其他可能性,从载体和标量构建矩阵,只要存在足够的组分来初始化矩阵。从矩阵构造矩阵:
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
这应该会给你正确的结果:
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, };