在 Webgl 中绘制多个元素

Drawing multiple elements in Webgl

我在 youtube 上看过很多关于这方面的视频,并且访问了这些网站:

这些来源中的大部分都很相似,但我就是无法理解其中的要点。

我使用 webgl 已经 4 个月了,我制作了三角形、矩形、球体、立方体,还编写了一些很酷的片段着色器。

但是显示多个对象对我来说是一个很大的障碍。

我不知道从哪里开始或我应该如何更改现有代码。

我是否应该创建更多缓冲区或创建更多顶点数组或创建更多程序?

我该如何处理?

我目前正在尝试为一个项目制作多个球体。这些球体将充当围绕原子核运行的电子。基本上我正在尝试制作原子的 3d 模型。

我知道像 three.js 和 babylon.js 这样的库在这里很有用,但我真的很想在没有任何外部库的情况下做到这一点。

有很多方法可以解决这个问题。

缓冲区定义几何体,而着色器程序定义几何体如何进入屏幕。如何将它们组合在一起以获得您想要的结果取决于您。

简短的版本是,当您调用 gl.draw*() 函数时,绑定的着色器程序将使用您告诉它使用的任何缓冲区和制服来执行。您可以根据需要完成该帧,使用不同的缓冲区、着色器或着色器输入多次执行此操作。


假设您有一个立方体,一个球体。它们具有相同的颜色和样式(意味着它们使用相同的着色器)。假设着色器将顶点位置作为 attribute vec3 aVert 并将颜色作为 uniform vec4 uColor.

您可能会为每个对象创建一个缓冲区,其中包含该形状的顶点数据。然后渲染:

  1. 绑定着色器
  2. 将着色器上的 uColor uniform 设置为 [1,0,0,1](红色)
  3. 立方体:
    1. 绑定立方体缓冲区
    2. 将缓冲区数据设置为aVert属性
    3. 致电gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
  4. 球体:
    1. 绑定球体缓冲区
    2. 将缓冲区数据设置为aVert属性
    3. 致电gl.drawArrays(gl.TRIANGLES, 0, vertexCount)

在此示例中,您使用两个绘制调用使用相同的着色器绘制两个不同的缓冲区。


现在假设你有多个立方体,你想用不同的颜色渲染它们(相同的着色器,但不同的制服)。假设您的着色器还采用 uniform vec3 aPos 值来定位立方体的中心。

  1. 绑定着色器
  2. 将缓冲区数据设置为aVert属性
  3. 红方块:
    1. 将着色器上的 uColor uniform 设置为 [1,0,0,1](红色)
    2. uPos 制服设置为 [0,0,0]
    3. 致电gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
  4. 蓝色立方体:
    1. 将着色器上的 uColor uniform 设置为 [0,0,1,1](蓝色)
    2. uPos 制服设置为 [10,0,0]
    3. 致电gl.drawArrays(gl.TRIANGLES, 0, vertexCount)

在本例中,您使用一个着色器将一个缓冲区绘制为具有两个不同绘制调用的两个对象,每个绘制调用在该着色器中具有不同的统一值。


Am I supposed to create more buffers or create more vertex arrays or create more programs?

是,或两者兼而有之,视需要而定。你有不同的几何图形要画吗?然后你需要更多的缓冲区。您有不同的方法来渲染该几何图形吗?然后你需要更多的着色器。缓冲区定义了一个空白canvas,着色器就是你的颜料和画笔。也许您使用相同的画笔和相同的颜料绘制多个对象,或者您可能不这样做。由你决定。

I'm currently trying to make multiple spheres for a project. The spheres will act as electrons orbiting a nucleus of an atom. Basically I'm trying to make a 3d model of an atom.

一个缓冲区(一个球体)和一个着色器的简单版本。着色器将定义:

attribute vec3 aVert;
uniform vec4 uColor;
uniform float uRadius; // radius of sphere
uniform float uOrbitRadius; // radius of orbit distance
uniform fload uOrbitAngle; // radians around the orbit

这个着色器将有一个顶点着色器,它根据 uRadius 缩放球体,然后将球体移动到轨道上,使用 uOrbitAngleuOrbitRadius 上的一些三角函数。

它会有一个片段着色器,它执行 shading/lighting/whatever 并将结果着色 uColor

然后通过以下方式渲染氢原子:

  1. 绑定着色器
  2. 绑定缓冲区
  3. 在着色器中设置 aVert 属性
  4. 核心:
    1. 将着色器 uColor 设置为 [0.5,0.5,0.5,1](灰色)
    2. 将着色器 uRadius 设置为 10
    3. 将着色器 uOrbitRadius 设置为 0
    4. 将着色器 uOrbitAngle 设置为 0
    5. 致电gl.drawArrays()
  5. 电子:
    1. 将着色器 uColor 设置为 [1,0,1,1] (megenta)
    2. 将着色器 uRadius 设置为 1
    3. 将着色器 uOrbitRadius 设置为 20
    4. 将着色器 uOrbitAngle 设置为每帧增加的数量
    5. 致电gl.drawArrays()

然后您可以通过重复电子渲染来添加更多电子,仅更改 uOrbitAngle

但这实际上取决于您希望这两个对象的外观,这将决定您如何构造它。