美文网首页
LearnOpenGL 完整画一个三角形or正方形

LearnOpenGL 完整画一个三角形or正方形

作者: li_礼光 | 来源:发表于2020-09-15 00:48 被阅读0次

    实现流程
    1.创建一个基本的窗口.
    2.利用用C++封装的Program和Shader
    3.简单创建自己需要的顶点数据和索引数据
    4.调用对应的绘制方法. glDrawArrays 或者 glDrawElements

    #include "MyOpenglWindow.hpp"
    #include <iostream>
    #include <glad/glad.h>
    #include <GLFW/glfw3.h>
    
    #include "MyShader.hpp"
    #include "MyProgram.hpp"
    
    #define STRINGIZE(x) #x
    #define SHADER(shader) STRINGIZE(shader)
    
    
    // 模拟顶点数据
    //三角形
    GLfloat triangleVertices[] = {
        -0.5f, -0.5f, 0.0f,  //左下
         0.5f, -0.5f, 0.0f,  //右下
         0.0f,  0.5f, 0.0f,   //中上
    };
      
    
    //正方形
    GLfloat squareVertices[] = {
        -0.5f, -0.5f, 0.0f,  //左下
         0.5f, -0.5f, 0.0f,  //右下
         0.5f,  0.5f, 0.0f,   //右上
        -0.5f,  0.5f, 0.0f,   //左上
    };
      
      
    unsigned int  squareIndices[] = { // 注意索引从0开始!
        0, 1, 2, // 第一个三角形
        0, 3, 2  // 第二个三角形
    };
    
    
    //顶点着色器程序
    char *vertexShaderStr = SHADER(
        \#version 330 core\n
                                   layout (location = 0) in vec3 position;
                                   void main()
                                   {
        gl_Position = vec4(position.x, position.y, position.z, 1.0);
        }
    );
    
    //片元着色器程序
    char *fragmentShaderSrc = SHADER(
                \#version 330 core\n
                                     out vec4 color;
                                     void main()
                                     {
        color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
        }
    );
    
    
    
    bool showTriangle = false;
    
    
    int runMyOpenGlWindow() {
            
        int result = glfwInit();
        if (result == GL_FALSE) {
            printf("glfwInit 初始化失败");
            return -1;
        }
        
        //这里的宏不好提示出来, 根据LearnOpenGL的文档提示, 用这三个
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //Mac平台需要加入
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    
        //创建一个Window
        GLFWwindow *window = glfwCreateWindow(600, 400, "My Opengl Window", NULL, NULL);
        if(!window) {
            printf("window 创建失败");
    
        }
        
        //opengl运行模式 -- 单线程, 理解为跟当前的Window做一次绑定操作.
        glfwMakeContextCurrent(window);
        
        //任何的OpenGL接口调用都必须在初始化GLAD库后才可以正常访问。如果成功的话,该接口将返回GL_TRUE,否则就会返回GL_FALSE。
        gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
        
        
        
        
         //----------------------------------------------------------------------
        //先创建我们的Program对象, 加载顶点着色器程序和片元着色器程序
        MyProgram myProgram = MyProgram(vertexShaderStr, fragmentShaderSrc);
    
        GLuint VBO , VAO , EBO;
        unsigned int squareIndicesCount = 0;
        showTriangle = false;
        if (showTriangle) {
            //创建VBO
            glGenBuffers(1, &VBO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
    
           
           //创建VAO
            glGenVertexArrays(1, &VAO);
            glBindVertexArray(VAO);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
            glEnableVertexAttribArray(0);
            //解绑VAO
            glBindVertexArray(0);
            
            
        } else {
            //创建VBO
            glGenBuffers(1, &VBO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertices), squareVertices, GL_STATIC_DRAW);
    
            
            //创建VAO
            glGenVertexArrays(1, &VAO);
            glBindVertexArray(VAO);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
            glEnableVertexAttribArray(0);
            
            //创建EBO, 这里的EBO相当于索引的作用
            glGenBuffers(1, &EBO);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(squareIndices), squareIndices, GL_STATIC_DRAW);
    
            //解绑VAO
            glBindVertexArray(0);
            //计算索引个数
            squareIndicesCount = sizeof(squareIndices)/sizeof(squareIndices[0]);
            
        }
        
       
        
        
        //在glUseProgram函数调用之后,每个着色器调用和渲染调用都会使用这个程序对象(也就是之前写的着色器)了。
        glUseProgram(myProgram.program);
        //线框模式
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        //----------------------------------------------------------------------
     
    
    
        
        //进行绘制
        while(!glfwWindowShouldClose(window)){
           //检查事件
            glfwPollEvents();
            
            //渲染指令
            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            //这里VAO也行, VBO也行
            glBindVertexArray(VAO);
            
            if (showTriangle) {
                glDrawArrays(GL_TRIANGLES, 0, 3);
                
            } else {
                //使用EBO
                glDrawElements(GL_TRIANGLES, squareIndicesCount, GL_UNSIGNED_INT, 0);
                
                //不使用EBO
    //            glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
                /*
                v参数1:有三种取值
                1.GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接
                2.GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形
                3.GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。
                 这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形
                */
            }
            
            //解绑VAO
            glBindVertexArray(0);
            
            //交换缓冲
            glfwSwapBuffers(window);
        }
        //程序销毁
        glfwTerminate();
        
        return 1;
    }
    

    在main.cpp中执行

    int main(int argc, const char * argv[]) {
        return runMyOpenGlWindow();
    }
    



    注意点 :
    1.创建了一个SHADER宏 , 里面写的内容直接会转为字符串.

    1. 顶点着色器程序vertexShaderStr 和片元着色器程序fragmentShaderSrc暂时不用管它是什么一回事, 假装默认就是这样. 还需要研究Shader编程.

    3.理解绘制的流程, 绘制的方法.

    4.理解VAO,VBO,EBO的buffer绑定方式,怎么(调用什么函数)把数据拷贝到缓冲区中

    5.整个流程理解了, 开始研究Shader, 着色器语言.

    6.后续实现 : 通过研究Shader,实现一个渐变的正方形




    效果图 :


    正方形

    相关文章

      网友评论

          本文标题:LearnOpenGL 完整画一个三角形or正方形

          本文链接:https://www.haomeiwen.com/subject/wazmektx.html