在GLSL中从数组初始化结构
Initializing structures from arrays in GLSL
假设我在着色器中有一个数组变量,在着色器存储块中声明:
layout(std430, binding = 2) buffer MyBuffer
{
float lotsOfFloats[];
};
和struct:
struct myStruct
{
float f1;
vec3 vf1;
}struct1;
是否有一种方法来"快速"初始化这个结构的对象在着色器中使用的值在一个缓冲区存储块(在lotsOfFloats数组在这个例子)?例如,在c++中可以将内存从数组复制到对象:
memcpy(&struct1, &lotsOfFloats[0], sizeof(myStruct) );
或者可以通过赋值将数组值字节复制到对象中:
struct1 = *(myStruct*)&lotsOfFloats[0];
在GLSL中是否有类似的方法?例如,将工作的第二种方式(字节拷贝赋值)在GLSL?
与其将SSB视为浮点数的非结构化数组,不如将其声明为结构的非大小数组:
struct myStruct
{ // Addresses Occupied
float f1; // 0N
vec3 vf1; // 1N,2N,3N
};
layout(std430, binding = 2) buffer MyBuffer
{
myStruct lotsOfStructs[];
};
有一个小问题与你的结构,它目前的方式编写:
gpu不喜欢大多数3-component数据类型,通常必须像对待4-component那样对待它们。因此,vec3
具有与vec4
相同的对齐规则。
现在,你有一个vec3
开始在错误的边界。vec3
和vec4
数据类型需要对齐到4N的倍数(其中N是float
的大小)。
以下更改通过重新安排vf1
和f1
来解决此问题:
struct myStruct
{ // Addresses Occupied
vec3 vf1; // 0N,1N,2N
float f1; // 3N
};
(单精度)标量可以在任何边界上对齐,因为它们的大小为1N,所以你可以把f1
放在vf1
后面,没有问题。
您可能会发现,在std430
中,有一个额外的要求,即结构体的大小必须是最大基数对齐的倍数。在这种情况下,这个结构体中所有成员的最大基数对齐是vf1
(vec3
),它的基数对齐是4N。
这意味着如果你在结构的末尾没有f1
(它的大小将是3N), GL将自动添加1N值的填充到结构的末尾,你需要在你的C代码中考虑GL的行为。你的结构已经对齐了4N,所以你可以开始了,但如果你不知道这一点,它可能会让你大吃一惊。
你应该仔细阅读 7.6.2.2 Standard Uniform Block Layout
,在处理着色器存储缓冲区和统一缓冲区时,对齐是非常重要的。
相关文章:
- 在C和C++中初始化结构中的数组
- 我们可以用参数化构造函数初始化结构的数组吗?
- 尝试初始化结构内的联合时出错
- 使用其他成员初始化结构的成员?
- 使用构造函数初始化结构还是在之后设置其值更好?
- 如果不初始化结构中的向量,它会自动为空还是具有随机内存位置的值?
- 如何在另一个结构中初始化结构数组?
- 如何在构造函数中初始化结构体的动态数组?
- 初始化结构中的联合 - c++
- 尝试初始化结构向量时出现编译错误
- 用于初始化结构的 void 指针强制转换
- 初始化结构的两种方式
- 使用用户定义的构造函数初始化C++结构
- 使用初始值设定项列表初始化结构,对于 std::array 失败
- 在 c++ 中初始化结构的指针
- 无序列图会创建一个零初始化结构吗?
- 如何在C++中初始化结构
- C 用结构指针初始化结构
- 在C 中初始化结构数组
- 使用数组聚合初始化结构数组