2025年OpenGL - TBO (Texture Buffer Object) - 缓存纹理 - Instancing Using TBO 前置篇

OpenGL - TBO (Texture Buffer Object) - 缓存纹理 - Instancing Using TBO 前置篇准备尝试一下 TBO 的方式来实现 Instancing 渲染 所以提前了解一下 TBO 是什么 怎么用 是很有必要的 TBO 就是 Texture Buffer Object 的缩写 意思是 缓存纹理对象 简单的使用 可以参考如下内容 如下内容引用 OpenGL

大家好,我是讯享网,很高兴认识大家。

准备尝试一下 TBO 的方式来实现 Instancing 渲染,所以提前了解一下 TBO 是什么,怎么用,是很有必要的

TBO 就是:Texture Buffer Object 的缩写,意思是:缓存纹理对象

简单的使用,可以参考如下内容

如下内容引用:OpenGL 红宝书 第9版 第6章 - 缓存纹理


缓存纹理

缓存纹理是一种特殊形式的纹理,它允许从着色器中直接访问缓存对象的内容,将它当作一个巨大的以为纹理使用。缓存纹理与一般的以为纹理相比有一些限制和不同,但是在代码中所体现出的形态是非常类似的。我们可以把它当作一般的纹理对象创建,绑定到纹理单元,并使用 glTextureParameteri() 控制它们的参数1。但是,纹理数据的存储实际上是由一个缓存对象(它必须是有名称的)来管理和控制的。此外,缓存纹理也没有内置的采样器,并且采样器对象也不会对缓存纹理产生效果。缓存纹理与一般的一维纹理相比有如下不同之处:

  • 一维纹理的尺寸受限于 GL_MAX_TEXTURE_SIZE 对应的最大值,但是缓存纹理的尺寸受限于 GL_MAX_TEXTURE_BUFFER_SIZE 的值,通常能达到 2GB 甚至更多。
  • 一维纹理支持滤波、mipmap、纹理坐标的截取,以及其他的一些采样器参数,但是缓存纹理不行
  • 一维纹理的纹理坐标是归一化的浮点数值,但是缓存纹理使用的是没有归一化的整数纹理坐标。

我们需要根据自己的实际需求,在应用程序中选中使用缓存纹理或者一维纹理。如果要创建纹理,需要调用 glCreateTexture() 来创建纹理对象,并将 GL_TEXTURE_BUFFER 作为输入的目标参数,然后使用 glTextureBuffer() 函数将纹理与一个缓存对象关联起来。

void glTextureBuffer(GLuint texture, GLenum internalformat, GLuint buffer); 

讯享网

将缓存对象 buffer 的存储空间与缓存纹理 texture 进行关联。buffer 的存储数据将被视为一组数据格式为 internalformat 的元素进行解析,注意数据格式必须是有尺寸后缀的。如果 buffer 为0,那么缓存纹理 texture 中当前已经存在的关联信息将被断开,缓存数据将无法再读取。

例 6.23 是上述缓存创建、初始化数据存储,然后与一个缓存纹理进行关联的全过程示例。

例 6.23 创建和初始化缓存纹理


讯享网

讯享网// 作为数据存储的缓存对象 GLuint buffer; // 作为缓存纹理使用的纹理对象 GLuint tex; // 数据应当被保存到程序内存中了 extern const GLvoid* data; // 生成、绑定和初始化缓存对象,设置绑定点为 GL_TEXTURE_BUFFER。假设这里用到的数据量是 1MB glGenBuffers(1, &buf); glBindBuffer(GL_TEXTURE_BUFFER, buf); glBufferData(GL_TEXTURE_BUFFER, 1024 * 1024, data, GL_STATIC_DRAW); // 现在创建缓存纹理对象并将它与缓存对象关联 glCreateTexture(1, GL_TEXTURE_BUFFER, &tex); glTextureBuffer(tex, GL_R32F, buf); 

如果只需要关联缓存对象的一部分到缓存纹理中,需要使用 glTextureBufferRange() 函数,它的原型如下所示:

void glTextureBufferRange(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); 

将缓存对象 buffer 中从 offset 开始,总共 size 字节的一部分存储区域,关联给缓存纹理 texture。buffer 的存储数据将被视为一组数据格式为 internalformat 的元素进行解析,注意数据格式必须是有尺寸后缀的。如果 buffer 为 0,那么缓存纹理 texture 中当前已经存在的关联信息将被断开,缓存数据将无法再读取。offset 必须是一个整数值,并且是系统平台所定义的常量 GL_TEXTURE_BUFFER_OFFSET_ALGINMENT 的倍数。

为了在着色器中访问缓存纹理,还需要创建一个 uniform 变量 samplerBuffer(对于有符号或者无符号整型的变量,还可以使用 isamplerBuffer 和 usamplerBuffer),然后用 texelFetch 函数2来读取单独的纹理采样数据并使用。用于缓存纹理的 texelFetch 函数的定义如下:

讯享网vec4 texelFetch(samplerBuffer s, int coord); ivec4 texelFetch(isamplerBuffer s, int coord); uvec4 texelFetch(usamplerBuffer s, int coord); 

对一个单独的纹素执行查找,纹理当前绑定到 s,而纹理坐标设置为 coord。

有关声明缓存采样器并使用 texelFetch 来读取数据的过程,可以参见例 6.24。

例 6.24 从缓存纹理中查找纹素

#version 450 core layout (binding = 0) uniform samplerBuffer buf; in int buf_tex_coord; layout (location = 0) out vec4 color; void main(void) { 
    color = texelFetch(buf, buf_tex_coord); } 

References

  • OpenGL 红宝书 第9版 第6章 - 缓存纹理

  1. 并不是所有的纹理参数都适用于缓存纹理,并且缓存纹理也没有采样器,因此会忽略所有的采样器参数。 ↩︎
  2. texelFetch 函数除了用于缓存纹理,也可以用于一般的纹理。如果我们用它来采样一个非缓存纹理,那么纹理的采样器参数将被忽略,并且纹理坐标在这里会被视为一个没有经过归一化的整数数值(这一点与缓存纹理的用法相同)。我们选择在这里单独介绍这个函数,是因为它是使用缓存纹理时最常用到的。 ↩︎
小讯
上一篇 2025-03-31 07:58
下一篇 2025-02-05 21:58

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/65876.html