OpenGL入门教程
本文章被包含在OpenGL学习专栏中。
本练习基于OpenGL绘制三角形中绘制三角形的代码程序。
练习题目
1.绘制两个彼此相连的三角形。
2.创建相同的两个三角形,对它们的数据使用不同的VAO和VBO。
3.创建两个着色器程序。使用两个着色器程序分别绘制出一个绿色三角形和黄色三角形。
题目一
解题思路
要绘制两个三角形,我们只需要给顶点数据添加三个顶点,然后在渲染循环中使用"glDrawArrays(GL_TRIANGLES, 0, 6)"函数,即可绘制两个三角形。
glDrawArrays函数中第一个参数表示打算绘制的OpenGL图元类型,第二个参数指定顶点数组的起始索引,第三个参数指定我们打算绘制多少个顶点。
对于VBO而言它依旧会将顶点数据复制到显存中,对于VAO而言顶点数据的读取方式依旧是三个GLfloat类型为一个顶点属性,因此VAO和VBO不需要进行调整。
还要注意的是顶点数据位置坐标需要在[-1,1]内,否则会无法显示。
解题代码
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// 定义窗口大小
const GLuint WIDTH = 800, HEIGHT = 600;
// 定义字符串:着色器源代码(这种形式会自动拼接,分行只是好看)
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main()
{
// GLFW的初始化
glfwInit();
// GLFW的配置
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// 创建glfw窗口并设置窗口的状态为当前线程的主状态
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// 设置glew更加现代化
glewExperimental = GL_TRUE;
// 初始化glew
glewInit();
// 定义视口左下角在窗口的位置 和 视口的大小
glViewport(0, 0, 800, 600);
// 顶点着色器的创建、绑定源代码、编译
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 检查顶点着色器编译是否成功
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 片段着色器的创建、绑定源代码、编译
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 检查片段色器编译是否成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 创建着色器程序、添加着色器后链接着色器
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 检查链接是否成功
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
// 链接失败则获取原因并打印
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// 链接着色器后就删除着色器,节省显存
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 定义顶点属性数据(可以自定义任意格式)
GLfloat vertices[] = {
// First triangle
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
// Second triangle
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
// 创建VAO、VBO
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 绑定VAO
glBindVertexArray(VAO);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// 将顶点数据vertices复制到GL_ARRAY_BUFFER绑定的对象VBO中
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAO中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 解绑VBO(因为暂时不需要再向这个VBO传入数据了)
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 解绑VAO(因为暂时不需要再配置这个VAO的解析方式了)
// 要用的时候再绑定需要的VAO
glBindVertexArray(0);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
// 检查窗口事件
glfwPollEvents();
// 清空屏幕缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
glUseProgram(shaderProgram);
// 需要使用VAO解析顶点数据
glBindVertexArray(VAO);
// 根据传入VBO显存中的顶点数据和VAO解析方式渲染
glDrawArrays(GL_TRIANGLES, 0, 6);
// 使用完解除VAO绑定
glBindVertexArray(0);
// 交换缓冲区
glfwSwapBuffers(window);
}
// 删除VAO、VBO释放显存
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// 释放glfw申请的内存
glfwTerminate();
return 0;
}
题目二
解题思路
使用不同的VAO和VBO管理两个三角形的顶点数据之前,我们需要将题目一代码中三角形的顶点数据分开为两个顶点数据。配置VBO和VAO的核心代码如下所示:
// 第一个三角形的顶点数据
GLfloat firstTriangle[] = {
// First triangle
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
};
// 第二个三角形的顶点数据
GLfloat secondTriangle[] = {
// Second triangle
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
// 创建VAO、VBO,要注意是数组,传入无需&
GLuint VBOs[2], VAOs[2];
glGenVertexArrays(2, VAOs);
glGenBuffers(2, VBOs);
// 第一个三角形VBO和VAO的配置
// 绑定VAO
glBindVertexArray(VAOs[0]);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
// 将顶点数据firstTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[0]中
glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[0]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 第二个三角形VBO和VAO的配置
// 绑定VAO
glBindVertexArray(VAOs[1]);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
// 将顶点数据secondTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[1]中
glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[1]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
在渲染循环中,对每个三角形使用对应的VAO,然后进行绘制。核心代码如下:文章来源:https://www.toymoban.com/news/detail-420368.html
glBindVertexArray(VAOs[0]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(VAOs[1]);
glDrawArrays(GL_TRIANGLES, 0, 3);
// 使用完解除VAO绑定
glBindVertexArray(0);
完整代码
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// 定义窗口大小
const GLuint WIDTH = 800, HEIGHT = 600;
// 定义字符串:着色器源代码(这种形式会自动拼接,分行只是好看)
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main()
{
// GLFW的初始化
glfwInit();
// GLFW的配置
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// 创建glfw窗口并设置窗口的状态为当前线程的主状态
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// 设置glew更加现代化
glewExperimental = GL_TRUE;
// 初始化glew
glewInit();
// 定义视口左下角在窗口的位置 和 视口的大小
glViewport(0, 0, 800, 600);
// 顶点着色器的创建、绑定源代码、编译
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 检查顶点着色器编译是否成功
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 片段着色器的创建、绑定源代码、编译
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// 检查片段色器编译是否成功
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 创建着色器程序、添加着色器后链接着色器
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 检查链接是否成功
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
// 链接失败则获取原因并打印
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// 链接着色器后就删除着色器,节省显存
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 第一个三角形的顶点数据
GLfloat firstTriangle[] = {
// First triangle
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
};
// 第二个三角形的顶点数据
GLfloat secondTriangle[] = {
// Second triangle
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
// 创建VAO、VBO,要注意是数组,传入无需&
GLuint VBOs[2], VAOs[2];
glGenVertexArrays(2, VAOs);
glGenBuffers(2, VBOs);
// 第一个三角形VBO和VAO的配置
// 绑定VAO (传入数组首地址)
glBindVertexArray(VAOs[0]);
// 绑定VBO (传入数组首地址)
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
// 将顶点数据firstTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[0]中
glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[0]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 第二个三角形VBO和VAO的配置
// 绑定VAO
glBindVertexArray(VAOs[1]);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
// 将顶点数据secondTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[1]中
glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[1]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 解绑VBO(因为暂时不需要再向这个VBO传入数据了)
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 解绑VAO(因为暂时不需要再配置这个VAO的解析方式了)
// 要用的时候再绑定需要的VAO
glBindVertexArray(0);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
// 检查窗口事件
glfwPollEvents();
// 清空屏幕缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
glUseProgram(shaderProgram);
// 需要使用VAO解析顶点数据
glBindVertexArray(VAOs[0]);
// 根据传入VBO显存中的顶点数据和VAO解析方式渲染
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(VAOs[1]);
// 根据传入VBO显存中的顶点数据和VAO解析方式渲染
glDrawArrays(GL_TRIANGLES, 0, 3);
// 使用完解除VAO绑定
glBindVertexArray(0);
// 交换缓冲区
glfwSwapBuffers(window);
}
// 删除VAO、VBO释放显存
glDeleteVertexArrays(2, VAOs);
glDeleteBuffers(2, VBOs);
// 释放glfw申请的内存
glfwTerminate();
return 0;
}
题目三
解题思路
创建两个fragmentShader的源代码、两个片段着色器、两个着色器程序,在渲染三角形时激活对应的着色器程序即可。文章来源地址https://www.toymoban.com/news/detail-420368.html
完整代码
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// 定义窗口大小
const GLuint WIDTH = 800, HEIGHT = 600;
// 定义字符串:着色器源代码(这种形式会自动拼接,分行只是好看)
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource1 = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
const GLchar* fragmentShaderSource2 = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";
int main()
{
// GLFW的初始化
glfwInit();
// GLFW的配置
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// 创建glfw窗口并设置窗口的状态为当前线程的主状态
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// 设置glew更加现代化
glewExperimental = GL_TRUE;
// 初始化glew
glewInit();
// 定义视口左下角在窗口的位置 和 视口的大小
glViewport(0, 0, 800, 600);
// 顶点着色器的创建、绑定源代码、编译
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// 检查顶点着色器编译是否成功
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 片段着色器的创建、绑定源代码、编译
GLuint fragmentShader1 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader1, 1, &fragmentShaderSource1, NULL);
glCompileShader(fragmentShader1);
// 检查片段色器编译是否成功
glGetShaderiv(fragmentShader1, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(fragmentShader1, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT1::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 片段着色器的创建、绑定源代码、编译
GLuint fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader2, 1, &fragmentShaderSource2, NULL);
glCompileShader(fragmentShader2);
// 检查片段色器编译是否成功
glGetShaderiv(fragmentShader2, GL_COMPILE_STATUS, &success);
if (!success)
{
// 着色器源代码编译失败则获取原因并打印
glGetShaderInfoLog(fragmentShader2, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT2::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// 创建着色器程序、添加着色器后链接着色器
GLuint shaderProgram1 = glCreateProgram();
glAttachShader(shaderProgram1, vertexShader);
glAttachShader(shaderProgram1, fragmentShader1);
glLinkProgram(shaderProgram1);
// 检查链接是否成功
glGetProgramiv(shaderProgram1, GL_LINK_STATUS, &success);
if (!success) {
// 链接失败则获取原因并打印
glGetProgramInfoLog(shaderProgram1, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM1::LINKING_FAILED\n" << infoLog << std::endl;
}
// 创建着色器程序、添加着色器后链接着色器
GLuint shaderProgram2 = glCreateProgram();
glAttachShader(shaderProgram2, vertexShader);
glAttachShader(shaderProgram2, fragmentShader2);
glLinkProgram(shaderProgram2);
// 检查链接是否成功
glGetProgramiv(shaderProgram2, GL_LINK_STATUS, &success);
if (!success) {
// 链接失败则获取原因并打印
glGetProgramInfoLog(shaderProgram2, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM1::LINKING_FAILED\n" << infoLog << std::endl;
}
// 链接着色器后就删除着色器,节省显存
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader1);
glDeleteShader(fragmentShader2);
// 第一个三角形的顶点数据
GLfloat firstTriangle[] = {
// First triangle
-0.9f, -0.5f, 0.0f, // Left
-0.0f, -0.5f, 0.0f, // Right
-0.45f, 0.5f, 0.0f, // Top
};
// 第二个三角形的顶点数据
GLfloat secondTriangle[] = {
// Second triangle
0.0f, -0.5f, 0.0f, // Left
0.9f, -0.5f, 0.0f, // Right
0.45f, 0.5f, 0.0f // Top
};
// 创建VAO、VBO,要注意是数组,传入无需&
GLuint VBOs[2], VAOs[2];
glGenVertexArrays(2, VAOs);
glGenBuffers(2, VBOs);
// 第一个三角形VBO和VAO的配置
// 绑定VAO (传入数组首地址)
glBindVertexArray(VAOs[0]);
// 绑定VBO (传入数组首地址)
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
// 将顶点数据firstTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[0]中
glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[0]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 第二个三角形VBO和VAO的配置
// 绑定VAO
glBindVertexArray(VAOs[1]);
// 绑定VBO
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
// 将顶点数据secondTriangle复制到GL_ARRAY_BUFFER绑定的对象VBOs[1]中
glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
// 设置解析顶点数据的方式到绑定VertexArray的VAOs[1]中
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用顶点属性0号位置
glEnableVertexAttribArray(0);
// 解绑VBO(因为暂时不需要再向这个VBO传入数据了)
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 解绑VAO(因为暂时不需要再配置这个VAO的解析方式了)
// 要用的时候再绑定需要的VAO
glBindVertexArray(0);
// 渲染循环
while (!glfwWindowShouldClose(window))
{
// 检查窗口事件
glfwPollEvents();
// 清空屏幕缓存
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 使用着色器程序
glUseProgram(shaderProgram1);
// 需要使用VAO解析顶点数据
glBindVertexArray(VAOs[0]);
// 根据传入VBO显存中的顶点数据和VAO解析方式渲染
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(shaderProgram2);
glBindVertexArray(VAOs[1]);
// 根据传入VBO显存中的顶点数据和VAO解析方式渲染
glDrawArrays(GL_TRIANGLES, 0, 3);
// 使用完解除VAO绑定
glBindVertexArray(0);
// 交换缓冲区
glfwSwapBuffers(window);
}
// 删除VAO、VBO释放显存
glDeleteVertexArrays(2, VAOs);
glDeleteBuffers(2, VBOs);
// 释放glfw申请的内存
glfwTerminate();
return 0;
}
到了这里,关于OpenGL入门教程之 三角形练习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!