OpenGL入门教程之 三角形练习

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,然后进行绘制。核心代码如下:

	 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的源代码、两个片段着色器、两个着色器程序,在渲染三角形时激活对应的着色器程序即可。

完整代码

#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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仰望—星空

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值