【问题标题】:GLSL : Adressing pixel of a 2D texture loaded via TEXTURE_BUFFERGLSL:处理通过 TEXTURE_BUFFER 加载的 2D 纹理的像素
【发布时间】:2022-01-16 00:24:35
【问题描述】:

我正在做一些测试以通过 GL_TEXTURE_BUFFER 加载图像。我被困在从 texelFetch 正确处理像素上。目标是只显示 R8 纹理。

这是我创建缓冲区的方法:

sz = width*height*sizeof(uint8)
glGenBuffers( 1, &pbo );        
glBindBuffer( GL_TEXTURE_BUFFER, pbo );
glBufferStorage( GL_TEXTURE_BUFFER, sz, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |GL_MAP_COHERENT_BIT );

我通过 memcpy 上传到它,数据是 uint8

最后我将它链接到 GL_TEXTURE_BUFFER 纹理

glBindTexture( GL_TEXTURE_BUFFER, texture );
glTexBuffer( GL_TEXTURE_BUFFER, GL_R8, pbo );

在这一步,我只画了一个简单的矩形并将 uv 坐标传递给片段着色器 绘制函数是:

尺寸明显是640*480

uniform samplerBuffer texture;
in vec2 uv;
...
float f;
f =  640. * 480. * (uv.y) +  640. * (uv.x);
index = int(f);
color.r = texelFetch( texture, index )[0];

我试图规范化 color.r ( / 255.f ) 但没有任何效果。奇怪的行为是,如果我修改窗口的几何形状,着色器输出会不断变化,并且在某个特定维度上我可以看到纹理。我不明白,因为我的 uv 坐标没有改变(常规 0,1 1,1 ... 对于简单的四边形)。

我的索引计算不正确,这就是为什么我想知道是否有人可以指出问题所在。

(我已经用常规的 GL_TEXTURE_2D、GL_PIXEL_UNPACK_BUFFER、sampler2D 测试了着色器,没有问题)

编辑 1:

我尝试将图像尺寸作为 uv 坐标传递。

uv_min = {0,0}
uv_max = {640,480}

并将片段中的索引计算为:

int index = int( 640.*uv.y + 640.*uv.x)

失败。

【问题讨论】:

  • 如果您的数据是 2D 光栅图像,那么您为什么还要尝试通过 TEXUTURE_BUFFER 首先访问它?
  • 如果我错了,请纠正我,但据我所知,当我使用 PIXEL_UNPACK_BUFFER 并更新纹理时,缓冲区被复制到真正的纹理内存块中,我想跳过这个副本通过使用纹理缓冲区。

标签: opengl glsl buffer textures


【解决方案1】:

您的 2D 到 1D 索引计算已关闭:

float f;
f =  640. * 480. * (uv.y) +  640. * (uv.x);
index = int(f);

假设一个 640x480 像素的图像,以及 [0,1] 中的归一化纹理坐标,正确的方法需要是

 int index = 640 * int(480 * uv.y) + int(640 * uv.x);

奇怪的行为是,如果我修改窗口的几何形状,着色器输出会不断变化,并且在某些特定维度上我可以看到纹理。

您的640. * 480. * (uv.y) 将在行之间的任意像素上结束,而不是在行开头,除非uv.y 恰好落在1/480 的整数倍,这取决于重新缩放的因素您在抽样期间申请。

另外,根据您的评论:

如果我错了,请纠正我,但据我所知,在 GL 上,当我使用 PIXEL_UNPACK_BUFFER 并更新纹理时,缓冲区被复制到真正的纹理内存块中,我想使用纹理缓冲区。

从技术上讲,这是正确的,但它缺少更大的图景。 PBO 是一种异步更新纹理/纹理流的好方法。

改用 TBO,您确实绕过了该副本,但在从 GPU 采样时,您也绕过了 GPU 上的 TMU 硬件单元,这意味着您完全失去了所有纹理过滤器和包装模式等。

此外,2D 纹理不会像在TexImage(以及此处的 TBO)的输入缓冲区中那样以线性方式存储,而是以平铺和混合格式来优化采样时的缓存命中。通过完全绕过纹理功能,实际采样数据的成本实际上会更高,而且您的性能不一定会更高。

TBO 并不是真正用于纹理数据,它们是用于访问任意缓冲区数据适合纹理(并且比 UBO 允许的更大),基本上,它们完全被 SSBO 在现代 GL。

【讨论】:

  • 对于缓存未命中,我知道这一点,但想知道如何在片段中访问它。非常感谢,如果没有你的帮助,我想我会花上一天的时间。
猜你喜欢
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多