【发布时间】:2019-09-07 00:41:30
【问题描述】:
我正在 WebGL2 中进行 GPGPU 编程,并且通过将其打包到纹理中以绕过统一计数限制,将一个大型 4 维方形数组传递给我的着色器。从不得不使用相对较小的固定大小数组中解放出来,我希望能够指定实际以编程方式传入的数据的大小。
以前,我使用const int 硬编码要读取的数据大小,如下所示:
const int SIZE = 5;
const int SIZE2 = SIZE*SIZE;
const int SIZE3 = SIZE2*SIZE;
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 * 255.0);
}
如果我将 SIZE2 和 SIZE3 更新为非常量并在 main 中初始化,它仍然有效:
const int SIZE = 5;
int SIZE2;
int SIZE3;
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 * 255.0);
}
...
void main(){
SIZE2 = SIZE*SIZE;
SIZE3 = SIZE*SIZE2;
...
}
但是,如果我随后将const int SIZE = 5; 替换为uniform int SIZE;,然后添加
const size_loc = gl.getUniformLocation(program, "SIZE");
gl.uniform1i(size_loc, 5);
在 JavaScript 端将其设置为与过去硬编码相同的整数值,我开始看到从纹理中读取的值不正确。我做错了什么?
更新 1:我做了一个小实验,我保持不变的 SIZE 规范,但随后也传递了一个统一的 int 旁边。如果它们不相等,我会让着色器退出并返回全零。这样,我可以验证正确的整数值实际上是在统一变量上设置的——但是如果我随后将SIZE 设为非常量,并将其设置为统一变量的值 只是比较并发现相等然后事情就破裂了。什么鬼?
更新 2:
这行得通:
int SIZE = 5;
uniform int u_size;
....
void main() {
if (u_size != SIZE) return;
SIZE = u_size;
...
}
这不是:
int SIZE = 5;
uniform int u_size;
....
void main() {
SIZE = u_size;
...
}
【问题讨论】:
-
你确实在
gl.uniform1i(size_loc, 5);之前的某个地方打电话给gl.useProgram(program);,不是吗? -
@Rabbid76 是的。有几个预先存在的统一变量有效,并且一直有效。
-
我突然想到,除了纹理位置之外,我所有的其他统一值都是浮点数。因此,我尝试传入一个统一的浮点数,然后将其转换为 int 以初始化
SIZE——但最终得到完全相同(不正确)的结果。 -
这只是一个猜测,但如果你这样做,问题是否仍然存在
ivec2(i.x*SIZE*SIZE*SIZE+i.y*SIZE*SIZE+i.z*SIZE+i.w, 0) -
@Rabbid76 是的。 :(