opengl - 你好,三角形

发表时间: 2018-11-12作者: 何景松 0 9

    概念介绍

    1. 顶点数组对象:Vertex Array ObjectVAO

    对顶点属性的管理和配置,只要绑定不同的VAO就可以快速的切换不同顶点数据和属性配置。

    2. 顶点缓冲对象:Vertex Buffer ObjectVBO

    存储顶点数据,可以将数据一次性发送到GPU上进行运算。

    3. 索引缓冲对象:Element Buffer ObjectEBO

    保存绘制数据的索引下标,让内存保存更少的数据。

     

    图形渲染管线

    介绍

    3D坐标转变成屏幕有色的2D输出。

    流程

     

    相关代码

    #include <windows.h>
    #include "common.h"
    
    
    static const float frame = 60;
    static const float pre_frame_second = 1.0f / frame;
    static const long pre_frame_ms = 1000 / frame;
    
    
    void on_window_change_size(GLFWwindow *win, int width, int height) {
        
    }
    
    void on_press_key(GLFWwindow* win, int key, int scancode, int action, int mode) {
        if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
            glfwSetWindowShouldClose(win, 1);
        }
    }
    
    
    class CTriangle {
    public:
        CTriangle(const float *vertexs, int size) {
            int ret;
            this->vertex_size = size * sizeof(float);
            this->m_vertexs = new float[this->vertex_size];
            assert(this->m_vertexs != NULL);
            memcpy(this->m_vertexs, vertexs, this->vertex_size);
            this->m_rotate[0] = 90;
            this->m_rotate[1] = 225;
            this->m_rotate[2] = 315;
            ret = this->_Create();
            assert(ret == 0);
        }
    
        ~CTriangle() {
            delete[] this->m_vertexs;
        }
    
        void MoveBy(float sec, float x, float y, float z = 0) {
            this->m_targetPosX = this->m_curPosX + x;
            this->m_targetPosY = this->m_curPosY + y;
            this->m_targetPosZ = this->m_curPosZ + z;
            this->m_befPosX = this->m_curPosX;
            this->m_befPosY = this->m_curPosY;
            this->m_befPosZ = this->m_curPosZ;
            this->m_moveSec = sec;
        }
    
        void RotateBy(float sec, float rotate) {
            this->m_targetRotate = this->m_curRotate + rotate;
            this->m_befRotate = this->m_curRotate;
            this->m_rotateSec = sec;
        }
    
        void Update() {
            glUseProgram(this->m_shader_program);
            glBindVertexArray(this->m_VAO);
            this->_UpdateMove();
            this->_UpdateRotate();
            glBufferData(GL_ARRAY_BUFFER, this->vertex_size, this->m_vertexs, GL_DYNAMIC_DRAW);
            glDrawArrays(GL_TRIANGLES, 0, 3);
        }
    
        void Update2() {
            glUseProgram(this->m_shader_program);
            glBindVertexArray(this->m_VAO);
            this->_UpdateMove();
            this->_UpdateRotate();
            glBufferData(GL_ARRAY_BUFFER, this->vertex_size, this->m_vertexs, GL_DYNAMIC_DRAW);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            glBindVertexArray(0);
        }
    
    private:
        int _Create() {
            int ret = 0;
            char log_buff[512] = { 0 };
    
            this->m_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(this->m_vertex_shader, 1, &this->m_svertex_shader, NULL);
            glCompileShader(this->m_vertex_shader);
            glGetShaderiv(this->m_vertex_shader, GL_COMPILE_STATUS, &ret);
            if (!ret) {
                glGetShaderInfoLog(this->m_vertex_shader, sizeof(log_buff), NULL, log_buff);
                std::cout << log_buff << std::endl;
                return -1;
            }
    
            this->m_frament_shader = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(this->m_frament_shader, 1, &this->m_sframent_shader, NULL);
            glCompileShader(this->m_frament_shader);
            glGetShaderiv(this->m_frament_shader, GL_COMPILE_STATUS, &ret);
            if (!ret) {
                glGetShaderInfoLog(this->m_frament_shader, sizeof(log_buff), NULL, log_buff);
                std::cout << log_buff << std::endl;
                return -1;
            }
    
            this->m_shader_program = glCreateProgram();
            glAttachShader(this->m_shader_program, this->m_vertex_shader);
            glAttachShader(this->m_shader_program, this->m_frament_shader);
            glLinkProgram(this->m_shader_program);
            glGetProgramiv(this->m_shader_program, GL_LINK_STATUS, &ret);
            if (!ret) {
                glGetProgramInfoLog(this->m_shader_program, sizeof(log_buff), NULL, log_buff);
                std::cout << log_buff << std::endl;
                return -1;
            }
    
            glDeleteShader(this->m_vertex_shader);
            glDeleteShader(this->m_frament_shader);
    
            glGenBuffers(1, &this->m_VBO);
            glGenVertexArrays(1, &this->m_VAO);
            glBindBuffer(GL_ARRAY_BUFFER, this->m_VBO);
            glBindVertexArray(this->m_VAO);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), NULL);
            glEnableVertexAttribArray(0);
            return 0;
        }
    
        void _UpdateMove() {
            if (abs(this->m_curPosX - this->m_targetPosX) > 0.001) {
                float diff = this->m_targetPosX - this->m_befPosX;
                float step = diff / frame * this->m_moveSec;
                this->m_curPosX += step;
                this->m_vertexs[0] += step;
                this->m_vertexs[3] += step;
                this->m_vertexs[6] += step;
            }
            else {
                this->m_targetPosX = this->m_curPosX;
            }
    
            if (abs(this->m_curPosY - this->m_targetPosY) > 0.001) {
                float diff = this->m_targetPosY - this->m_befPosY;
                float step = diff / frame * this->m_moveSec;
                this->m_curPosY += step;
                this->m_vertexs[1] += step;
                this->m_vertexs[4] += step;
                this->m_vertexs[7] += step;
            }
            else {
                this->m_targetPosY = this->m_curPosY;
            }
    
            if (abs(this->m_curPosZ - this->m_targetPosZ) > 0.001) {
                float diff = this->m_targetPosZ - this->m_befPosZ;
                float step = diff / frame * this->m_moveSec;
                this->m_curPosZ += step;
                this->m_vertexs[2] += step;
                this->m_vertexs[5] += step;
                this->m_vertexs[8] += step;
            }
            else {
                this->m_targetPosZ = this->m_curPosZ;
            }
        }
    
        void _UpdateRotate() {
            if (abs(this->m_targetRotate - this->m_curRotate) > 0.001) {
                float diff = this->m_targetRotate - this->m_befRotate;
                float step = diff / frame * this->m_rotateSec;
                this->m_curRotate += step;
                this->m_rotate[0] += step;
                this->m_rotate[1] += step;
                this->m_rotate[2] += step;
                this->m_vertexs[0] = 0.5 * cos(3.14159 * this->m_rotate[0] / 180);
                this->m_vertexs[1] = 0.5 * sin(3.14159 * this->m_rotate[0] / 180);
                this->m_vertexs[3] = 0.5 * cos(3.14159 * this->m_rotate[1] / 180);
                this->m_vertexs[4] = 0.5 * sin(3.14159 * this->m_rotate[1] / 180);
                this->m_vertexs[6] = 0.5 * cos(3.14159 * this->m_rotate[2] / 180);
                this->m_vertexs[7] = 0.5 * sin(3.14159 * this->m_rotate[2] / 180);
            }
            else {
                this->m_curRotate = int(this->m_curRotate) % 360;
                this->m_targetRotate = this->m_curRotate;
                this->m_rotate[0] = int(this->m_rotate) % 360;
                this->m_rotate[1] = int(this->m_rotate) % 360;
                this->m_rotate[2] = int(this->m_rotate) % 360;
            }
        }
    
    private:
        float *m_vertexs;
        float m_targetPosX, m_targetPosY, m_targetPosZ;
        float m_targetRotate;
        float m_curPosX, m_curPosY, m_curPosZ;
        float m_befPosX, m_befPosY, m_befPosZ;
        float m_curRotate, m_befRotate;
        float m_moveSec, m_rotateSec;
        float m_rotate[3];
        int vertex_size;
        const char* m_svertex_shader = "#version 330 core\nlayout (location = 0) in vec3 aPos;\nvoid main() {\ngl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n}";
        const char* m_sframent_shader = "#version 330 core\nout vec4 FragColor;\nvoid main() {\nFragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n}";
        unsigned int m_VBO, m_VAO;
        unsigned int m_vertex_shader, m_frament_shader, m_shader_program;
    };
    
    int main(const int argc, const char* argv[]) {
        DWORD start, end, run_time;
        long fix;
        const float vertexs[] = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f
        };
        const float vertexs2[] = {
            0.5f, 0.5f, 0.0f,   // 右上角
            0.5f, -0.5f, 0.0f,  // 右下角
            -0.5f, -0.5f, 0.0f, // 左下角
            -0.5f, 0.5f, 0.0f   // 左上角
        };
        const unsigned int indices[] = {
            0, 1, 3, // 第一个三角形
            1, 2, 3  // 第二个三角形
        };
    
        GLFWwindow *win = init_window();
        if (NULL == win) {
            return -1;
        }
        set_key_callback(win, on_press_key);
        set_changesize_callback(win, on_window_change_size);
        set_windows_size(800, 600);
    
        //CTriangle1 triangle(vertexs2, sizeof(vertexs2) / sizeof(vertexs2[0]),
         //   indices, sizeof(indices) / sizeof(indices[0]));
        CTriangle triangle(vertexs, sizeof(vertexs) / sizeof(vertexs[0]));
        triangle.MoveBy(1.0, 0.5, 0.5);
    
        while (!glfwWindowShouldClose(win)) {
            start = GetTickCount();
            glfwPollEvents();
    
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            triangle.Update();
    
            glfwSwapBuffers(win);
            end = GetTickCount();
    
            run_time = end - start;
            fix = run_time - pre_frame_ms;
            if (fix < 0) {
                Sleep(-fix);
            }
        }
    
    
        return 0;
    }