OpenGL--使用ImGui渲染三角形

OpenGL–使用ImGui渲染三角形

首先看一下作业要求:
OpenGL--使用ImGui渲染三角形_第1张图片
OpenGL--使用ImGui渲染三角形_第2张图片

下面是我实现的代码:

#include "imgui/imgui.h"
#include "imgui_impl_glfw_gl3.h"
#include 
#include   //  使用gl3w,glad也行,注意要在项目工程中添加gl3w.c(或者glad.c/使用glad)
#include 
#include 

//当用户改变窗口的大小的时候,视口也应该被调整。我们可以对窗口注册一个回调函数,它会在每次窗口大小被调整的时候被调用。
//其实我把教程的这个函数删掉对结果也没有影响,不过教程说对于Retina屏幕输入的width和height都会比原值大,所以保留这个函数
void window_size_callback(GLFWwindow* window, int width, int height);

// 设置窗口大小
const unsigned int Window_width = 1600;
const unsigned int Window_height = 1200;

//使用GLSL编写出来的顶点着色器和片段着色器的代码
//顶点着色器主要是把输入的数据转化为标准化设备坐标,把它们转换至OpenGL的可视区域内
//片段着色器所做的是计算像素最后的颜色输出,可以理解为我们所画的图元“上色”
//这两个着色器程序都是最简单的程序,没有对输入的数据做任何处理就输出了
const char *VertexShaderCode = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 ourColor;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos, 1.0);\n"
"   ourColor = aColor;\n"
"}\0";
const char *FragmentShaderCode = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 ourColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(ourColor, 1.0f);\n"
"}\n\0";

