【问题标题】:GLSL : uniform buffer object exampleGLSL:统一缓冲区对象示例
【发布时间】:2014-04-21 19:32:58
【问题描述】:

我有一个可变大小的 GLubyte 数组。我想将它传递给片段着色器。我见过 This thread this thread。所以我决定使用“统一缓冲区对象”。但是作为 GLSL 的新手,我不知道:

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

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

2- 在 C++ 代码中如何以及在何处关联此缓冲区对象?

3 - 如何处理将 GLubyte 转换为浮点数?

【问题讨论】:

    标签: c++ opengl buffer glsl


    【解决方案1】:

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

    使用 Uniform Buffers (UB),您无法做到这一点。

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

    解决此问题的现代方法是使用 GL4 中称为 Shader Storage Buffers (SSB) 的功能。

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

    在旧版本的 GL 中,您可以使用 Buffer Texture 将大量动态大小的数据传递到着色器中,但与 SSB 相比,这是一种廉价的 hack,并且您无法使用漂亮的 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-位整数占用自己的 1/4 uint

    较新版本的 GLSL 引入了 intrinsic functions 可以做到这一点,但只要着色器存在,GPU 实际上就一直在做这种事情。每当您从着色器读取/写入GL_RGBA8 纹理时,您基本上是在打包或解压缩由 32 位整数表示的 4 个 8 位 unorms。

    【讨论】:

    • 很好的答案,但是它甚至让我害怕使用 UBO!正如你所指出的,我最好使用缓冲纹理,因为 UBO 在我的设置中引入了复杂性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 2021-05-03
    • 2019-09-18
    相关资源
    最近更新 更多