这是 WebGL 系列的第 6 天教程,每天都有新文章发布。
第 5 天我们已经学习了如何使用交错缓冲区。但是,因为某些多边形之间会共用顶点,使得我们的缓冲区包含大量重复数据。
让我们回到简单的矩形示例:
📄 src/webgl-hello-world.js
[128, 0.0, 128, 255], // purple
];
- const triangles = createHexagon(canvas.width / 2, canvas.height / 2, canvas.height / 2, 7);
+ const triangles = createRect(0, 0, canvas.height, canvas.height);
function createHexagon(centerX, centerY, radius, segmentsCount) {
const vertexData = [];
使用仅有的顶点坐标进行填充:
📄 src/webgl-hello-world.js
const triangles = createRect(0, 0, canvas.height, canvas.height);
+ function createRect(top, left, width, height) {
+ return [
+ left, top, // x1 y1
+ left + width, top, // x2 y2
+ left, top + height, // x3 y3
+ left + width, top + height, // x4 y4
+ ];
+ }
+
function createHexagon(centerX, centerY, radius, segmentsCount) {
const vertexData = [];
const segmentAngle = Math.PI * 2 / (segmentsCount - 1);
让我们现在暂时禁用颜色属性
📄 src/webgl-hello-world.js
const attributeSize = 2;
const type = gl.FLOAT;
const nomralized = false;
- const stride = 24;
+ const stride = 0;
const offset = 0;
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, attributeSize, type, nomralized, stride, offset);
- gl.enableVertexAttribArray(colorLocation);
- gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
+ // gl.enableVertexAttribArray(colorLocation);
+ // gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
gl.drawArrays(gl.TRIANGLES, 0, vertexData.length / 6);
好的,这样我们的缓冲区包含 4
个顶点数据,但是 webgl
如何仅用 4
个顶点渲染 2 个三角形?
这是一种特殊的缓冲区,可以指定如何从顶点缓冲区中获取数据并构建图元(在我们的示例中为三角形)
这个缓冲区叫做 index buffer
,它包含顶点缓冲区中顶点数据块的索引。
因此,我们需要指定三角形顶点的索引。
📄 src/webgl-hello-world.js
const vertexData = new Float32Array(triangles);
const vertexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
+ const indexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
+
+ const indexData = new Uint6Array([
+ 0, 1, 2, // first triangle
+ 1, 2, 3, // second trianlge
+ ]);
+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
gl.lineWidth(10);
下一步 – 将数据上传到 WebGL 缓冲区。
告诉 GPU,我们使用的是 index buffer
,我们需要传递 gl.ELEMENT_ARRAY_BUFFER
作为 gl.bindBuffer
和 gl.bufferData
第一个参数。
📄 src/webgl-hello-world.js
1, 2, 3, // second trianlge
]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
gl.lineWidth(10);
最后一步:渲染索引顶点,我们还需要调用其他方法 – 使用 drawElements
而不是 drawArrays
。
📄 src/webgl-hello-world.js
const indexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
- const indexData = new Uint6Array([
+ const indexData = new Uint8Array([
0, 1, 2, // first triangle
1, 2, 3, // second trianlge
]);
// gl.enableVertexAttribArray(colorLocation);
// gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
- gl.drawArrays(gl.TRIANGLES, 0, vertexData.length / 6);
+ gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_BYTE, 0);
等等,为什么没有渲染?
原因是我们已经禁用了 color
属性,所以它填充了零,(0, 0, 0, 0)
– 透明黑色。
我们把它修改好:
📄 src/webgl-hello-world.js
void main() {
gl_FragColor = vColor / 255.0;
+ gl_FragColor.a = 1.0;
}
`;
结论
现在,我们知道了如何使用索引缓冲区,来清除需要上传到 gpu
的顶点数量。
上面的矩形示例也很简单(仅复制 2
个顶点),也就是只使用 33%
,从而在渲染大量数据时,尤其是频繁更新顶点数据并重新上传缓冲区内容的时候,能够带来很大的性能提升。
作业
使用索引缓冲区渲染 n-gon
明天见👋
本文来自投稿,不代表程序员编程网立场,如若转载,请注明出处:http://www.cxybcw.com/202967.html