有很多方法可以解决这个问题。
缓冲区定义几何体,着色器程序定义几何体如何进入屏幕。如何将它们组合在一起以获得您想要的东西取决于您。
简短的版本是,当您调用gl.draw*() 函数时,绑定的着色器程序将使用您告诉它使用的缓冲区和制服执行。您可以根据需要使用不同的缓冲区、着色器或着色器输入多次执行此操作,以完成该帧。
假设你有一个立方体,一个球体。它们具有相同的颜色和样式(意味着它们使用相同的着色器)。假设着色器将顶点位置设为attribute vec3 aVert,将颜色设为uniform vec4 uColor。
您可能会为每个对象创建一个缓冲区,其中包含该形状的顶点数据。然后渲染:
- 绑定着色器
- 将着色器上的
uColor 统一设置为 [1,0,0,1](红色)
- 立方体:
- 绑定多维数据集缓冲区
- 将缓冲区数据设置为
aVert属性
- 致电
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
- 球体:
- 绑定球体缓冲区
- 将缓冲区数据设置为
aVert属性
- 致电
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
在此示例中,您使用相同的着色器使用两个绘制调用绘制两个不同的缓冲区。
现在假设您有多个立方体,您想用不同的颜色(相同的着色器,但不同的制服)进行渲染。假设您的着色器还采用定位立方体中心的uniform vec3 aPos 值。
- 绑定着色器
- 将缓冲区数据设置为
aVert属性
- 红立方:
- 将着色器上的
uColor 统一设置为 [1,0,0,1](红色)
- 将
uPos 统一设置为[0,0,0]
- 致电
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
- 蓝色立方体:
- 将着色器上的
uColor 统一设置为 [0,0,1,1](蓝色)
- 将
uPos 统一设置为[10,0,0]
- 致电
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
在此示例中,您使用一个着色器将一个缓冲区绘制为两个对象,并使用两个不同的绘制调用,每个绘制调用在该着色器中具有不同的统一值。
我应该创建更多缓冲区或创建更多顶点数组或创建更多程序吗?
可以,或两者都根据需要。你有不同的几何图形要画吗?然后你需要更多的缓冲区。你有不同的方法来渲染那个几何图形吗?然后你需要更多的着色器。缓冲区定义了一个空白画布,着色器是您的油漆和画笔。也许您使用相同的画笔和相同的颜料绘制多个对象,或者您不使用。这取决于你。
我目前正在尝试为一个项目制作多个球体。这些球体将充当围绕原子核运行的电子。基本上我正在尝试制作原子的 3d 模型。
一个缓冲区(一个球体)和一个着色器的简单版本。着色器将定义:
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 缩放球体,然后通过uOrbitAngle 和uOrbitRadius 上的一些三角函数将球体移入轨道。
它会有一个片段着色器,可以进行着色/照明/任何事情,并将结果着色为uColor。
然后你渲染一个氢原子:
- 绑定着色器
- 绑定缓冲区
- 在着色器中设置
aVert属性
- 细胞核:
- 将着色器
uColor 设置为[0.5,0.5,0.5,1](灰色)
- 将着色器
uRadius 设置为10
- 将着色器
uOrbitRadius 设置为0
- 将着色器
uOrbitAngle 设置为0
- 致电
gl.drawArrays()
- 电子:
- 将着色器
uColor 设置为 [1,0,1,1] (megenta)
- 将着色器
uRadius 设置为1
- 将着色器
uOrbitRadius 设置为20
- 将着色器
uOrbitAngle 设置为每帧增加的数量
- 致电
gl.drawArrays()
然后您可以通过重复电子渲染来添加更多电子,只更改uOrbitAngle。
但这实际上取决于您希望这两个对象的外观,这将决定您如何构建它。