WebGL; 实例化渲染 - 设置除数

Ske*_*een 0 buffer instance webgl

我正在尝试使用实例化渲染 ( ANGLE_instanced_arrays)在 webgl 中绘制大量立方体。

但是,我似乎无法理解如何设置除数。我有以下缓冲区;

36 个顶点(6 个面由 2 个三角形组成,每个三角形使用 3 个顶点)。每个立方体 6 种颜色(每个面 1 种颜色)。每个立方体翻译 1 次。

重用每个立方体的顶点;我将它的除数设置为 0。对于颜色,我将除数设置为 2(即对两个三角形使用相同的颜色 - 一张脸))。对于平移,我将除数设置为 12(即 6 个面 * 每个面 2 个三角形的相同平移)。

为了渲染我打电话 ext_angle.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 36, num_cubes);

然而,这似乎并没有渲染我的立方体。

使用平移除数 1 确实如此,但那时颜色相差甚远,立方体是单一纯色。

我想这是因为我的实例现在是完整的立方体,但是如果我限制count(即每个实例的顶点),我似乎并没有完全通过顶点缓冲区,实际上我只是为每个立方体渲染一个三角形然后。

我将如何渲染大量这样的立方体;脸色各异?

gma*_*man 6

实例化的工作方式如下:

最终你会打电话

ext.drawArraysInstancedANGLE(mode, first, numVertices, numInstances);
Run Code Online (Sandbox Code Playgroud)

因此,假设您正在绘制立方体的实例。一个立方体有 36 个顶点(每个面 6 个 * 6 个面)。所以

numVertices = 36
Run Code Online (Sandbox Code Playgroud)

假设你想画 100 个立方体

numInstances = 100
Run Code Online (Sandbox Code Playgroud)

假设你有一个像这样的顶点着色器

假设您有以下着色器

attribute vec4 position;

uniform mat4 matrix;

void main() {
  gl_Position = matrix * position;
}
Run Code Online (Sandbox Code Playgroud)

如果你什么都不做,只是打电话

var mode = gl.TRIANGLES;
var first = 0;
var numVertices = 36
var numInstances = 100

ext.drawArraysInstancedANGLE(mode, first, numVertices, numInstances);
Run Code Online (Sandbox Code Playgroud)

它只会在相同的确切位置绘制相同的立方体 100 次

接下来你想给每个立方体一个不同的翻译,所以你更新你的着色器

attribute vec4 position;
attribute vec3 translation;

uniform mat4 matrix;

void main() {
  gl_Position = matrix * (position + vec4(translation, 0));
}
Run Code Online (Sandbox Code Playgroud)

您现在创建一个缓冲区并为每个立方体放置一个翻译,然后像平常一样设置属性

gl.vertexAttribPointer(translationLocation, 3, gl.FLOAT, false, 0, 0)
Run Code Online (Sandbox Code Playgroud)

但是你也设置了一个除数

ext.vertexAttribDivisorANGLE(translationLocation, 1);
Run Code Online (Sandbox Code Playgroud)

那个 1 表示“每个实例只前进到翻译缓冲区中的下一个值一次

现在,您希望每个立方体的每个面都有不同的颜色,并且您只希望数据中的每个面只有一种颜色(您不想重复颜色)。没有任何设置, 因为您numVertices = 36只能选择推进每个顶点(除数 = 0)或每 36 个顶点的倍数(即 numVertices)一次。

所以你说,如果实例面而不是立方体呢?那么现在你遇到了相反的问题。每张脸涂上一种颜色。numVertices = 6, numInstances = 600(100 个立方体 * 每个立方体 6 个面)。您将颜色的除数设置为 1 以在每个面上增加一次颜色。您可以将平移除数设置为 6,以每 6 个面(每 6 个实例)仅推进一次平移。但是现在你不再有一个立方体,你只有一个面。换句话说,您将绘制 600 个面朝同一方向的面,每 6 个面都平移到同一个位置。

要取回立方体,您必须添加一些东西以将面实例定向到 6 个方向。

好的,你用 6 个方向填充了一个缓冲区。那行不通。您不能将除数设置为任何将使用这 6 个方向的任何内容,每个面仅前进一次,然后在下一个立方体的 6 个面后重置。只有 1 个除数设置。将其设置为 6 以重复每个面或 36 以重复每个立方体,但您希望每个面前进重置每个立方体。不存在这样的选项。

你可以做的是用 6 个绘制调用来绘制它,每个面方向一个。换句话说,你要绘制所有的左面,然后是所有的右面,所有的顶面,等等......

为此,我们只制作 1 个面,每个立方体 1 个平移,每个立方体的每个面 1 种颜色。我们将翻译和颜色的除数设置为 1。

然后我们绘制 6 次,每个面方向一次。每次绘制之间的区别在于我们传递了面部的方向,我们更改了颜色属性的属性偏移并将其步幅设置为 6 * 4 浮点数 (6 * 4 * 4)。

ext.drawArraysInstancedANGLE(mode, first, numVertices, numInstances);
Run Code Online (Sandbox Code Playgroud)
numVertices = 36
Run Code Online (Sandbox Code Playgroud)
numInstances = 100
Run Code Online (Sandbox Code Playgroud)