c++ - 从 GLSL 中的数组初始化结构

标签 c++ c opengl glsl

假设我在着色器中有一个数组变量,在着色器存储 block 中声明:

layout(std430, binding = 2) buffer MyBuffer
{
  float lotsOfFloats[];
};

和一个结构:

struct myStruct
{
 float f1;
 vec3 vf1;
}struct1;

有没有一种方法可以使用缓冲区存储 block 中数组中的值(在本例中为 lotsOfFloats 数组)在着色器中“快速”初始化此结构的对象?比如,在 C++ 中,可以将内存从数组复制到对象:

memcpy(&struct1, &lotsOfFloats[0], sizeof(myStruct) );

或者可以通过赋值将数组值字节复制到对象:

struct1 = *(myStruct*)&lotsOfFloats[0];

GLSL中有类似的方法吗?例如。将在 GLSL 中以第二种方式(字节复制赋值)工作吗?

最佳答案

与其将您的 SSB 视为非结构化的 float 组,您实际上可以将其声明为您的结构的未调整大小的数组:

struct myStruct
{              // Addresses Occupied
  float f1;    // 0N
  vec3  vf1;   // 1N,2N,3N
};

layout(std430, binding = 2) buffer MyBuffer
{
  myStruct lotsOfStructs[];
};

您的结构目前的编写方式存在一个小问题:

GPU 不喜欢大多数 3 分量数据类型,通常必须将它们视为 4 分量数据类型才能正确对齐。因此,vec3vec4 具有相同的对齐规则。

现在,您有一个从错误边界开始的 vec3vec3vec4 数据类型需要对齐到 4N 的倍数(其中 N 是 float 的大小)。

以下更改通过重新安排 vf1f1 解决了此问题:

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 , 在处理 Shader Storage Buffers 和 Uniform Buffers 时对齐非常重要。

关于c++ - 从 GLSL 中的数组初始化结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23433202/

相关文章:

c++ - 将 Depthbuffer 和 TextureBuffer 发送到同一个 Fragment OpenGL3

c++ - 使键等于(如果键存在于映射中)或严格小于映射中的给定输入

c++ - 如何从连接的控制台执行命令

c - gcc 用 memcpy 和 memset 替换循环

c - 在 c 中使用 openMP 并行化的最佳方法是什么

java - OpenGL 中场景中其他对象的反射

c++ - '{' token 之前的预期类名 - 带有头文件和 cpp 文件

c++ - 在 C++ 中始终对 float 使用后缀 'f' 有什么好处?

c - snprintf 和 friend 们可以安全使用吗?

c++ - OpenGL _ Front 对象被 Back 对象覆盖。所以看不到