我正在尝试进行统一的网格存储: https://www.researchgate.net/figure/A-2D-uniform-grid-example-with-grid-cell-and-particle-ids_fig3_325579657
https://jsfiddle.net/mikoval/0147xwfq/12/ 可在一台计算机上运行,而不能在另一台计算机上运行。存储桶值将在控制台中打印。
一切都可以在一台计算机上正常运行,但是当我在另一台计算机上进行测试时,得到的结果却截然不同。我正在使用的算法如下:
生成两个渲染目标。使用一个作为输入,使用一个作为输出。在每一帧的开始都将它们清除。
基于位置纹理将所有粒子渲染到帧缓冲区中。我不渲染颜色,而是渲染粒子的索引。我使用此过程的输出传递到下一个渲染。在每次渲染期间,都会检查粒子是否已经渲染,如果已经渲染,则将其忽略。这样,我可以在同一网格位置拥有多达4个不同的粒子(每个粒子将作为单个索引存储在RGBA通道中)。
以下是我的着色器:
this.bucketVertex = `#version 300 es
precision highp float;
in ivec2 position;
flat out ivec2 id;
out vec2 pv;
uniform vec2 res;
uniform sampler2D image;
uniform sampler2D current;
void main() {
gl_PointSize = 1.0;
id = position;
float aspect = res.y / res.x;
vec2 pos = texelFetch(image, position, 0).xy;
pos.x *= aspect;
float gSize = float(textureSize(image, 0).x);
float val = float(id.x + id.y * int(gSize) + 1);
vec2 b = floor(pos * gSize)/gSize + 0.5/gSize;
pv = (b + 1.0)/2.0;
vec4 c = texture(current, pv.xy);
for(int i = 0; i < 4; i++){
if(c[i] == val) {
b = vec2(1000.0, 1000.0);
}
}
gl_Position = vec4(b, 0, 1);
}
`;
this.bucketFragment = `#version 300 es
precision highp float;
flat in ivec2 id;
in vec2 pv;
out vec4 outColor;
uniform sampler2D current;
uniform sampler2D image;
void main() {
vec2 p = pv;
vec4 c = texture(current, p.xy);
int size = textureSize(image, 0).x;
int val = id.x + id.y * size + 1;
for(int i = 0; i < 4; i++){
if(c[i] == 0.0){
c[i] = float(val);
break;
}
}
outColor = c;
}
`;
我的存储桶渲染循环如下所示:
/* clear previous run */
gl.bindFramebuffer(gl.FRAMEBUFFER, this.bucketTarget2.fb);
gl.clearColor(0.0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.disable(gl.BLEND);
gl.bindFramebuffer(gl.FRAMEBUFFER, this.bucketTarget.fb);
gl.viewport(0, 0, this.bucketTarget.fb.width, this.bucketTarget.fb.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(this.bucketObj.program);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, state.texture);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.bucketTarget2.texture);
gl.uniform1i(this.bucketObj.uniformImage, 0);
gl.uniform1i(this.bucketObj.uniformImage2, 1);
gl.bindVertexArray(this.bucketVao);
gl.uniform2f(this.bucketObj.uniformRes, gl.canvas.width, gl.canvas.height);
for(var i = 0; i < 4; i++){
gl.drawArrays(gl.POINTS, 0, this.size * this.size);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, state.texture);
gl.uniform1i(this.bucketObj.uniformImage, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.bucketTarget2.texture);
gl.uniform1i(this.bucketObj.uniformImage2, 1);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, this.bucketTarget2.fb.width, this.bucketTarget2.fb.height, 0);
}
如前所述,这在一台计算机上完全可以正常工作,其中示例输出纹理可能如下所示(是的,它是浮点纹理):
[
5, 0, 0, 0,
3, 2, 0, 0,
4, 1, 6, 0,
7, 8, 0, 0
...
]
但是,在另一台计算机上,我得到以下信息:
[0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 4,
1, 1, 1, 3,
0, 0, 0, 0,
1, 1, 1, 2,
0, 0, 0, 0,
0, 0, 0, 0]
无论出于何种原因,每当存在一个非1的粒子时,纹理就会以1s填充,然后仅在最后一个通道中显示一个值。
如果我只做(for i = 0; i < 2; i++)
,则纹理看起来像
[ 1,4,0,0, 1,0,0,0, 1、3、0、0, .... ]
我不知道这些1的来源是基于着色器代码的。如果有帮助,我可以稍后尝试摆弄演示。
编辑:更新了gman的评论。