在WebGL中用1d纹理替换统一数组时数据损坏

问题描述 投票:1回答:2

我正在WebGL2中的大型4D输入数组上进行一些GPGPU处理。最初,我只是将输入数组展平并将其作为一个统一的int数组传递,在GLSL中使用自定义访问器函数将4D坐标转换为数组索引,如下所示:

const int SIZE = 5; // The largest dimension that works; if I can switch to textures, this will be passed in as a uniform value.
const int SIZE2 = SIZE*SIZE;
const int SIZE3 = SIZE*SIZE2;
const int SIZE4 = SIZE*SIZE3;
uniform int u_map[SIZE4];

int get_cell(vec4 m){
  ivec4 i = ivec4(mod(m,float(SIZE)));
  return u_map[i.x*SIZE3+i.y*SIZE2+i.z*SIZE+i.w];
}

在JavaScript方面,展平的数据传递如下:

const map_loc = gl.getUniformLocation(program, "u_map");
gl.uniform1iv(map_loc, data);

其中data是一个包含8位值的Int32Array(因为这是映射到GLSL整数所需的)。

这有效,但它严重限制了我可以使用的输入大小。如果只有1024个可用于此数据和其他控制输入,则尺寸大小为6会导致使用1296个统一插槽。

所以,我想切换到使用纹理来容纳更大量的数据。所以,我已经将JS代码更新为:

const tex = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, data.length, 1, 0, gl.RED, gl.UNSIGNED_BYTE, data);

其中data被重新打包为Uint8Array,应该用于在GLSL中的纹理采样器对象中提供单通道r值。 GLSL代码更新如下:

uniform sampler2D u_map;

int get_cell(vec4 m){
  ivec4 i = ivec4(mod(m,float(SIZE)));
  float r = texelFetch(u_map, ivec2(i.x*SIZE3+i.y*SIZE2+i.z*SIZE+i.w, 0), 0).r;
  return int(r);
}

它应该从底层缓冲区中获取单个有效通道值,就像我们使用数组时一样。

然而,在做这个替换后,我只是得到了垃圾。从get_cell返回的值看起来都是1或0 - 并且它们都没有可靠地对应于原始数据缓冲区中实际的1或0值的存在。

我究竟做错了什么?

gpgpu webgl2
2个回答
1
投票

如果纹理的内部格式是gl.R8,则纹理在texelFetch中查找的值在[0.0,1.0]范围内。

如果要在[0,255]范围内下注值,则必须将值乘以255.0:

int get_cell(vec4 m){
    ivec4 i = ivec4(mod(m,float(SIZE)));
    float r = texelFetch(u_map, ivec2(i.x*SIZE3+i.y*SIZE2+i.z*SIZE+i.w, 0), 0).r;
    return int(r * 255.0);
}

请注意,R8RGB8RGBA8等格式是无符号规范化定点格式。假设颜色值是[0.0,1.0]范围内的浮点值,其中最小可能值0被转换为0.0并且最大可能值(2 ^ 8-1 == 255)被转换为1.0。


1
投票

您使用的R8格式是一种标准化浮点格式,其值为0.0到1.1。如果你想要一个int格式然后考虑使用R32I纹理内部格式,提供纹理数据格式gl.RED_INTEGER,键入gl.INT并使用Int32Array,将您的采样器更改为isampler2D并使用int r = textureFetch(....).r读取数据。

如果你想要一个整数结果,你还需要为结果创建一个整数纹理,并将其附加到帧缓冲区以呈现整数结果。

© www.soinside.com 2019 - 2024. All rights reserved.