OpenTK中文教程——1.3.元素缓冲区对象(EBO)

224 阅读3分钟

元素缓冲区对象(EBO)

我们已经渲染了第一个三角形,但如果我们想做更复杂的事情呢?例如,一个矩形?

OpenGL 仅使用三角形工作。它对正方形和其他形状有部分支持,但这些已经废弃了很长时间,不应该再使用。你可以通过定义六个顶点来创建两个看起来像一个形状的三角形,但这是一种浪费,因为矩形只需要四个顶点。虽然这看起来不是什么大问题,但考虑一下立方体:如果不浪费任何一个顶点,只需要八个顶点,但如果你采用每个面由两个三角形组成的方法,单个立方体就需要 36 个顶点!模型越复杂,数字只会变得更糟;显然,需要一种更好的方法。

有许多不同的方法可以实现这一点(例如三角形带),在本教程中,我们将使用一种称为元素缓冲对象的东西,这是一种缓冲区类型,允许我们重复使用顶点来创建多个图元。通过使用EBO,我们将能够仅使用四个顶点创建一个矩形。

将你的顶点数组替换为以下内容:

float[] vertices = {
     0.5f,  0.5f, 0.0f,  // 右上
     0.5f, -0.5f, 0.0f,  // 右下
    -0.5f, -0.5f, 0.0f,  // 左下
    -0.5f,  0.5f, 0.0f   // 左上
};

然后,在其下方添加以下数组:

uint[] indices = {  // 注意我们从0开始!
    0, 1, 3,   // 第一个三角形
    1, 2, 3    // 第二个三角形
};

索引数组将被送入我们的EBO,以指定将使用哪些顶点来创建三角形。这个数组将使用顶点0、1和3来创建一个三角形,以及使用顶点1、2和3来创建第二个三角形。

接下来,作为属性,在您添加VertexBufferObject的地方添加int ElementBufferObject这一行。

现在,在OnLoad中,在初始化VertexBufferObject之后,我们以类似的方式初始化ElementBufferObject

ElementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.StaticDraw);
警告\color{#FAAD14}{警告}(掘金没有警告框真是要了老命!)

绑定元素数组缓冲区是特殊的,因为它只有在当前绑定了VAO的情况下才能被绑定。从概念上讲,可以认为VAO拥有绑定槽。如果你解绑VAO,元素数组缓冲区仍然绑定到VAO!

这几乎和你使用VBO的方式完全一样!OpenGL的大多数缓冲区类型都会遵循这种模式:使用GL.GenBuffer()创建,使用GL.BindBuffer绑定,然后使用GL.BufferData向其中添加数据。

EBO现在已经准备好了。在OnRenderFrame中,将DrawArrays的调用替换为以下内容:

GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0);

参数依次为:

  • 原始类型。和上次一样,我们希望使用原始三角形。
  • 要绘制的顶点数量。我们使用索引的长度来绘制所有内容。
  • EBO 元素的类型。无符号整数。
  • 要绘制内容的偏移量。由于我们要绘制所有内容,因此我们只需使用 0。

这就够了!如果你现在运行你的程序,你应该能够看到你有一个矩形而不是一个三角形。