解决three.js/webGL中的gl_PointSize限制 [英] Working around gl_PointSize limitations in three.js / webGL

查看:288
本文介绍了解决three.js/webGL中的gl_PointSize限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用three.js创建交互式数据可视化.该可视化过程涉及渲染68000个节点,其中每个不同的节点都有不同的大小和颜色.

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.

最初,我尝试通过渲染网格来做到这一点,但是事实证明这是非常昂贵的.我目前的尝试是使用Three.js粒子系统,每个点都是可视化中的一个节点.

Initially I tried to do this by rendering meshes, but that proved to be very expensive. My current attempt is to use a three.js particle system, with each point being a node in the visualisation.

我可以控制点的颜色*大小,但只能控制到某个点.在我的卡片上,滑点的最大大小似乎是63.当我放大可视化效果时,点会变大-到一个点,然后保持在63像素.

I can control the color * size of the point, but only to a certain point. On my card, the maximum size for a gl point seems to be 63. As I zoom in to the visualisation, points get larger - to a point, and then remain at 63 pixels.

我正在使用顶点&当前片段着色器:

I'm using a vertex & fragment shader currently:

顶点着色器:

attribute float size;
attribute vec3 ca;
varying vec3 vColor;

void main() {
    vColor = ca;
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
    gl_Position = projectionMatrix * mvPosition;
}

片段着色器:

uniform vec3 color;
uniform sampler2D texture;

varying vec3 vColor;

void main() {
    gl_FragColor = vec4( color * vColor, 1.0 );
    gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}

这些都是从Three.js示例之一中几乎逐字复制的.

These are copied almost verbatim from one of the three.js examples.

我对GLSL完全陌生,但是我正在寻找一种绘制大于63像素的点的方法.是否可以对大于特定大小的任何点绘制网格,但是可以使用gl_point?我还可以使用其他解决方法来绘制大于63像素的点吗?

I'm totally new to GLSL, but I'm looking for a way to draw points larger than 63 pixels. Can I do something like draw a mesh for any points larger than a certain size, but use a gl_point otherwise? Are there any other work-arounds I can use to draw points larger than 63 pixels?

推荐答案

您可以通过制作单位四边形+中心点的数组然后在GLSL中按大小扩展来创建自己的点系统.

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

因此,您将有2个缓冲区.一个缓冲区只是一个2D单位四倍,重复绘制要绘制的点数.

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,
];

第二个是您的得分,除了每个位置需要重复4次

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,
]);

设置缓冲区和属性

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);

在GLSL着色器中,计算所需的gl_PointSize,然后将unitQuad乘以该大小在视图空间或屏幕空间中.屏幕空间将与gl_Point的功能匹配,但是人们通常希望它们的点像普通的东西一样以3D缩放,在这种情况下,视图空间就是您想要的.

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

这篇关于解决three.js/webGL中的gl_PointSize限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