glsl“统一网格”存储

时间:2018-10-05 16:07:44

标签: graphics opengl-es glsl webgl gpu

我正在尝试进行统一的网格存储: 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的评论。

链接至演示:https://jsfiddle.net/mikoval/0147xwfq/12/

0 个答案:

没有答案