无法使用Regl在Z方向上绘制点

时间:2018-09-23 23:10:00

标签: webgl regl

我从regl开始,我正在尝试制作一个用于在所有三个轴上绘制点的小演示。我以这个link开始。

在上面的示例中,点被初始化为

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 :(得分:1)

添加的z坐标无效的原因是,当前在渲染管道中没有“深度投影”的概念。

通常,您需要在渲染管道中添加一个“投影矩阵”,当将这些3D顶点位置映射到2D屏幕时,该投影矩阵将说明顶点中的z坐标。

您应该能够使用canvas-orbit-camera模块之类的方法相当简单地添加此投影。在将该模块添加到项目中之后,请考虑对代码进行以下调整(请参见带有[Add]标记的注释):

// 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();
    }
});

希望这会有所帮助!