GLSL:统一缓冲区对象示例

时间:2014-04-21 19:32:59

标签: c++ opengl buffer glsl

我有一个可变大小的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转换为浮动?

1 个答案:

答案 0 :(得分:5)

  

1 - 如果我要将其添加到片段着色器,我该如何传递大小?我应该创建一个结构吗?

使用统一缓冲区(UB),你不能这样做。

当您链接您的GLSL计划时,

size必须是静态的并且是已知的。这意味着它必须硬编码到实际的着色器中。

现代的方法是使用GL4中的一个名为Shader Storage Buffers(SSB)的功能。

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位统一。