Невозможно построить точки в направлении Z, используя regl - PullRequest
0 голосов
/ 24 сентября 2018

Я начинаю с regl и пытаюсь сделать небольшую демонстрацию для построения точек по всем трем осям.Я использовал эту ссылку для начала.

В приведенном выше примере точки были инициализированы как

const points = d3.range(numPoints).map(i => ({
                x: //Code,
                y: //Code,
                color: [1, 0, 0],
            }));

Я изменил его на тот, что ниже, чтобы получить спираль, которая уходит в бесконечность

const points = d3.range(numPoints).map(i => ({
                x: 200+radius*Math.cos(i*Math.PI/180),
                y: 200+radius*Math.sin(i*Math.PI/180),
                z: i,
                color: [1, 0, 0],
            }));

Я изменилвершинный шейдер для учета дополнительной оси.Ниже приведен код, который рисует точки

const drawPoints = regl({
                frag:`
                precision highp float;
                varying vec3 fragColor;
                void main() 
                {
                    gl_FragColor = vec4(fragColor, 1);
                }
                `,

                vert:`
                attribute vec3 position;
                attribute vec3 color;
                varying vec3 fragColor;
                uniform float pointWidth;
                uniform float stageWidth;
                uniform float stageHeight;
                uniform float stageDepth;
                vec3 normalizeCoords(vec3 position) 
                {
                    float x = position[0];
                    float y = position[1];
                    float z = position[2];
                    return vec3(2.0 * ((x / stageWidth) - 0.5),-(2.0 * ((y / stageHeight) - 0.5)),1.0 * ((z / stageDepth) - 0.0));
                }
                void main()
                {
                    gl_PointSize = pointWidth;
                    fragColor = color;
                    gl_Position = vec4(normalizeCoords(position), 1.0);
                }
                `,
                attributes:
                {
                    position: points.map(d => [d.x, d.y, d.z]),
                    color: points.map(d => d.color),
                },
                uniforms:
                {
                    pointWidth: regl.prop('pointWidth'),
                    stageWidth: regl.prop('stageWidth'),
                    stageHeight: regl.prop('stageHeight'),
                    stageDepth: regl.prop('stageDepth'),
                },

                count: points.length,
                depth: 
                {
                    enable: true,
                    mask: true,
                    func: 'less',
                    range: [0, 1]
                },
                primitive: 'points',



            });
frameLoop = regl.frame(() => {
        // clear the buffer
        regl.clear({
            // background color (black)
            color: [0, 0, 0, 1],
            depth: 1,
        });

        drawPoints({
            pointWidth,
            stageWidth: width,
            stageHeight: height,
        });

        if (frameLoop) {
            frameLoop.cancel();
        }
    });

Но в результате получается круг, нанесенный на одну и ту же плоскость.Третий вход в позицию, кажется, не имеет никакого эффекта.Я попытался поменять значения y и z в позиции, и я получил синусоиду.Таким образом, значение z назначается правильно.Еще одна вещь, которую я заметил, это то, что если значение z равно нулю, ничего не отображается.Любое другое значение z , похоже, не дает никакого эффекта.

1 Ответ

0 голосов
/ 24 сентября 2018

Причина, по которой добавленная координата z не имеет никакого эффекта, заключается в том, что в вашем конвейере рендеринга нет понятия «проекция глубины».

Как правило, вам нужно добавить «матрицу проекции» в конвейер рендеринга, которая будет учитывать координату z в вершинах при отображении этих трехмерных позиций вершин на 2D-экран.

Вы сможете добавить эту проекцию довольно просто, используя что-то вроде canvas-orbit-camera модуля.Как только вы добавите этот модуль в свой проект, рассмотрите возможность внесения следующих изменений в свой код (см. Комментарии, помеченные [Добавить]):

// Your init code ..

// [Add] Register camera middleware with canvas
const camera = require('canvas-orbit-camera')(canvas)

// Your init code ..

const drawPoints = regl({
    frag:`
    precision highp float;
    varying vec3 fragColor;
    void main() 
    {
        gl_FragColor = vec4(fragColor, 1);
    }
    `,

    vert:`
    attribute vec3 position;
    attribute vec3 color;
    varying vec3 fragColor;
    uniform float pointWidth;
    uniform float stageWidth;
    uniform float stageHeight;
    uniform float stageDepth;

    uniform mat4 proj; // [Add] Projection matrix uniform

    vec3 normalizeCoords(vec3 position) 
    {
        float x = position[0];
        float y = position[1];
        float z = position[2];
        return vec3(2.0 * ((x / stageWidth) - 0.5),-(2.0 * ((y / stageHeight) - 0.5)),1.0 * ((z / stageDepth) - 0.0));
    }
    void main()
    {
        gl_PointSize = pointWidth;
        fragColor = color;
        gl_Position = proj * vec4(normalizeCoords(position), 1.0); // [Add] Multiply vertex by projection matrix
    }
    `,
    attributes:
    {
        position: points.map(d => [d.x, d.y, d.z]),
        color: points.map(d => d.color),
    },
    uniforms:
    {
        pointWidth: regl.prop('pointWidth'),
        stageWidth: regl.prop('stageWidth'),
        stageHeight: regl.prop('stageHeight'),
        stageDepth: regl.prop('stageDepth'),

        // [Add] Projection matrix calculation
        proj: ({viewportWidth, viewportHeight}) =>
            mat4.perspective([],
                Math.PI / 2,
                viewportWidth / viewportHeight,
                0.01,
                1000),
    },

    count: points.length,
    depth: 
    {
        enable: true,
        mask: true,
        func: 'less',
        range: [0, 1]
    },
    primitive: 'points',
});

frameLoop = regl.frame(() => {
    // clear the buffer
    regl.clear({
        // background color (black)
        color: [0, 0, 0, 1],
        depth: 1,
    });

    // [Add] Camera re computation
    camera.tick()

    drawPoints({
        pointWidth,
        stageWidth: width,
        stageHeight: height,
    });

    if (frameLoop) {
        frameLoop.cancel();
    }
});

Надеюсь, это поможет!

...