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(即每个实例的顶点),我似乎并没有完全通过顶点缓冲区,实际上我只是为每个立方体渲染一个三角形然后。
我将如何渲染大量这样的立方体;脸色各异?
实例化的工作方式如下:
最终你会打电话
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)