Working around gl_PointSize limitations in three.js / webGL

前端 未结 2 1954
孤街浪徒
孤街浪徒 2021-02-09 12:06

I\'m using three.js to create an interactive data visualisation. This visualisation involves rendering 68000 nodes, where each different node has a different size and color.

2条回答
  •  臣服心动
    2021-02-09 12:21

    You can make your own point system by making arrays of unit quads + the center point then expanding by size in GLSL.

    So, you'd have 2 buffers. One buffer is just a 2D unitQuad repeated for how ever many points you want to draw.

    var unitQuads = new Float32Array([
      -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
      -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
      -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
      -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
      -0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
    ];
    

    The second one is your points except the positions need to be repeated 4 times each

    var points = new Float32Array([
      p1.x, p1.y, p1.z, p1.x, p1.y, p1.z, p1.x, p1.y, p1.z, p1.x, p1.y, p1.z,
      p2.x, p2.y, p2.z, p2.x, p2.y, p2.z, p2.x, p2.y, p2.z, p2.x, p2.y, p2.z,
      p3.x, p3.y, p3.z, p3.x, p3.y, p3.z, p3.x, p3.y, p3.z, p3.x, p3.y, p3.z,
      p4.x, p4.y, p4.z, p4.x, p4.y, p4.z, p4.x, p4.y, p4.z, p4.x, p4.y, p4.z,
      p5.x, p5.y, p5.z, p5.x, p5.y, p5.z, p5.x, p5.y, p5.z, p5.x, p5.y, p5.z,
    ]);
    

    Setup your buffers and attributes

    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, unitQuads, gl.STATIC_DRAW);
    gl.enableVertexAttribArray(unitQuadLoc);
    gl.vertexAttribPointer(unitQuadLoc, 2, gl.FLOAT, false, 0, 0);
    
    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
    gl.enableVertexAttribArray(pointLoc);
    gl.vertexAttribPointer(pointLoc, 3, gl.FLOAT, false, 0, 0);
    

    In your GLSL shader, compute the gl_PointSize you want then multiply the unitQuad by that size in view space or screen space. Screen space would match what gl_Point does but often people want their points to scale in 3D like normal stuff in which case view space is what you want.

    attribute vec2 a_unitQuad;
    attribute vec4 a_position;
    uniform mat4 u_view;
    uniform mat4 u_viewProjection;
    
    void main() {
       float fake_gl_pointsize = 150;
    
       // Get the xAxis and yAxis in view space
       // these are unit vectors so they represent moving perpendicular to the view.
       vec3 x_axis = view[0].xyz;
       vec3 y_axis = view[1].xyz;
    
       // multiply them by the desired size 
       x_axis *= fake_gl_pointsize;
       y_axis *= fake_gl_pointsize;
    
       // multiply them by the unitQuad to make a quad around the origin
       vec3 local_point = vec3(x_axis * a_unitQuad.x + y_axis * a_unitQuad.y);
    
       // add in the position you actually want the quad.
       local_point += a_position;
    
       // now do the normal math you'd do in a shader.
       gl_Position = u_viewProjection * local_point;
    }
    

    I'm not sure that made any sense but there's more complicated but a working sample here

提交回复
热议问题