OpenGL入门教程之 三角形练习

这篇具有很好参考价值的文章主要介绍了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的源代码、两个片段着色器、两个着色器程序,在渲染三角形时激活对应的着色器程序即可。文章来源地址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模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包