如何在着色器存储缓冲区中初始化矩阵?

时间:2017-11-10 16:17:01

标签: opengl

我在顶点着色器中有一个着色器存储块,如下所示:

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核心配置文件)。我做错了吗?

2 个答案:

答案 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. 如果成员是标量或向量的数组,则根据规则(1),(2)和(3),将基本对齐和数组步长设置为匹配单个数组元素的基本对齐,并且四舍五入到vec4的基线对齐。阵列末端可能有填充;数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。
  2.   
  3. 如果该成员是具有C列和R行的列主矩阵,则根据规则(4),矩阵与C列向量的数组相同地存储,每个R成分,根据规则(4)。
  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,  };