现在,我正在生成大量具有相同顶点的四边形,然后将这些四边形的中心位置作为属性传递,并将比例作为统一传递。
例如,假设有以下缓冲区
顶点缓冲区:
-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
Run Code Online (Sandbox Code Playgroud)
位置缓冲区:
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
Run Code Online (Sandbox Code Playgroud)
然后在顶点着色器中类似:
attribute vec2 aVert;
attribute vec2 aPos;
uniform float uSize;
void main() {
vec2 realVertexPosition = aVert * uSize + aPos;
gl_Position = toScreenSpaceMagic(realVertexPosition);
}
Run Code Online (Sandbox Code Playgroud)
让我感到奇怪的是这里有多少数据重复。
如果我有 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)
Run Code Online (Sandbox Code Playgroud)
然后用类似这样的方式渲染,假设有 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)
})
Run Code Online (Sandbox Code Playgroud)
但我想要的是缓冲区中只有 6 个坐标quads,但调用仍然通过一次绘制调用绘制 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)
Run Code Online (Sandbox Code Playgroud)
但这显然行不通,因为缓冲区中没有 6000 个顶点,只有 6 个。
最后,你可能会问为什么?这在一定程度上是学术性的。这种数据重复让我怀疑这是否是正确的方法。但其次,这是一个在移动设备上运行的 Expo 应用程序,其中一些移动设备的内存限制要低得多。因此,对大量重复数据进行洗牌似乎非常浪费。
| 归档时间: |
|
| 查看次数: |
436 次 |
| 最近记录: |