VAO-VBO-EBO
概念部分:
VAO:顶点数组对象
VBO:顶点缓存对象
EBO:索引缓存对象
VAO用来管理缓存的数据
VBO用来存储缓存的数据
EBO用来存储每个三角形的点索引
VAO的初始化
//VAO顶点数组对象
unsigned int VAO;
//创建一个VAO对象,使用VAO无符号整型存储索引
glGenVertexArrays(1, &VAO);
//进行绑定
glBindVertexArray(VAO);
VBO的初始化
顶点数据
//顶点数据
float vertices[] = {
//opengl本身采用的是逆时针绘制三角形
//当其为顺时针的时候,其实绘制的是三角形的背面。
//逆时针
-0.5f,-0.5f,0.0f,//0
0.5f,-0.5f,0.0f,//1
0.0f,0.5f,0.0f,//2
//顺时针
/*0.5f,-0.5f,0.0f,
0.0f,0.5f,0.0f,*/
0.8f,0.8f,0.0f,//3
};
//VBO顶点缓冲对象
unsigned int VBO;
glGenBuffers(1, &VBO);//生成一个缓冲,但是此时opengl并不知道对象类型是什么,所以需要进行绑定
//绑定缓冲类型--顶点缓冲
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//将顶点数据写入到顶点缓冲中
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices), vertices,GL_STATIC_DRAW);
GL_STATIC_DRAW表示数据不会被修改
EBO的初始化
索引数组
//索引缓存数组
unsigned int indices[] = {
0,1,2,//第一个三角形
1,2,3//第二个三角形
};
//创建EBO对象
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices, GL_STATIC_DRAW);
顶点着色器
//创建EBO对象
//GLSL顶点着色器的源代码
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";
顶点着色器初始化
//顶点着色器
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);//编译着色器
片段着色器
//片段着色器的源代码
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 fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);//编译着色器
片段着色器和顶点着色器进行链接‘
//shader program---将vertexShader和fragmentShader连接成一个program
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
循环渲染
回调
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
//检查按键是否按下
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
渲染实现
通过判断窗口是否关闭实现==
//循环渲染
while (!glfwWindowShouldClose(window)) {//检查glfw是否被退出
//检查按键是否按下
processInput(window);
//渲染指令
//glClearColor设置清空屏幕所用的颜色----状态设置函数
//glClear函数清除颜色缓冲之后,屏幕会填充为glClearColor中的颜色。---状态使用函数
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//画三角形
glBindVertexArray(VAO);
glUseProgram(shaderProgram);
//glDrawArrays(GL_TRIANGLES,0,6);//画6个点
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//检查调用事件,交换缓存
//双缓冲:前面缓存一张画面用于显示,后台会额外缓存另一张,当第一张结束,直接交换,效果上便不会有重新逐行绘制带来的闪屏。
glfwSwapBuffers(window);//交换颜色缓存
glfwPollEvents();//检查鼠标,键盘,更新窗口状态,并调用对应的回调函数。
}
关于opengl的绘制顺序
opengl采用的逆时针绘制,同时默认会绘制正反面,当给到的顶点缓存数据中顶点坐标为顺时针时,显示的为绘制结果的反面。
可以通过如下操作进行修改绘制面的显示:(显示背面)
//设置opengl绘制图像时,正面和背面的关系。
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);