1. 首页
  2. IT资讯

「译」WebGL 系列 06 索引缓冲区

这是 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

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code