int main()
{
    // 实例化GLFW窗口
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //下面这条语句是为了适应苹果系统
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // 创建一个窗口对象,这个窗口对象存放了所有和窗口相关的数据,而且会被GLFW的其他函数频繁地用到。
    // 此外增加 if (window == NULL) 判断窗口是否创建成功
    GLFWwindow* window = glfwCreateWindow(Window_width, Window_height, "ImGui Triangle", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, window_size_callback);
    glfwSwapInterval(1);

    //初始化gl3w
    gl3wInit();

    //创建并绑定ImGui
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    ImGui_ImplGlfwGL3_Init(window, true);
    ImGui::StyleColorsClassic();

    // 建立 shader program
    // 顶点着色器
    int VShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VShader, 1, &VertexShaderCode, NULL);
    glCompileShader(VShader);
    // 检查顶点着色器是否编译成功
    int success_compiler;
    char wrong_information[512];
    glGetShaderiv(VShader, GL_COMPILE_STATUS, &success_compiler);
    if (!success_compiler)
    {
        glGetShaderInfoLog(VShader, 512, NULL, wrong_information);
        std::cout << "顶点着色器编译失败:\n" << wrong_information << std::endl;
    }
    // 片段着色器
    int FShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(FShader, 1, &FragmentShaderCode, NULL);
    glCompileShader(FShader);
    // 检查片段着色器是否编译成功
    glGetShaderiv(FShader, GL_COMPILE_STATUS, &success_compiler);
    if (!success_compiler)
    {
        glGetShaderInfoLog(FShader, 512, NULL, wrong_information);
        std::cout << "片段着色器编译失败:\n" << wrong_information << std::endl;
    }
    // 链接着色器
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, VShader);
    glAttachShader(shaderProgram, FShader);
    glLinkProgram(shaderProgram);
    // 检查链接着色器是否成功
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success_compiler);
    if (!success_compiler) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, wrong_information);
        std::cout << "着色器程序链接失败:\n" << wrong_information << std::endl;
    }
    //在把着色器对象链接到程序对象以后,删除不再需要的着色器对象
    glDeleteShader(VShader);
    glDeleteShader(FShader);

    //初始化各种数据
    ImVec4 top_color = ImVec4(0.0f, 1.0f, 0.0f, 1.00f);
    ImVec4 left_color = ImVec4(1.0f, 0.0f, 0.0f, 1.00f);
    ImVec4 right_color = ImVec4(0.0f, 0.0f, 1.0f, 1.00f);
    ImVec4 bottom_color = ImVec4(0.0f, 1.0f, 1.0f, 1.00f);
    ImVec4 same_color = ImVec4(0.0f, 1.0f, 0.0f, 1.00f);
    bool ImGui = true;
    bool the_same_color = false;
    bool draw_trangle_without_render = false;
    bool draw_trangle = false;
    bool bonus_draw_line = false;
    bool bonus_draw_another_trangle = false;
    unsigned int VBO, VAO, EBO;

    // 渲染循环
    while (!glfwWindowShouldClose(window))
    {

        if (the_same_color) {
            top_color = same_color;
            left_color = same_color;
            right_color = same_color;
            bottom_color = same_color;
        }

        float vertices[] = {
            // 坐标              // 颜色
            0.2f, -0.2f, 0.0f,  right_color.x, right_color.y, right_color.z,  // bottom right
            -0.2f, -0.2f, 0.0f, left_color.x, left_color.y, left_color.z,  // bottom left
            0.0f,  0.2f, 0.0f,  top_color.x, top_color.y, top_color.z,   // top 
            0.0f,  -0.8f, 0.0f,  bottom_color.x, bottom_color.y, bottom_color.z   // bottom

        };

        unsigned int indices[] = { // 注意索引从0开始
            0, 1, 2, // 第一个三角形
            0, 1, 3  // 第二个三角形
        };

        //生成VAO、VBO、EBO对象
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);
        // 1. 绑定顶点数组对象
        glBindVertexArray(VAO);
        // 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        // 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        // 4. 设定顶点属性指针
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // 5. 设定顶点颜色属性指针
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
        //glEnableVertexAttribArray(1);
        // 6.创建一个程序对象
        glUseProgram(shaderProgram);

        // 创建ImGui
        glfwPollEvents();
        ImGui_ImplGlfwGL3_NewFrame();
        ImGui::Begin("Edit color", &ImGui, ImGuiWindowFlags_MenuBar);

        ImGui::ColorEdit3("Basic triangle -- top color", (float*)&top_color);
        ImGui::ColorEdit3("Basic triangle -- left color", (float*)&left_color);
        ImGui::ColorEdit3("Basic triangle -- right color", (float*)&right_color);
        ImGui::ColorEdit3("Bonus triangle -- bottom color", (float*)&bottom_color);
        ImGui::ColorEdit3("Optional -- the same color", (float*)&same_color);

        ImGui::Checkbox("the same color", &the_same_color);
        ImGui::Checkbox("Draw triangle without rendering", &draw_trangle_without_render);
        ImGui::Checkbox("Basic draw triangle", &draw_trangle);
        ImGui::Checkbox("Bonus draw line", &bonus_draw_line);
        ImGui::Checkbox("Bonus draw another triangle", &bonus_draw_another_trangle);
        ImGui::End();

        // 渲染窗口颜色
        int view_width, view_height;
        glfwGetFramebufferSize(window, &view_width, &view_height);
        glViewport(0, 0, view_width, view_height);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui::Render();
        ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());

        //画Basic 三角形,没有加入渲染
        if (draw_trangle_without_render) {
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }

        // 渲染Basic 三角形
        if (draw_trangle) {
            glEnableVertexAttribArray(1);
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }

        // 渲染Bonus 线段
        if (bonus_draw_line) {
            glEnableVertexAttribArray(1);
            glBindVertexArray(VAO);
            glDrawArrays(GL_LINE_STRIP, 0, 2);
        }

        // 渲染Bonus 三角形
        if (bonus_draw_another_trangle) {
            glEnableVertexAttribArray(1);
            glBindVertexArray(VAO);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            glBindVertexArray(0);
        }

        // 双缓冲。前缓冲保存着最终输出的图像,它会在屏幕上显示;而所有的的渲染指令都会在后缓冲上绘制。
        glfwSwapBuffers(window);
    }

    // 释放VAO、VBO、EBO资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);

    // 释放ImGui资源
    ImGui_ImplGlfwGL3_Shutdown();
    ImGui::DestroyContext();

    // 清除所有申请的glfw资源
    glfwTerminate();
    return 0;
}

void window_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

你可能感兴趣的:(OpenGL)