跳转到内容

游戏开发/渲染与游戏引擎/OpenGL/绘制几何体

50% developed
来自维基教科书,自由的教科书

绘制颜色的几何体

[编辑 | 编辑源代码]

这是将三角形的顶点数据传递给 OpenGL 的方法。

数据在一个数组中指定,每三个顶点表示一个新的三角形。在此格式中,需要按照连接的顺序指定数据。

#include <gl\glew.h>
#include <MyGLWindow.h>

void MyGLWindow::initializeGL(){
	GLfloat verts[] =
	{
                //1st Triangle
		+0.0f, +1.0f, +0.0f, //Vertex 1
		-1.0f, -1.0f, -0.5f, //Vertex 2
		+1.0f, -1.0f, +0.5f, //Vertex 3
                //2nd Triangle
		+0.0f, -1.0f, +0.0f, //Vertex 1
		-1.0f, +1.0f, -0.5f, //Vertex 2
		+1.0f, +1.0f, +0.5f, //Vertex 3
	};
	GLuint myBufferID;
	glGenBuffers(1, &myBufferID); //Generate an identifier for the buffer ID
	glBindBuffer(GL_ARRAY_BUFFER, myBufferID); //Bind it to the array buffer binding point
	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); //Send the size of the data and the data to the buffer assigned to the array buffer binding point.

	//Describing the data
	glEnableVertexAttribArray(0); //The first attribute to send to openGL (later redirected through a vertex shader)
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); //There are 3 floats per vertex...
}

void MyGLWindow::paintGL(){
	glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
	glDrawArrays(GL_TRIANGLES, 0, 6); //Connect the 6 vertices into triangles (triangle=3, 6/3 = 2 triangles)
}

这段代码很容易修改为只传递 2D 数据,为此你需要更改两件事。

  • 数组应该只包含 X 和 Y 坐标。
  • glVertexAttribPointer 参数 2 需要从 3 更改为 2。

几何体的优化绘制

[编辑 | 编辑源代码]

此程序的新版本传递顶点位置的 ID,以说明如何连接三角形。对于没有连接的基本三角形,这比之前效率低,但是对于大多数形状,三角形将共享顶点,这意味着你不需要指定 3 个数据(XYZ,如果添加颜色和光照法线则更多),只需要传递一个额外的短整型作为顶点索引。这样可以节省内存,因为需要更少的数据,并且对于动画几何体,这意味着需要发送到 OpenGL 及更远端的数据副本更少。

#include <gl\glew.h>
#include <MyGLWindow.h>

void MyGLWindow::initializeGL(){
	GLfloat verts[] =
	{
                //1st Triangle
		+0.0f, +1.0f, +0.0f, //Vertex 1
		-1.0f, -1.0f, -0.5f, //Vertex 2
		+1.0f, -1.0f, +0.5f, //Vertex 3
                //2nd Triangle
		+0.0f, -1.0f, +0.0f, //Vertex 1
		-1.0f, +1.0f, -0.5f, //Vertex 2
		+1.0f, +1.0f, +0.5f, //Vertex 3
	};
	GLuint myBufferID;
	glGenBuffers(1, &myBufferID); //Num buffers, BufferID
	glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

        //Assigning the positions of the vertices into 2 triangle (triangle 1= {0,1,2}, triangle 2={3,4,5})
        GLushort indices[] = {0,1,2,  3,4,5};
	GLuint indexBufferID;
	glGenBuffers(1, &indexBufferID); //Generate an identifier for the index buffer ID
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); //Link the index buffer to the element array buffer binding point
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //Send the size of the data and the data to the index buffer, linked to the element array buffer binding point.

	//Describing the data
	glEnableVertexAttribArray(0); //The first attribute
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); A vertex consists of 3 floats
}

void MyGLWindow::paintGL(){
	glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0); //Notice this is different from above
}

绘制颜色的几何体(保留之前的优化)

[编辑 | 编辑源代码]

注意:在设置片段着色器之前,颜色不会生效。但是,要设置片段着色器,你需要从顶点着色器发送颜色数据。

#include <gl\glew.h>
#include <MyGLWindow.h>

void MyGLWindow::initializeGL(){
	GLfloat verts[] =
	{
                //One colourful triangle being drawn
		+0.0f, +1.0f, +0.0f, //Vertex 1
                +1.0f, +0.0f, +0.0f, //Vertex 1's Color (Red)

		-1.0f, -1.0f, -0.5f, //Vertex 2
                +0.0f, +1.0f, +0.0f, //Vertex 2's Color (Green)

		+1.0f, -1.0f, +0.5f, //Vertex 3
                +0.0f, +0.0f, +1.0f, //Vertex 3's Color (Blue)
	};
	GLuint myBufferID;
	glGenBuffers(1, &myBufferID); //Num buffers, BufferID
	glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
	glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

        GLushort indices[] = {0,1,2};
	GLuint indexBufferID;
	glGenBuffers(1, &indexBufferID);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//Describing the data
	glEnableVertexAttribArray(0); //The first attribute (Vertex data)
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6,0); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices
	glEnableVertexAttribArray(1); //The second attribute (Color data)
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6, (char*)(sizeof(float)*3)); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices. The first piece of data starts after 3 floats.
}

void MyGLWindow::paintGL(){
	glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
}

参考文献

[编辑 | 编辑源代码]
华夏公益教科书