现在,我正在生成大量具有相同顶点的四边形,然后将这些四边形的中心位置作为属性传递,并将比例作为一致性传递。
例如,假设以下缓冲区
垂直缓冲区:
-1,-1, -1,1, 1,1, 1,1, 1,-1, -1,1 // quad #1
-1,-1, -1,1, 1,1, 1,1, 1,-1, -1,1 // quad #2
-1,-1, -1,1, 1,1, 1,1, 1,-1, -1,1 // quad #3
-1,-1, -1,1, 1,1, 1,1, 1,-1, -1,1 // quad #3
位置缓冲器:
10,10, 10,10, 10,10, 10,10, 10,10, 10,10 // position of quad #1
20,20, 20,20, 20,20, 20,20, 20,20, 20,20 // position of quad #2
30,30, 30,30, 30,30, 30,30, 30,30, 30,30 // position of quad #3
40,40, 40,40, 40,40, 40,40, 40,40, 40,40 // position of quad #4
然后在顶点着色器中,类似于:
attribute vec2 aVert;
attribute vec2 aPos;
uniform float uSize;
void main() {
vec2 realVertexPosition = aVert * uSize + aPos;
gl_Position = toScreenSpaceMagic(realVertexPosition);
}
让我感到奇怪的是,这里有多少数据重复。
如果有1000个四边形,那么相同的顶点数据会重复1000次。每个四边形的位置重复6次。
那么,有没有办法重用一个小缓冲区并告诉WebGL它是如何重复的呢?例如,告诉WebGL一个缓冲区1000次,其中只有一个四边形的顶点?
// pointsToQuads returns a [number, number][] with 6 elements
// for each point, 3 points for each triangle in quad.
// Note how each quad has a `pos` (meaning the center) of [0,0].
const quads = pointsToQuads(
layoutNodes.map(() => ({
pos: [0, 0],
size: { width: 1, height: 1 },
})),
)
// calls gl.bufferData() with the flattened array of values.
this.buffers.quads.updateBuffer(quads)
// Fill a buffer of center positions for every vertex.
// dupeEntries() here changes clones each element at it's
// original index 6 times, one for each vertex of that quad.
// This duplicates the same point six times.
this.buffers.positions.updateBuffer(
dupeEntries(
layoutNodes.map((node) => node.position),
6,
),
)
// Generate other buffers (UVs, vertex colors, etc)
然后使用如下方式渲染,假设1000个四边形:
// Calls gl.useProgram()
shaderPrograms.layoutPoints.use((shader) => {
// Calls gl.vertexAttribPointer() for each attribute.
shader.setAttributes({
// here are the same six points cloned 1000 times.
aVert: this.buffers.quads,
aUV: this.buffers.uv,
aIconUV: this.buffers.iconUv,
aPos: this.buffers.positions,
aColor: this.buffers.stateColors,
})
// Calls gl.uniform[1,2,3,4]f() for each uniform
shader.setUniforms({ uSize: styles.pointsLayout.size })
// One draw calls now renders all 1000 quads, so count here is 1000 * 6.
gl.drawArrays(gl.TRIANGLES, 0, this.buffers.quads.count)
})
但我想要的是,在这个坐标系中只有六个坐标
quads
缓冲区,但调用仍然使用一个draw调用绘制1000个四边形。
类似于:
// only six points in `buffer`
gl.bindBuffer(gl.ARRAY_BUFFER, buffer.glBuffer)
// Repeat buffer 1000 times.
gl.vertexAttribPointer(attribute, 1000 * 6, gl.FLOAT, false, 0, 0)
// Then one draw call
gl.drawArrays(gl.TRIANGLES, 0, 1000 * 6)
但这显然不起作用,因为缓冲区中没有6000个顶点,只有6个。
最后,你可能会问为什么?这在一定程度上是学术性的。这种重复的数据让我怀疑这是否是正确的方法。但第二,这是一个将在移动设备上运行的Expo应用程序,其中一些设备的内存限制要低得多。因此,在大量重复数据中来回移动似乎是相当浪费的。