v4vendeta's homepage

home | project | blog| other

OpenGL-04-DrawTriangle

三角形的绘制


顶点输入

要绘制一个三角形,首先我们要定义一个float类型的数组来储存三角形的三个顶点,我们将三个顶点的z坐标均设为0以表示我们要绘制的三角形是一个平面图形

float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

顶点缓冲对象

定义顶点数据后,我们会把它作为输入发送给顶点着色器,它会在GPU上创建一片内存储存我们的顶点数据,我们用顶点缓冲对象(Vertex Buffer Object,简称VBO)来操作这片内存,VBO实质上是一个unsigned int型变量,我们用glGenBuffer()函数创建缓冲并将缓冲的ID返回给VBO

GLuint VBO;
glGenBuffers(1, &VBO);

调用glGenBuffer()后,我们得到了缓冲对象的ID,但它还不是真正的缓冲对象,在缓冲对象的ID和缓冲类型通过glBindBuffer()函数绑定后,其对应的缓冲对象才会被创建出来

glBindBuffer(GL_ARRAY_BUFFER, VBO);

上文代码中的GL_ARRAY_BUFFER就是一个缓冲对象类型,一个缓冲类型只能和一个缓冲对象绑定,如果新的缓冲对象绑定了已绑定的缓冲对象类型,那么先前的绑定将会销毁。在OpenGL红宝书中给出了一个恰当的比喻:绑定对象的过程就像设置铁路的道岔开关,每一个缓冲类型中的各个对象就像不同的轨道一样,我们将开关设置为其中一个状态,那么之后的列车都会驶入这条轨道。

此后,我们使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)。然后我们可以调用glBufferData()函数,它会把之前定义的顶点数据复制到缓冲的内存中

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

## 顶点数组对象

顶点数组对象(VAO)也是一个 OpenGL 对象,它存储提供顶点数据所需的所有状态,即告诉OpenGL如何读取VBO中所储存的定点数据,创建VAO的方式和VBO类似,通过glGenVertexArrays()glBindVertexArray()创建并绑定

GLunit VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

我们通过glVertexAttribPointer()告诉OpenGL如何解析数据

glVertexAttribPointer(
   0,                  // attribute 0. No particularreason for 0, but must match the layout in the shader.
   3,                 // size
   GL_FLOAT,          // type
   GL_FALSE,          // normalized?
   3 * sizeof(float), // stride
   (void*)0           // array buffer offset
);

glEnableVertexAttribArray(0);

着色器


顶点着色器

顶点着色器(Vertex Shader)是几个可编程着色器中的一个。现代OpenGL需要我们至少设置一个顶点和一个片段着色器。我们会配置两个非常简单的着色器来绘制一个三角形

const char* vertexShaderSource =
"#version 330 core										 \n"
"layout(location = 0) in vec3 aPos;						  \n"
"void main() {											\n"
"	gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);}	   \n";

片段着色器

const char* fragmentShaderSource =
"#version 330 core										  \n"
"out vec4 FragColor;									  \n"
"void main(){											  \n"
"	FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);}			    \n";

编译着色器

	unsigned int vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);

	unsigned int fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);

调用着色器程序

	unsigned int shaderProgram;
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);


绘制

要想绘制我们想要的物体,OpenGL给我们提供了glDrawArrays函数,它使用当前激活的着色器,之前定义的顶点属性配置,和VBO的顶点数据(通过VAO间接绑定)来绘制图元。

//绘制代码(渲染循环中)

glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

输出结果

完整代码

.. ... ...