GLSL:统一缓冲区对象示例

GLSL : uniform buffer object example

本文关键字:对象 缓冲区 GLSL      更新时间:2023-10-16

我有一个大小可变的GLubyte数组。我想把它传给碎片着色器。我见过这根线和这根线。所以我决定使用"统一缓冲区对象"。但作为GLSL的新手,我不知道:

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

layout(std140) uniform MyArray
 { 
  GLubyte  myDataArray[size];  //I know GLSL doesn't understand GLubyte
 };

2-在C++代码中如何以及在哪里关联这个缓冲区对象?

3-如何处理铸造GLubyte浮动?

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

使用统一缓冲区(UB),您无法做到这一点

size必须是静态的,并且在链接GLSL程序时是已知的。这意味着它必须硬编码到实际的着色器中。

解决这一问题的现代方法是使用GL4中名为着色器存储缓冲区(SSB)的功能

SSB可以具有可变长度(最后一个字段可以声明为无大小数组,如myDataArray[]),并且它们还可以存储比UB多得多的数据。

在旧版本的GL中,您可以使用缓冲区纹理将大量动态大小的数据传递到着色器中,但与SSB相比,这是一种廉价的破解方法,而且您也无法使用类似struct的界面访问数据。

3-如何处理铸造GLubyte浮动?

你真的根本不会这么做,这要复杂得多

GLSL数据结构中可以使用的最小数据类型是32位。如果需要,您可以使用packUnorm4x8 (...)等特殊函数将较小的数据块打包和解包到uint中。这样做是有意的,以避免定义具有较小大小的新数据类型。

即使不使用任何特殊的GLSL函数,也可以执行此操作。

packUnorm4x8 (...)大致相当于执行以下操作:

for (int i = 0; i < 4; i++)
  packed += round (clamp (vec [i], 0, 1) * 255.0) * pow (2, i * 8);

它采用范围为[0,1]的浮点值的4分量矢量,并进行定点运算,将每个浮点值打包为一个无符号归一化(unorm)8位整数,占据uint的1/4。

GLSL的较新版本引入了可以做到这一点的内部函数,但实际上,只要着色器存在,GPU就一直在做这种事情。无论何时从着色器读取/写入GL_RGBA8纹理,基本上都是在打包或拆包由32位整数表示的4个8位无序。