GLSL "равномерная сетка" ведро - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь сделать равномерное распределение по сетке: 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, текстуразаполняется 1 с, а затем просто отображает одно значение в последнем канале.

Если я только сделаю (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/

...