我有一个可变大小的GLubyte数组。我想将它传递给片段着色器。我见过 This thread 和this thread。所以我决定使用" Uniform Buffer Objects"。但作为GLSL的新手,我不知道:
1 - 如果我要将其添加到片段着色器,我该如何传递大小?我应该创建一个结构吗?
layout(std140) uniform MyArray
{
GLubyte myDataArray[size]; //I know GLSL doesn't understand GLubyte
};
2- C ++代码中如何以及在何处关联此缓冲区对象?
3 - 如何处理将GLubyte转换为浮动?
答案 0 :(得分:5)
1 - 如果我要将其添加到片段着色器,我该如何传递大小?我应该创建一个结构吗?
size
必须是静态的并且是已知的。这意味着它必须硬编码到实际的着色器中。
SSB可以具有可变长度(最后一个字段可以声明为非大小数组,如myDataArray[]
),它们也可以存储比UB更多的数据。
在旧版本的GL中,您可以使用Buffer Texture将大量动态大小的数据传递到着色器,但与SSB相比,这是一个廉价的黑客攻击,并且您无法使用漂亮的{{{{{{ 1}} - 类似界面。
3 - 如何处理将GLubyte转换为浮动?
您可以在GLSL数据结构中使用的最小数据类型是32位。如果需要,您可以使用struct
等特殊功能将较小的数据打包并解压缩到uint
。这是故意完成的,以避免必须定义较小尺寸的新数据类型。
即使不使用任何特殊的GLSL功能,您也可以这样做。
packUnorm4x8 (...)
大致相当于执行以下操作:packUnorm4x8 (...)
它采用[0,1]范围内的浮点值的4分量向量,并进行定点运算以将它们中的每一个打包成无符号规范化(unorm)8-位整数占据for (int i = 0; i < 4; i++)
packed += round (clamp (vec [i], 0, 1) * 255.0) * pow (2, i * 8);
的1/4。
较新版本的GLSL引入了intrinsic functions这样做,但是只要着色器出现,GPU实际上就是在做这种事情。无论何时从着色器读取/写入uint
纹理,您基本上都要打包或解包4个由32位整数表示的8位统一。