OpenGL元素缓冲区对象绘制多个三角形
上一节介绍了如何绘制单个三角形。这些练习着眼于如何将其扩展到绘制两个三角形。然而,这涉及重复数据。在本节中,元素缓冲区对象(EBO)用于绘制多个三角形,无需重复顶点数据。
程序A03.java使用EBO渲染两个三角形,以生成一个矩形。
// Two triangles to make a rectangle.
private float[] vertices = { // x,y,z,
-0.5f, 0.5f, 0.0f, // Top Left
-0.5f, -0.5f, 0.0f, // Bottom Left
0.5f, -0.5f, 0.0f, // Bottom Right
0.5f, 0.5f, 0.0f, // Top Right
};
private int[] indices = { // Note that we start from 0
0, 1, 2, // First Triangle
0, 2, 3 // Second Triangle
};
在private float中,我们可以看到列出了四个顶点来描述两个三角形。数组索引描述了如何利用顶点创建两个三角形。
在private int引入了一种新的缓冲区,即元素缓冲区(elementBufferId),用于存储描述三角形的索引-您可能需要在一张纸上绘制三角形以检查您的理解。
/* THE BUFFERS
*/
private int[] vertexBufferId = new int[1];
private int[] vertexArrayId = new int[1];
private int[] elementBufferId = new int[1]; /* new */
private void fillBuffers(GL3 gl) {
gl.glGenVertexArrays(1, vertexArrayId, 0);
gl.glBindVertexArray(vertexArrayId[0]);
gl.glGenBuffers(1, vertexBufferId, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBufferId[0]);
FloatBuffer fb = Buffers.newDirectFloatBuffer(vertices);
gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * vertices.length,
fb, GL.GL_STATIC_DRAW);
int stride = 3; /* new */
int numVertexFloats = 3; /* new */
int offset = 0; /* new */
gl.glVertexAttribPointer(0, numVertexFloats, GL.GL_FLOAT, false, /* changed to */
stride*Float.BYTES, offset); /* use variables */
gl.glEnableVertexAttribArray(0);
gl.glGenBuffers(1, elementBufferId, 0); /* new */
IntBuffer ib = Buffers.newDirectIntBuffer(indices); /* new */
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, elementBufferId[0]); /* new */
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, /* new */
Integer.BYTES * indices.length, ib, GL.GL_STATIC_DRAW);
gl.glBindVertexArray(0);
}
程序显示了render()方法使用EBO所需的更改。
/* THE SCENE
* Now define all the methods to handle the scene.
*/
public void initialise(GL3 gl) {
initialiseShader(gl);
shaderProgram = compileAndLink(gl);
fillBuffers(gl);
}
public void render(GL3 gl) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindVertexArray(vertexArrayId[0]);
gl.glDrawElements(GL.GL_TRIANGLES, indices.length, GL.GL_UNSIGNED_INT, 0); /* new */
gl.glBindVertexArray(0);
}
唯一的变化是用于绘制数据的方法。
public void render(GL3 gl) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glUseProgram(shaderProgram);
gl.glBindVertexArray(vertexArrayId[0]);
gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3); /* drawing one triangle */
gl.glBindVertexArray(0);
}
您应该能够按照Joey的示例来确定JOGL代码中的情况。 正如我之前说过的,即使有更多的顶点可以处理,也可以从一个程序中复制许多用于处理GPU的代码。 我们将在随后的部分中看到这一点。 我们将在后续程序中使用EBO。
练习:
1.可以通过配置OpenGL来绘制三角形的边缘而不是填充三角形来绘制线框的“线框”,而不是填充绘制的三角形。这是在Method Init()内完成的,其中其他OpenGL属性也被类似配置,例如设置背景透明颜色。 (注意:可以使用gl.xyz在JOGL中引用某些OpenGL属性。这适用于已在OpenGL的所有先前版本中可用的属性。但是,有些需要使用特定的OpenGL配置文件,例如GL3.GL3.Gl3.gl_line。大多数情况下,您可以求助于所有使用GL3.XYZ,除非您使用以后的OpenGL 4.x配置文件。)
2.更改程序以绘制三个三角形。 (提示:如图2.12所示,如果您绘制三角形的轮廓,可能会更容易看到发生的事情。)(我们将研究下一章中如何更改三角形的颜色。 )
解决方案:
/* THE DATA
*/
// Two triangles to make a rectangle.
private float[] vertices = { // x,y,z,
-0.5f, 0.5f, 0.0f, // Top Left
-0.5f, -0.5f, 0.0f, // Bottom Left
0.5f, -0.5f, 0.0f, // Bottom Right
0.5f, 0.5f, 0.0f, // Top Right
0.0f, 0.9f, 0.0f // another vertex ***********
};
private int[] indices = { // Note that we start from 0
0, 1, 2, // First Triangle
0, 2, 3, // Second Triangle
0, 3, 4 // Third Triangle *************
};