zoukankan      html  css  js  c++  java
  • -OPENGL7 Geometry & Instance-

    CP24: GeometryShader

    一开始首先要认识到什么是最基础的图元:点,线,三角面

    教程中的一开始初始化的点是在NDC设备,我的同样一样,在shader中,教程中vert 不包含projection * view *model,我的依然存在。

    如果在Geometry绘制的线段依然要满足透视关系,所以也得把projection * view * model带入

    在这里修改了LoaderShader.h

    #ifndef LOADSHADER_H
    #define LOADSHADER_H
    
    
    #include <GL/glew.h>
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <vector>
    #include "ALG_TextureDelegate.h"
    
    namespace AlgebraMaster
    {
    
    using namespace std;
    // Shaders
    
    const char* vertexShaderSource = "#version 450 core
    "
                                     "layout (location = 0) in vec4 v_position;
    "
                                     "layout ( location = 1 ) in vec3 v_normal;
    "
                                     "layout ( location = 2 ) in vec2 v_texCoord;
    "
                                     "out vec2 myTexCoord;
    "
                                     "uniform mat4 model;
    "
                                     "uniform mat4 view;
    "
                                     "uniform mat4 projection;
    "
                                     "void main()
    "
                                     "{
    "
                                     "gl_Position = projection *   view * model * v_position;
    "
                                     "myTexCoord = v_texCoord;
    "
                                     "}";
    
    
    
    const char* fragmentShaderSource = "#version 450 core
    "
                                       "out vec4 fColor;
    "
                                       "void main()
    "
                                       "{
    "
                                       "fColor = vec4(1.0f, 1.0f, 1.0f , 1.0f);
    "
                                       "}
    ";
    
    // this have texture
    const char* fragmentShaderSource2 = "#version 450 core
    "
                                        "out vec4 fColor;
    "
                                        "in vec2 myTexCoord;
    "
                                        "struct Material
    "
                                        "{
    "
                                        "float Kd;        // diffuse mult
    "
                                        "float kS;        // specular mult
    "
                                        "float shininess; // phong pow(,shine)
    "
                                        "sampler2D diffuse_map;
    "
                                        "sampler2D specular_map;
    "
                                        "sampler2D emission_map;
    "
                                        "};
    "
                                        "uniform Material material;
    "
                                        "void main()
    "
                                        "{
    "
                                        "vec4 df_tex=texture(material.diffuse_map, myTexCoord);
    ;"
                                        "fColor = vec4(df_tex.r,df_tex.g,df_tex.b,1.0f) ;
    "
                                        "}
    ";
    
    struct LoadShader
    {
        enum ShaderIOType{FILE,INLINE_DEFAULT_PROJECTION,INLINE_TEXTURE_PROJECTION};
        void compileShaderProgram(bool needGeometryShader = false){
            // create shader program and check it
            GLint success;
            GLchar infoLog[512];
            shaderProgram = glCreateProgram();
            glAttachShader(shaderProgram,vertexShader);
            glAttachShader(shaderProgram,fragmentShader);
            // if we need attach geometry shader
            if (needGeometryShader){
                glAttachShader(shaderProgram,geometryShader);
            }
            glLinkProgram(shaderProgram );
            glGetProgramiv( shaderProgram, GL_LINK_STATUS, &success );  // Get Link Status
            if (!success)
            {
                glGetProgramInfoLog( shaderProgram, 512, NULL, infoLog );
                std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
    " << infoLog << std::endl;
            }
            // Delete the allShaders as they're linked into our program now and no longer necessery
            glDeleteShader( vertexShader );
            glDeleteShader( fragmentShader );
        }
        void compileVertexShader(const string& code){
            vertexShader = glCreateShader( GL_VERTEX_SHADER );
    
            const char * src = code.c_str();
            glShaderSource( vertexShader, 1, &(src), 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
    " << infoLog << std::endl;
            }
        }
        void compileGeometryShader(const string& code){
            const char *src = code.c_str();
            GLint success;
            GLchar infoLog[512];
            geometryShader = glCreateShader( GL_GEOMETRY_SHADER );
            glShaderSource( geometryShader, 1, &src, NULL );
            glCompileShader( geometryShader );
            glGetShaderiv( geometryShader, GL_COMPILE_STATUS, &success ); // Get Compile status
            if ( !success )
            {
                glGetShaderInfoLog( geometryShader, 512, NULL, infoLog );
                std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
    " << infoLog << std::endl;
            }
        }
        void compileFragmentShader(const string& code){
            const char * src = code.c_str();
            GLint success;
            GLchar infoLog[512];
            fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
            glShaderSource( fragmentShader, 1, &src, NULL );
            glCompileShader( fragmentShader );
            glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &success ); // Get Compile status
            if ( !success )
            {
                glGetShaderInfoLog( fragmentShader, 512, NULL, infoLog );
                std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
    " << infoLog << std::endl;
            }
        }
    
        void fromSrc(const string &vertCode, const string &fragCode){
            compileVertexShader(vertCode);
            compileFragmentShader(fragCode);
            compileShaderProgram();
        }
        void fromSrc(const string &vertCode, const string &fragCode, const string&geometryCode){
            compileVertexShader(vertCode);
            compileFragmentShader(fragCode);
            compileGeometryShader(geometryCode);
            compileShaderProgram(true);
        }
    
    
        LoadShader(){
    
        }
        ~LoadShader(){
    
        }
    
        // ------------ this method do not compile the geometry shader -----------------------
        void asSimpleTextureShader(){
            shaderName = "simpleTex";
            shaderIOType = INLINE_TEXTURE_PROJECTION;
            compileVertexShader(vertexShaderSource);
            compileFragmentShader(fragmentShaderSource2);
            compileShaderProgram();
        }
        void asSimpleShader()
        {
            shaderName = "simpleCol";
            shaderIOType = INLINE_DEFAULT_PROJECTION;
            compileVertexShader(vertexShaderSource);
            compileFragmentShader(fragmentShaderSource);
            compileShaderProgram();
        }
        // ------------ this method do not compile the geometry shader -----------------------
    
    
        void setShaderName(const string &name){
            shaderName = name;
        }
    
    
        // ------------ read text file -----------------------
        string _readFile(const char *path){
            ifstream stream;
            stringstream ss;
            stream.exceptions(ifstream::badbit);
            try
            {
                stream.open(path);    // open file
                ss << stream.rdbuf(); // get strings from file
            } catch (ifstream::failure e)
            {
                cout << "ERROR::OPEN FILE:" << path << endl;
            }
            // close file handle
            stream.close();
    
            // get str() from stringstream
            string shaderCode = ss.str();
            return shaderCode;
        }
    
        // ------------ load a vertex shader from a path ----------------------------------
        void _loadVertexShader(const char *path){
            // read shader code
            auto handle = _readFile(path);
            compileVertexShader(handle);
        }
    
        // ------------ load a fragment shader from a path ----------------------------------
        void _loadFragmentShader(const char *path){
            // read shader code
            auto handle = _readFile(path);
            compileFragmentShader(handle);
        }
    
        // ------------ load a geometry shader from a path ----------------------------------
        void _loadGeometryShader(const char *path){
            auto handle = _readFile(path);
            compileGeometryShader(handle);
        }
    
        // ------------ only load two shader : vert & frag ----------------------------------
        void load(const char* vertShaderPath, const char* fragShaderPath){
            shaderIOType = FILE;
            _loadVertexShader(vertShaderPath);
            _loadFragmentShader(fragShaderPath);
            // create shader program and check it
            compileShaderProgram();
        }
        // ------------ shader program have 3 shader: vert&frag&geometry ----------------------------------
        void load(const char* vertShaderPath, const char* fragShaderPath, const char* geometryShaderPath){
            shaderIOType = FILE;
            _loadVertexShader(vertShaderPath);
            _loadFragmentShader(fragShaderPath);
            _loadGeometryShader(geometryShaderPath);
            // create shader program and check it
            compileShaderProgram(true);
        }
    
        // ------------ active current shader program ----------------------------------
        void use(){
            glUseProgram(shaderProgram);
        }
    
    
        // ------------ set shader method ----------------------------------
        void setBool(const char *name, bool value) const
        {
            glUniform1i(glGetUniformLocation(shaderProgram, name), (int)value);
        }
        void setInt(const char *name, int value) const
        {
            glUniform1i(glGetUniformLocation(shaderProgram,name), value);
        }
        // ------------------------------------------------------------------------
        void setFloat(const char *name, float value) const
        {
            glUniform1f(glGetUniformLocation(shaderProgram, name), value);
        }
        // ------------------------------------------------------------------------
        void setVec2(const char *name, const glm::vec2 &value) const
        {
            glUniform2fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
        }
    
        void setVec2(const char *name, float x, float y) const
        {
            glUniform2f(glGetUniformLocation(shaderProgram,name), x, y);
        }
        // ------------------------------------------------------------------------
        void setVec3(const char *name, const glm::vec3 &value) const
        {
            glUniform3fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
        }
        void setVec3(const char *name, float x, float y, float z) const
        {
            glUniform3f(glGetUniformLocation(shaderProgram,name), x, y, z);
        }
        // ------------------------------------------------------------------------
        void setVec4(const char *name, const glm::vec4 &value) const
        {
            glUniform4fv(glGetUniformLocation(shaderProgram,name), 1, &value[0]);
        }
        void setVec4(const char *name, float x, float y, float z, float w)
        {
            glUniform4f(glGetUniformLocation(shaderProgram,name), x, y, z, w);
        }
    
        void setMat2(const char*name, const glm::mat2 &mat) const
        {
            glUniformMatrix2fv(glGetUniformLocation(shaderProgram, name), 1, GL_FALSE,glm::value_ptr(mat));
        }
    
        void setMat3(const char*name, const glm::mat3 &mat){
            GLuint location = glGetUniformLocation(shaderProgram, name);
            glUniformMatrix3fv(location,1, GL_FALSE, &mat[0][0]);
        }
    
        void setMat4(const char *name , const glm::mat4 &mat){
            GLuint location = glGetUniformLocation(shaderProgram, name);
            glUniformMatrix4fv(location,1, GL_FALSE, glm::value_ptr(mat));
        }
    
        GLuint shaderProgram;
        GLuint vertexShader;
        GLuint fragmentShader;
        GLuint geometryShader;
        ShaderIOType shaderIOType;
        string shaderName;
        vector <Texture*> textures;   // do not release this memory, scene will manipulate this mem
    
        glm::mat4 model;
        glm::mat4 view;
        glm::mat4 projection;
    
        // ------------ direct set shader projection,view,model ----------------------------------
        void setMatrix(const glm::mat4 &matModel , const glm::mat4 &matView , const glm::mat4 &matProjection){
            model = matModel;
            view = matView;
            projection = matProjection;
    
            setMat4("projection", projection);
            setMat4("view", view);
            setMat4("model", model);
        }
    };
    
    }
    
    
    #endif // LOADSHADER_H
    View Code

    集合体shader->GeometryShader.geom:

        >下面的layout(points) in; 意思很重要,基础图元,代表输入的是点,那么在下面访问的时候只能gl_in[0],因为操作一个点相当于操作C++里的VAO,也类似houdini attribute wrangle(points)。

         >顺理推如果layout(triangles)in; 就是我输入的是三角形,那么可以访问下面3个顶点也就是三角形的三个顶点。

             gl_in[0].position

             gl_in[1].position

             gl_In[2].position

         >同样接下来 layout (line_strip, max_verticles = 2) out; 这句话代表我要干什么,我要输出什么样的图像,这里是一条线,我要生成2个点。

    #version 450 core
    layout (points) in;
    layout (line_strip, max_vertices = 2) out;
    
    
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    void main() {
        gl_Position = gl_in[0].gl_Position + projection*view*model*vec4(-.2, 0.0, 0.0, 0.0);
        EmitVertex();
    
        gl_Position = gl_in[0].gl_Position + projection*view*model*vec4( 0.2, 0.0, 0.0, 0.0);
        EmitVertex();
    
        EndPrimitive();
    }
    #version 450 core
    // Final Color To export
    out vec4 FragColor;
    
    void main()
    {
    
        FragColor =  vec4(1,0,1,1);
    }
    SurfaceShader.frag
    #version 450 core
    // INCOMING DATA
    layout ( location = 0 ) in vec4 v_position; //  pos
    //layout ( location = 1 ) in vec2 v_texCoord; //  st
    //layout ( location = 2 ) in vec3 v_normal; //  st
    
    // define out data
    out vec2 f_TexCoord;
    // normal at world matrix, we direct from C++ calcalation
    out vec3 f_Normal;  // to world matrix : mat3( transpose(inverse(model)) ) * v_normal;
    out vec3 f_Pos;
    
    
    // INCOMING THE MATRIX FROM CLIENT to transform the gl point position
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    
    
    
    void main(){
        // Transform the world matrix to view matrix
    
        //f_Normal = mat3(transpose(inverse(model))) * v_normal;  // f_Normal at world matrix
        //f_TexCoord = v_texCoord;          // out TexCoord
        //f_Pos = vec3(model *v_position);  // out fragment position
    
        gl_Position = projection *   view * model * v_position;
    
    }
    SurfaceShader.vert
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <cstdlib>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include "ALG_LoadShader.h"
    #include "ALG_LoadTexture.h"
    #include "ALG_GLFWCamera.h"
    #include "ALG_FrameWindow.h"
    #include "ALG_ModelDelegate.h"
    #include "ALG_SceneDelegate.h"
    #include "ALG_DrawGrid.h"
    #include <cmath>
    #include "ALG_OGLHelper.h"
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <map>
    #include "ALG_DrawEnvBox.h"
    
    using namespace AlgebraMaster;
    
    
    const unsigned int SRC_WIDTH = 1400;
    const unsigned int SRC_HEIGHT = 720;
    
    
    
    static LoadShader SurfaceShader;
    
    void init();
    void display();
    
    
    void processInput(GLFWwindow *window);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
    void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);
    
    
    
    static float lastX =  float(SRC_WIDTH) / 2.0f;
    static float lastY =  float(SRC_HEIGHT) / 2.0f;
    static bool firstMouse = true;
    static bool firstMiddowMouse = true;
    // timing
    static float deltaTime = 0.0f;    // time between current frame and last frame
    static float lastFrame = 0.0f;
    
    
    
    
    // cube vao vbo
    static unsigned int VAO,VBO;
    
    // camera
    static GLFWCamera *camera;
    // light define
    static glm::vec3 lightPos(0.0f, 4.0f,-2.0f);
    
    static DrawGrid grid;
    static DrawEnvBox envBox;
    
    static LoadTexture cubeTex;
    static LoadTexture groundTex;
    
    
    static float testPoints[] = {
            -0.5f,  0.5f, // 左上
            0.5f,  0.5f, // 右上
            0.5f, -0.5f, // 右下
            -0.5f, -0.5f  // 左下
    };
    
    void init(){
        camera = new GLFWCamera;
        camera->pos.y = 1.0f;
        camera->pos.z = 4.0f;
        // GL depth zbuffer
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        SurfaceShader.load(
                "shaders/SurfaceShader.vert",
                "shaders/SurfaceShader.frag",
                "shaders/GeometryShader.geom");
    
        CreateGeometryBuffer(VAO,VBO);
        glBufferData(GL_ARRAY_BUFFER,sizeof(testPoints),&testPoints,GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
    
    
        grid.initialize();
    
    }
    
    // ----------- Render Loop ----------
    void display(){
    
    
        // per-frame time logic
                // --------------------
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
    
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    
    
    
        // object .vert settings
        glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f,  1000.0f);
        glm::mat4 view = camera->GetViewMatrix();
        // object world transformation
        glm::mat4 model = glm::mat4(1.0f);
        grid.draw(projection,view);
    
    
    
    
        SurfaceShader.use();
        SurfaceShader.setMatrix(model,view,projection);
    
        glBindVertexArray(VAO);
        glDrawArrays(GL_POINTS,0,4);
    
    }
    
    
    int main()
    {
        cout << sizeof(float) << endl;
        glfwInit();
        FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
        glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
        glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
        glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);
        init();
        // RENDER--------------
        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        while(!glfwWindowShouldClose(FrameWindow.getWindow())){
            processInput(FrameWindow.getWindow());
            display();
            glfwSwapBuffers(FrameWindow.getWindow());
            glfwPollEvents();
        }
        delete camera;
        return 0;
    }
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        // make sure the viewport matches the new window dimensions; note that width and
        // height will be significantly larger than specified on retina displays.
        glViewport(0, 0, width, height);
    }
    
    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
    }
    
    // ROTATE VIEW DIR
    void mouse_callback(GLFWwindow* window, double xpos, double ypos){
    
        int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE);
        int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
        int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
        // set up the camera view
        if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
        {
            if (firstMouse){
                lastX = xpos;
                lastY = ypos;
                firstMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->processMouseMove(xoffset,yoffset);
        }
        if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
            firstMouse = true;
        }
    
    
        // Move Camera Position
        if( middow_mouse_state == GLFW_PRESS) {
    
            if (firstMiddowMouse){
                lastX = xpos;
                lastY = ypos;
                firstMiddowMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->pos.x += xoffset*0.01f;
            camera->pos.y += yoffset*0.01f;
    
        }
        if ( middow_mouse_state == GLFW_RELEASE){
            firstMiddowMouse = true;
        }
    
    }
    
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
        camera->processFov(yoffset);
    }
    main.cpp

    法线向量显示:

    首先在vert阶段材质输出法线向量:

    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;
    
    out VS_OUT {
        vec3 normal;
    } vs_out;
    
    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 model;
    
    void main()
    {
        gl_Position = projection * view * model * vec4(aPos, 1.0); 
        mat3 normalMatrix = mat3(transpose(inverse(view * model)));
        vs_out.normal = normalize(vec3(projection * vec4(normalMatrix * aNormal, 0.0)));
    }

    然后在geometry阶段材质,注意接入是三角形,也就是可以访问三角形三个点。一个点要生成1跟线,1根线2个点, 则3个点需要3根线,6个点。

    不过作者这个是做的点法线,按道理做个面法线不是个困难的事情。

    #version 330 core
    layout (triangles) in;
    layout (line_strip, max_vertices = 6) out;
    
    in VS_OUT {
        vec3 normal;
    } gs_in[];
    
    const float MAGNITUDE = 0.4;
    
    void GenerateLine(int index)
    {
        gl_Position = gl_in[index].gl_Position;
        EmitVertex();
        gl_Position = gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * MAGNITUDE;
        EmitVertex();
        EndPrimitive();
    }
    
    void main()
    {
        GenerateLine(0); // point 1-> normal line
        GenerateLine(1); // point 2-> normal line
        GenerateLine(2); // point 3-> normal line
    }

    引用原图:

    CP25:利用Opengl Geometry Shader绘制坐标轴:

    当然有多种绘制方法,选择用这个主要练习。

    输入图元一个点,然后用这个点绘制3条线,即输出图元。最大点6个。

     包装成一个最简单的头文件。

    //
    // Created by Admin on 2020/3/5.
    //
    
    #ifndef TRIANGLE_ALG_DRAWORIGINGNOMON_H
    #define TRIANGLE_ALG_DRAWORIGINGNOMON_H
    
    #include <vector>
    #include "ALG_LoadShader.h"
    #include "ALG_OGLHelper.h"
    
    namespace AlgebraMaster
    {
        using namespace std;
        static float __originPt__[] = {0.0f,0.0f,0.0f};
    
    
        class DrawOriginGnomon{
        public:
    
            void initialize();
            void draw(glm::mat4 &proj, glm::mat4 &view);
    
            LoadShader shader;
            unsigned int VAO;
            unsigned int VBO;
    
    
        };
    
        void DrawOriginGnomon::initialize() {
            CreateGeometryBuffer(VAO,VBO);
            glBufferData(GL_ARRAY_BUFFER,sizeof(__originPt__),&__originPt__, GL_STATIC_DRAW);
            glEnableVertexAttribArray(0);
            glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE, 3 * sizeof(float), (void*)0 );
    
            shader.load("shaders/origin_gnomon/surface.vert",
                    "shaders/origin_gnomon/surface.frag",
                    "shaders/origin_gnomon/surface.geom");
    
        }
    
        void DrawOriginGnomon::draw(glm::mat4 &proj, glm::mat4 &view) {
            shader.use();
            shader.setMatrix(glm::mat4(1.0f),view,proj);
            glLineWidth(4.0f);
            glBindVertexArray(VAO);
            glDrawArrays(GL_POINTS,0,1);
        }
    
    
    }
    
    
    
    
    #endif //TRIANGLE_ALG_DRAWORIGINGNOMON_H
    ALG_DrawOriginGnomon.h

    由于shader stage: vert->geometry->fragment

    我想测试从geometry shader直接生成3中颜色,传递到fragment

    还有我想把projection*view*model从vert里面传递到geometry里(当然直接可以把这种uniform变量写到geometry shader),有两种方式传递:

    首先是vert材质:

    #version 450 core
    layout(location=0) in vec3 aPos;
    
    uniform mat4 projection;
    uniform mat4 view;
    uniform mat4 model;
    
    out mat4 testMat;
    
    out VS_OUT{
        mat4 toCameraMat;
    }vs_out;
    
    
    void main(){
        mat4 pipematrix =  projection * view * model;
    
        testMat = pipematrix; // only for test can transfer to geometry shader
    
        vs_out.toCameraMat = pipematrix;
        gl_Position = pipematrix * vec4(aPos,1.0f);
    
    
    }

    geometry shader:

    #version 450 core
    layout(points) in;
    layout(line_strip,max_vertices = 6 ) out;
    
    
    in mat4 testMat[];
    in VS_OUT{
        mat4 toCameraMat;
    }gs_in[];
    
    out vec3 fColor;
    
    void main(){
        // build x RED
        fColor = vec3(1,0,0);
        gl_Position = gl_in[0].gl_Position + gs_in[0].toCameraMat * vec4(0.0, 0.0, 0.0, 0.0);
        EmitVertex();
        gl_Position = gl_in[0].gl_Position + gs_in[0].toCameraMat * vec4(1.0, 0.0, 0.0, 0.0);
        EmitVertex();
        // build primitive
        EndPrimitive();
    
        // build y GREEN
        fColor = vec3(0,1,0);
        gl_Position = gl_in[0].gl_Position + gs_in[0].toCameraMat * vec4(0.0, 0.0, 0.0, 0.0);
        EmitVertex();
        gl_Position = gl_in[0].gl_Position + gs_in[0].toCameraMat * vec4(0.0, 1.0, 0.0, 0.0);
        EmitVertex();
        // build primitive
        EndPrimitive();
    
        // build z BLUE
        fColor = vec3(0,0,1);
        gl_Position =gl_in[0].gl_Position + testMat[0] * vec4(0.0, 0.0, 0.0, 0.0);   // 注意这里使用的testMat 和 gs_in[0].toCameraMat 完全一样!
        EmitVertex(); 
        gl_Position =gl_in[0].gl_Position + testMat[0] * vec4(0.0, 0.0, 1.0, 0.0);
        EmitVertex();
        // build primitive
        EndPrimitive();
    }

    fragment:fragment的颜色注意是直接从geometry shader来的。

    #version 450 core
    out vec4 FragColor;
    in vec3 fColor;
    
    void main()
    {
        FragColor = vec4(fColor, 1.0);
    }
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <cstdlib>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include "ALG_LoadShader.h"
    #include "ALG_LoadTexture.h"
    #include "ALG_GLFWCamera.h"
    #include "ALG_FrameWindow.h"
    #include "ALG_ModelDelegate.h"
    #include "ALG_SceneDelegate.h"
    #include "ALG_DrawGrid.h"
    #include <cmath>
    #include "ALG_OGLHelper.h"
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <map>
    #include "ALG_DrawEnvBox.h"
    #include "ALG_DrawOriginGnomon.h"
    using namespace AlgebraMaster;
    
    
    const unsigned int SRC_WIDTH = 1400;
    const unsigned int SRC_HEIGHT = 720;
    
    
    
    static LoadShader SurfaceShader;
    
    void init();
    void display();
    
    
    void processInput(GLFWwindow *window);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
    void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);
    
    
    
    static float lastX =  float(SRC_WIDTH) / 2.0f;
    static float lastY =  float(SRC_HEIGHT) / 2.0f;
    static bool firstMouse = true;
    static bool firstMiddowMouse = true;
    // timing
    static float deltaTime = 0.0f;    // time between current frame and last frame
    static float lastFrame = 0.0f;
    
    
    
    
    // cube vao vbo
    static unsigned int VAO,VBO;
    
    // camera
    static GLFWCamera *camera;
    // light define
    static glm::vec3 lightPos(0.0f, 4.0f,-2.0f);
    
    static DrawGrid grid;
    static DrawEnvBox envBox;
    static DrawOriginGnomon originGnomon;
    static LoadTexture cubeTex;
    static LoadTexture groundTex;
    
    
    static float testPoints[] = {
            -0.5f,  0.5f, // 左上
            0.5f,  0.5f, // 右上
            0.5f, -0.5f, // 右下
            -0.5f, -0.5f  // 左下
    };
    
    void init(){
        camera = new GLFWCamera;
        camera->pos.y = 1.0f;
        camera->pos.z = 4.0f;
        // GL depth zbuffer
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        SurfaceShader.load(
                "shaders/SurfaceShader.vert",
                "shaders/SurfaceShader.frag",
                "shaders/GeometryShader.geom");
    
        CreateGeometryBuffer(VAO,VBO);
        glBufferData(GL_ARRAY_BUFFER,sizeof(testPoints),&testPoints,GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
    
    
        grid.initialize();
        originGnomon.initialize();
    }
    
    // ----------- Render Loop ----------
    void display(){
    
    
        // per-frame time logic
                // --------------------
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
    
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    
        // object .vert settings
        glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f,  1000.0f);
        glm::mat4 view = camera->GetViewMatrix();
        // object world transformation
        glm::mat4 model = glm::mat4(1.0f);
        grid.draw(projection,view);
        originGnomon.draw(projection,view);
    
    
    
    }
    
    
    int main()
    {
        cout << sizeof(float) << endl;
        glfwInit();
        FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
        glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
        glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
        glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);
        init();
        // RENDER--------------
        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        while(!glfwWindowShouldClose(FrameWindow.getWindow())){
            processInput(FrameWindow.getWindow());
            display();
            glfwSwapBuffers(FrameWindow.getWindow());
            glfwPollEvents();
        }
        delete camera;
        return 0;
    }
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        // make sure the viewport matches the new window dimensions; note that width and
        // height will be significantly larger than specified on retina displays.
        glViewport(0, 0, width, height);
    }
    
    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
    }
    
    // ROTATE VIEW DIR
    void mouse_callback(GLFWwindow* window, double xpos, double ypos){
    
        int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE);
        int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
        int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
        // set up the camera view
        if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
        {
            if (firstMouse){
                lastX = xpos;
                lastY = ypos;
                firstMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->processMouseMove(xoffset,yoffset);
        }
        if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
            firstMouse = true;
        }
    
    
        // Move Camera Position
        if( middow_mouse_state == GLFW_PRESS) {
    
            if (firstMiddowMouse){
                lastX = xpos;
                lastY = ypos;
                firstMiddowMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->pos.x += xoffset*0.01f;
            camera->pos.y += yoffset*0.01f;
    
        }
        if ( middow_mouse_state == GLFW_RELEASE){
            firstMiddowMouse = true;
        }
    
    }
    
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
        camera->processFov(yoffset);
    }
    main.cpp

     

    CP26: Opengl Instance:

     

    还是借用以前的纳米模型那张,当前文件夹结构:

     注意场景的scene.json加入了从全局材质赋予每一个材质。详细见scene.json

    Mesh的类也修改了,因为要在main.cpp中分析贴图单元,所以把Mesh类的贴图单元创建部分单独立了一个函数。

    #ifndef MESH_H
    #define MESH_H
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <string>
    #include <vector>
    #include "ALG_LoadShader.h"
    #include <GL/glew.h>
    #include "ALG_TextureDelegate.h"
    #include "ALG_Vertex.h"
    namespace AlgebraMaster
    {
    
    using namespace std;
    
    
    
    
    struct Mesh
    {
    public:
        Mesh()= default;
        //* constructor */
        Mesh(const vector<Vertex> &vts,
                const vector<unsigned int>ids);
    
        void allocateTextureChannelFromShader(const LoadShader &rhs_shader);
    
    // rendering data
        vector<Vertex> vertices;
        vector<unsigned int> indices;
    
        // ogl
        unsigned int VAO,VBO,EBO; // vertex array buffer
    
        //* this method need called manually */
        virtual void setupMesh();
    
        // ogl draw
        virtual void draw();
    
        // shader
        LoadShader shader;
    
        // get mat from outside
        void assignMaterial(const LoadShader & rhs_shader);
    
    };
    
    
    Mesh::Mesh(const vector<Vertex> &vts,
               const vector<unsigned int>ids):vertices(vts),indices(ids){
    
    }
    
    void Mesh::assignMaterial(const LoadShader &rhs_shader) {
        // shader attach
        shader.fragmentShader = rhs_shader.fragmentShader;
        shader.vertexShader = rhs_shader.vertexShader;
        shader.geometryShader = rhs_shader.geometryShader;
        shader.shaderProgram = rhs_shader.shaderProgram;
    
        // matrix attach
        shader.projection = rhs_shader.projection;
        shader.view = rhs_shader.view;
        shader.model = rhs_shader.model;
    
        // texture attach
        shader.textures = rhs_shader.textures;
    
    }
    
    void Mesh::allocateTextureChannelFromShader(const LoadShader &rhs_shader)
    {
        string mat_prefix = "material.";
        for(auto &tex: rhs_shader.textures)
        {
            switch (tex->texType)
            {
                case Texture::BASECOLOR_MAP:{
                    glActiveTexture(tex->texChannel);
                    glBindTexture(GL_TEXTURE_2D, tex->id);
                    string texchanName = mat_prefix + "diffuse_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::SPECULAR_MAP:{
                    glActiveTexture(tex->texChannel);
                    glBindTexture(GL_TEXTURE_2D, tex->id);
                    string texchanName = mat_prefix + "specular_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::EMISSION_MAP:{
                    string texchanName = mat_prefix + "emission_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::BUMP_MAP:{
                    string texchanName = mat_prefix + "bump_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::NORMAL_MAP:{
                    string texchanName = mat_prefix + "normal_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::IOR_MAP:{
                    string texchanName = mat_prefix + "ior_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::OPACITY_MAP:{
                    string texchanName = mat_prefix + "opacity_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                case Texture::DISPLACE_MAP:{
                    string texchanName = mat_prefix + "displace_map";
                    shader.setInt(texchanName.c_str(),tex->textureUnitID);
                    break;
                }
                default:
                    break;
    
            } // end of switch
    
    
        } // end of for each textures
    
    
        string haveDfName = mat_prefix + "have_diffuse_map";
        string haveSpecName = mat_prefix + "have_specular_map";
        string haveEmissionName = mat_prefix + "have_emission_map";
    
        shader.setInt(haveDfName.c_str(), rhs_shader.haveTypeTexmap(Texture::BASECOLOR_MAP));
        shader.setInt(haveSpecName.c_str(), rhs_shader.haveTypeTexmap(Texture::SPECULAR_MAP));
        shader.setInt(haveEmissionName.c_str(), rhs_shader.haveTypeTexmap(Texture::EMISSION_MAP));
    
    }
    // opengl draw the mesh
    void Mesh::draw() {
        this->shader.use();
        shader.setMatrix(shader.model,shader.view,shader.projection);
        allocateTextureChannelFromShader(this->shader);
        // draw mesh
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
    
        // always good practice to set everything back to defaults once configured.
        glActiveTexture(GL_TEXTURE0);
    }
    
    // init our mesh data
    void Mesh::setupMesh() {
        glCreateVertexArrays(1,&VAO);           // vertex array object
        glCreateBuffers(1,&VBO);                // vertex buffer object
        glCreateBuffers(1,&EBO);                // vertex element array buffer object
        glBindVertexArray(VAO);                 // bind vertex array
    
        glBindBuffer(GL_ARRAY_BUFFER,VBO);      // bind vertex buffer
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
    
        // vertex attributes
        // position
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
        // normal
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 3*sizeof(float)) );
        //tex
        glEnableVertexAttribArray(2);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 6*sizeof(float)) );
        //tangent
        glEnableVertexAttribArray(3);
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 8*sizeof(float)) );
        // bitangent
        glEnableVertexAttribArray(4);
        glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)( 11*sizeof(float)) );
    
        glBindVertexArray(0);
    }
    
    } // end of namespace
    
    #endif // MESH_H
    ALG_MeshDelegate.h
    //
    // Created by Admin on 2020/3/7.
    //
    
    #ifndef TRIANGLE_ALG_RANDOM_H
    #define TRIANGLE_ALG_RANDOM_H
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    #include <random>
    #include <iostream>
    #include <vector>
    
    
    
    #include <iostream>
    #include <limits>
    #include <random>
    
    namespace AlgebraMaster {
        using namespace std;
    
        // ------------- Float 0-1 Random gen------------------------
        struct RandomFloatBase{
            RandomFloatBase(int num, int seed=1){
            }
    
            // datas
            vector<float> values;
            default_random_engine e;
            uniform_real_distribution<double> u;
            float operator[] (int index)const{
                return values[index];
            }
            float &operator[] (int index){
                return values[index];
            }
            friend ostream & operator << (ostream &os , const RandomFloatBase &rv){
                for(auto &v:rv.values){
                    cout << v <<" ";
                }
                cout << "
    ";
                return os;
            }
    
        };
    
    
    
    
        struct Random01:public RandomFloatBase{
            Random01(int num,int seed=1);
    
        };
    
        Random01::Random01(int num,int seed): RandomFloatBase(num, seed){
            e.seed(seed);
            u = uniform_real_distribution<double>(0.0,1.0);
            for(int i=0;i<num;i++){
                values.emplace_back(u(e));
            }
        }
    
        // ------------- Float 0-1 Random gen------------------------
    
        // ------------- Float -1 - 1 Random gen------------------------
        struct RandomN1P1:public RandomFloatBase{
            RandomN1P1(int num,int seed=1);
        };
    
        RandomN1P1::RandomN1P1(int num,int seed): RandomFloatBase(num, seed){
            e.seed(seed);
            u = uniform_real_distribution<double>(-1.0,1.0);
            for(int i=0;i<num;i++){
                values.emplace_back(u(e));
            }
        }
    
    
    
    } // namespace end
    
    
    
    
    
    #endif //TRIANGLE_ALG_RANDOM_H
    ALG_Random.h
    //
    // Created by Admin on 2020/2/23.
    //
    
    #ifndef TRIANGLE_ALG_SCENEDELEGATE_H
    #define TRIANGLE_ALG_SCENEDELEGATE_H
    #include <iostream>
    #include <json.hpp>
    #include <string>
    #include <fstream>
    #include <iomanip>
    #include <vector>
    #include "ALG_LoadShader.h"
    #include "ALG_ModelDelegate.h"
    #include "ALG_LoadTexture.h"
    #include "ALG_MeshDelegate.h" // texture struct
    
    
    namespace AlgebraMaster{
    // namespace
    using namespace std;
    using json = nlohmann::json;
    //
    
    bool checkJsonError(json &j,string msg);
    bool checkJsonError(json &j,string msg)
    {
        if (j.is_null()) {
            cout << "ERROR JSON:" << msg<<endl;
            return true;
        }
        return false;
    }
    
    
    
    template <typename T>
    void FreeSTLMemory(T & container);
    
    template <typename T>
    void FreeSTLMemory(T & container){
        // release mats mem
        for(auto &c: container){
            delete c;
        }
        container.clear();
    }
    
    
    Texture *CreateTexture(const LoadTexture &textureLoader,
                               const string &relativeTexturePath,
                               Texture::Type type,
                               unsigned int textureChannel,
                               unsigned int textureUnitID);
    
    Texture *CreateTexture(const LoadTexture &textureLoader,
                           const string &relativeTexturePath,
                           Texture::Type type,
                           unsigned int textureChannel,
                           unsigned int textureUnitID)
    {
        // create texture object
        auto *texture = new Texture;                // Create our texture object
        texture->id = textureLoader.getTextureID(); // Assign GL_TextureID to our texture object
        texture->texType = type;  // set texture type
        texture->path = relativeTexturePath;            // set texture path is relative
        texture->texChannel = textureChannel;
        texture->textureUnitID = textureUnitID;   //current unique texture unit
        return texture;
    }
    
    
    
    //* scene description from json object/
    class Scene{
    public:
        Scene();
        virtual ~Scene();
        void read(const string &path);
        void save(const string &path)const;
        virtual void draw();
        string getSceneName()const;
        void setSceneName(const string &name);
        Texture * getTextureByPath(const string &path){
            for(auto &t: allTextures){
                if(t->path == path)return t;
            }
            return nullptr;
        }
    
    
        vector<LoadShader *> allShaders;
        vector<Texture*> allTextures; // all texture from json file , this index will as GL_activeTexture(TEXTURE0+i)
        LoadShader* getShaderByName(const string &name){
            for(auto &m : allShaders){
                if(m->shaderName == name)
                    return m;
            }
            return nullptr;
        }
        void debugShaders(){
            for(auto &s: allShaders){
                cout <<"Scene::debugShaders debug shader pool have:" << s->shaderName <<endl;
            }
        }
        void parseInitialize();
        // read mesh
        void parseModel();
        void parseMats();
        void parseAssignMats();
        void setMatrix(glm::mat4 &proj , glm::mat4 & view , glm::mat4 model = glm::mat4(1.0f));
        //override all model mats
        void assignMaterial(LoadShader &shader){
            for(auto &m : allModels){
                m->assignMaterial(shader);
            }
        }
    
        vector<Model*> allModels;
    private:
        // * scene description json obj */
        json j;
    
    
    
        // proj
        string project_dir;
        //
        bool textureIsLoaded(const string &texturePath);
    
    public:
        static int currentActiveTextureChannel;
        static int currentTextureLoaderIndex;
    };
    int Scene::currentActiveTextureChannel = GL_TEXTURE0;
    int Scene::currentTextureLoaderIndex = 0;
    
    // ------------------ DEFINE FUNCTION --------------------------
    Scene::Scene(){
    
    }
    Scene::~Scene() {
        // release mats mem
    
        cout << "---------------Memory Release----------------------
    ";
        cout << "free model's mem 
    ";
        FreeSTLMemory(allModels);
        //
        cout << "free all textures mem 
    ";
        FreeSTLMemory(allTextures);
        //
        cout << "free all shaders mem 
    ";
        FreeSTLMemory(allShaders);
        cout << "---------------Memory Release----------------------
    ";
    }
    
    bool Scene::textureIsLoaded(const string &texturePath) {
        bool isLoaded = false;
        for(auto &tex: allTextures){
            if (tex->path == texturePath){
                isLoaded = true;
            }
        }
        return isLoaded;
    }
    
    void Scene::setMatrix(glm::mat4 &proj , glm::mat4 &view , glm::mat4 model)
    {
        for(auto &mod :allModels){
            for(auto &loc: mod->getLocations()) {
                loc->mesh->shader.setMatrix(model, view, proj);
            }
        }
    }
    
    
    
    // Read File
    void Scene::read(const string &path) {
        ifstream  in(path.c_str());
        in >> j;
    }
    
    // Write File
    void Scene::save(const string &path) const{
        // write prettified JSON to another file
        ofstream o(path.c_str());
        o << setw(4) << j << std::endl;
    }
    
    
    string Scene::getSceneName() const {
        auto name = j["name"];
        if( name){
            return name;
        }
        return "ERROR SCENE NAME";
    }
    void Scene::setSceneName(const string &name)  {
        j["name"] = name;
    }
    
    void Scene::draw() {
        for(auto &m : allModels){
            m->draw();
        }
    }
    
    void Scene::parseInitialize()
    {
        string temp_proj_dir = j["project_dir"];
        temp_proj_dir += "/";
        project_dir = temp_proj_dir;
    
    }
    
    void Scene::parseModel() {
        cout << j["models"] <<endl;
        for(string path :j["models"]){
            auto *model = new Model;
            string absPath = project_dir + path;
            cout << "Scene Parse Read mesh:" << absPath <<endl;
            model->readMesh(absPath);
            this->allModels.emplace_back(model);
        }
    }
    
    void Scene::parseMats() {
        json globalVertFileObj = j["global_vert_file"];
        json globalFragFileObj = j["global_frag_file"];
        json globalGeomFileObj = j["global_geom_file"];
    
    
    
        //  Get global shader file path
        string globalVertRelFilePath = globalVertFileObj.get<string>();
        string globalFragRelFilePath = globalFragFileObj.get<string>();
        string globalGeomRelFilePath = globalGeomFileObj.get<string>();
    
    
    
        json mats = j["mats"];
        for (auto& mat : mats.items())
        {
            json matNameObject = mat.key(); // json mat name
            json matContentObject = mat.value();  // json tex
    
    
            json shaderDefineObject =  matContentObject["shader_define"];
            json codeTypeObject = shaderDefineObject["code_type"];
            json fragCodeObject = shaderDefineObject["frag_code"];
            json vertCodeObject = shaderDefineObject["vert_code"];
            // Get may be used local file to create shader
            json vertFileObject = shaderDefineObject["vert_file"];
    
            // ----------- INIT shader pointer---------------------
            auto *shader = new LoadShader;
            // ----------- INIT shader pointer---------------------
    
            bool jsonIsError = false;   // if is error , create default mat
            jsonIsError = checkJsonError(shaderDefineObject,"Can not find key ->shader_define  ,create default color shader");
            if(jsonIsError)
            {
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(codeTypeObject,"Can not find key ->code_type  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(fragCodeObject,"Can not find key ->frag_code  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(vertCodeObject,"Can not find key ->vert_code  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
    
    
            // JSON shader_define values
            string std_strMatName = matNameObject.get<string>(); // mat name
            int codeType = codeTypeObject.get<int>();
            string fragCode = fragCodeObject.get<string>();
            string vertCode = vertCodeObject.get<string>();
    
            cout << "system create mat:" << std_strMatName << " codeType:" <<codeType <<endl;
    
            switch (codeType)
            {
                case 0:
                {
                    shader->asSimpleShader();
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 1:
                {
                    shader->asSimpleTextureShader();
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 3:
                {
                    shader->fromSrc(vertCode,fragCode);
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 5:{
                    shader->load(globalVertRelFilePath.c_str(), globalFragRelFilePath.c_str());
                    shader->shaderName = std_strMatName;
                    break;
                }
                default:
                    // create in line shader
                    shader->asSimpleShader();
                    shader->shaderName = std_strMatName;
                    break;
            }
    
            // shader param define
            json paramDefineObject = matContentObject["params_define"];
            for(auto &params: paramDefineObject.items())
            {
                json paramNameObject = params.key();
                json valueObject = params.value(); // may be relative texture path , or shader value
    
                string paramName = paramNameObject.get<string>();
                if(paramName == "diffuse")
                {
                    string texRelativePath = valueObject.get<string>();
                    string texAbsPath = project_dir + texRelativePath;
                    // create texture loader
                    LoadTexture textureLoader;
                    textureLoader.load(texAbsPath.c_str());
                    // if texture load error, pass this loading
                    if (!textureLoader.loadStatus)
                        continue;
    
                    // if this texture have loaded
                    if (textureIsLoaded(texRelativePath))
                    {
                        shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader
                        continue;
                    }
                    unsigned int texChannel = Scene::currentActiveTextureChannel;
                    unsigned int textureUnitID = Scene::currentTextureLoaderIndex;   //current unique texture unit
                    Texture *tex = CreateTexture(textureLoader,texRelativePath,
                                                 Texture::BASECOLOR_MAP,
                                                 texChannel,
                                                 textureUnitID);
                    cout << "OPENGL->register <diffuse> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl;
                    Scene::currentTextureLoaderIndex+=1;
                    Scene::currentActiveTextureChannel+=1;
                    allTextures.emplace_back(tex);
                    shader->textures.emplace_back(tex);// make connection with pair shader
                }
    
                if(paramName == "specular")
                {
                    string texRelativePath = valueObject.get<string>();
                    string texAbsPath = project_dir + texRelativePath;
    
                    // create texture loader
                    LoadTexture textureLoader;
                    textureLoader.load(texAbsPath.c_str());
                    // if texture load error, pass this loading
                    if (!textureLoader.loadStatus)
                        continue;
    
                    // if this texture have loaded
                    if (textureIsLoaded(texRelativePath)){
                        shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader
                        continue;
                    }
                    unsigned int texChannel = Scene::currentActiveTextureChannel;
                    unsigned int textureUnitID = Scene::currentTextureLoaderIndex;   //current unique texture unit
    
    
                    Texture *tex = CreateTexture(textureLoader,texRelativePath,
                                                 Texture::SPECULAR_MAP,
                                                 texChannel,
                                                 textureUnitID);
                    cout << "OPENGL->register <specular> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl;
                    Scene::currentTextureLoaderIndex+=1;
                    Scene::currentActiveTextureChannel+=1;
    
                    allTextures.emplace_back(tex);
                    shader->textures.emplace_back(tex);// make connection with pair shader
                }
    
            } // end of mat param settings
    
            allShaders.emplace_back(shader); // place shader in our container
    
        }//end of loop material
    }
    
    void Scene::parseAssignMats() {
    
        // loop all model
        cout << ">> -------------- Parse Assign Mat Start--------------------- 
    ";
        json matTree = j["assignMaterial"];
        for(auto &tree: matTree.items()){
            json locationPWDObject = tree.key();
            json locationMatNameObject = tree.value();
    
            string locationPWD = locationPWDObject.get<string>();
            string locationMatName = locationMatNameObject.get<string>();
            LoadShader *shader = getShaderByName(locationMatName);
            if (!shader){
                cout << "ERROR Try to assign:"<< locationPWD <<",But can not find material in material pool:" << locationMatName <<endl;
                continue;
            }
    
    
            // loop all model, find the location
            for(auto &model: allModels){
                SceneLocation *loc = model->getLocationByPath(locationPWD);
                loc->mesh->assignMaterial(*shader);
                cout << "assign:" << shader->shaderName << " to:" << loc->pwd <<endl;
            }
    
        }
        cout << ">> -------------- Parse Assign Mat End--------------------- 
    ";
    }
    
    }// end of namespace
    #endif //TRIANGLE_ALG_SCENEDELEGATE_H
    ALG_SceneDelegate.h
    //
    // Created by Admin on 2020/2/23.
    //
    
    #ifndef TRIANGLE_ALG_SCENEDELEGATE_H
    #define TRIANGLE_ALG_SCENEDELEGATE_H
    #include <iostream>
    #include <json.hpp>
    #include <string>
    #include <fstream>
    #include <iomanip>
    #include <vector>
    #include "ALG_LoadShader.h"
    #include "ALG_ModelDelegate.h"
    #include "ALG_LoadTexture.h"
    #include "ALG_MeshDelegate.h" // texture struct
    
    
    namespace AlgebraMaster{
    // namespace
    using namespace std;
    using json = nlohmann::json;
    //
    
    bool checkJsonError(json &j,string msg);
    bool checkJsonError(json &j,string msg)
    {
        if (j.is_null()) {
            cout << "ERROR JSON:" << msg<<endl;
            return true;
        }
        return false;
    }
    
    
    
    template <typename T>
    void FreeSTLMemory(T & container);
    
    template <typename T>
    void FreeSTLMemory(T & container){
        // release mats mem
        for(auto &c: container){
            delete c;
        }
        container.clear();
    }
    
    
    Texture *CreateTexture(const LoadTexture &textureLoader,
                               const string &relativeTexturePath,
                               Texture::Type type,
                               unsigned int textureChannel,
                               unsigned int textureUnitID);
    
    Texture *CreateTexture(const LoadTexture &textureLoader,
                           const string &relativeTexturePath,
                           Texture::Type type,
                           unsigned int textureChannel,
                           unsigned int textureUnitID)
    {
        // create texture object
        auto *texture = new Texture;                // Create our texture object
        texture->id = textureLoader.getTextureID(); // Assign GL_TextureID to our texture object
        texture->texType = type;  // set texture type
        texture->path = relativeTexturePath;            // set texture path is relative
        texture->texChannel = textureChannel;
        texture->textureUnitID = textureUnitID;   //current unique texture unit
        return texture;
    }
    
    
    
    //* scene description from json object/
    class Scene{
    public:
        Scene();
        virtual ~Scene();
        void read(const string &path);
        void save(const string &path)const;
        virtual void draw();
        string getSceneName()const;
        void setSceneName(const string &name);
        Texture * getTextureByPath(const string &path){
            for(auto &t: allTextures){
                if(t->path == path)return t;
            }
            return nullptr;
        }
    
    
        vector<LoadShader *> allShaders;
        vector<Texture*> allTextures; // all texture from json file , this index will as GL_activeTexture(TEXTURE0+i)
        LoadShader* getShaderByName(const string &name){
            for(auto &m : allShaders){
                if(m->shaderName == name)
                    return m;
            }
            return nullptr;
        }
        void debugShaders(){
            for(auto &s: allShaders){
                cout <<"Scene::debugShaders debug shader pool have:" << s->shaderName <<endl;
            }
        }
        void parseInitialize();
        // read mesh
        void parseModel();
        void parseMats();
        void parseAssignMats();
        void setMatrix(glm::mat4 &proj , glm::mat4 & view , glm::mat4 model = glm::mat4(1.0f));
        //override all model mats
        void assignMaterial(LoadShader &shader){
            for(auto &m : allModels){
                m->assignMaterial(shader);
            }
        }
    
        vector<Model*> allModels;
    private:
        // * scene description json obj */
        json j;
    
    
    
        // proj
        string project_dir;
        //
        bool textureIsLoaded(const string &texturePath);
    
    public:
        static int currentActiveTextureChannel;
        static int currentTextureLoaderIndex;
    };
    int Scene::currentActiveTextureChannel = GL_TEXTURE0;
    int Scene::currentTextureLoaderIndex = 0;
    
    // ------------------ DEFINE FUNCTION --------------------------
    Scene::Scene(){
    
    }
    Scene::~Scene() {
        // release mats mem
    
        cout << "---------------Memory Release----------------------
    ";
        cout << "free model's mem 
    ";
        FreeSTLMemory(allModels);
        //
        cout << "free all textures mem 
    ";
        FreeSTLMemory(allTextures);
        //
        cout << "free all shaders mem 
    ";
        FreeSTLMemory(allShaders);
        cout << "---------------Memory Release----------------------
    ";
    }
    
    bool Scene::textureIsLoaded(const string &texturePath) {
        bool isLoaded = false;
        for(auto &tex: allTextures){
            if (tex->path == texturePath){
                isLoaded = true;
            }
        }
        return isLoaded;
    }
    
    void Scene::setMatrix(glm::mat4 &proj , glm::mat4 &view , glm::mat4 model)
    {
        for(auto &mod :allModels){
            for(auto &loc: mod->getLocations()) {
                loc->mesh->shader.setMatrix(model, view, proj);
            }
        }
    }
    
    
    
    // Read File
    void Scene::read(const string &path) {
        ifstream  in(path.c_str());
        in >> j;
    }
    
    // Write File
    void Scene::save(const string &path) const{
        // write prettified JSON to another file
        ofstream o(path.c_str());
        o << setw(4) << j << std::endl;
    }
    
    
    string Scene::getSceneName() const {
        auto name = j["name"];
        if( name){
            return name;
        }
        return "ERROR SCENE NAME";
    }
    void Scene::setSceneName(const string &name)  {
        j["name"] = name;
    }
    
    void Scene::draw() {
        for(auto &m : allModels){
            m->draw();
        }
    }
    
    void Scene::parseInitialize()
    {
        string temp_proj_dir = j["project_dir"];
        temp_proj_dir += "/";
        project_dir = temp_proj_dir;
    
    }
    
    void Scene::parseModel() {
        cout << j["models"] <<endl;
        for(string path :j["models"]){
            auto *model = new Model;
            string absPath = project_dir + path;
            cout << "Scene Parse Read mesh:" << absPath <<endl;
            model->readMesh(absPath);
            this->allModels.emplace_back(model);
        }
    }
    
    void Scene::parseMats() {
        json globalVertFileObj = j["global_vert_file"];
        json globalFragFileObj = j["global_frag_file"];
        json globalGeomFileObj = j["global_geom_file"];
    
    
    
        //  Get global shader file path
        string globalVertRelFilePath = globalVertFileObj.get<string>();
        string globalFragRelFilePath = globalFragFileObj.get<string>();
        string globalGeomRelFilePath = globalGeomFileObj.get<string>();
    
    
    
        json mats = j["mats"];
        for (auto& mat : mats.items())
        {
            json matNameObject = mat.key(); // json mat name
            json matContentObject = mat.value();  // json tex
    
    
            json shaderDefineObject =  matContentObject["shader_define"];
            json codeTypeObject = shaderDefineObject["code_type"];
            json fragCodeObject = shaderDefineObject["frag_code"];
            json vertCodeObject = shaderDefineObject["vert_code"];
            // Get may be used local file to create shader
            json vertFileObject = shaderDefineObject["vert_file"];
    
            // ----------- INIT shader pointer---------------------
            auto *shader = new LoadShader;
            // ----------- INIT shader pointer---------------------
    
            bool jsonIsError = false;   // if is error , create default mat
            jsonIsError = checkJsonError(shaderDefineObject,"Can not find key ->shader_define  ,create default color shader");
            if(jsonIsError)
            {
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(codeTypeObject,"Can not find key ->code_type  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(fragCodeObject,"Can not find key ->frag_code  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
            jsonIsError = checkJsonError(vertCodeObject,"Can not find key ->vert_code  ,create default color shader");
            if(jsonIsError){
                shader->asSimpleShader();
                return;
            }
    
    
            // JSON shader_define values
            string std_strMatName = matNameObject.get<string>(); // mat name
            int codeType = codeTypeObject.get<int>();
            string fragCode = fragCodeObject.get<string>();
            string vertCode = vertCodeObject.get<string>();
    
            cout << "system create mat:" << std_strMatName << " codeType:" <<codeType <<endl;
    
            switch (codeType)
            {
                case 0:
                {
                    shader->asSimpleShader();
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 1:
                {
                    shader->asSimpleTextureShader();
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 3:
                {
                    shader->fromSrc(vertCode,fragCode);
                    shader->shaderName = std_strMatName;
                    break;
                }
                case 5:{
                    shader->load(globalVertRelFilePath.c_str(), globalFragRelFilePath.c_str());
                    shader->shaderName = std_strMatName;
                    break;
                }
                default:
                    // create in line shader
                    shader->asSimpleShader();
                    shader->shaderName = std_strMatName;
                    break;
            }
    
            // shader param define
            json paramDefineObject = matContentObject["params_define"];
            for(auto &params: paramDefineObject.items())
            {
                json paramNameObject = params.key();
                json valueObject = params.value(); // may be relative texture path , or shader value
    
                string paramName = paramNameObject.get<string>();
                if(paramName == "diffuse")
                {
                    string texRelativePath = valueObject.get<string>();
                    string texAbsPath = project_dir + texRelativePath;
                    // create texture loader
                    LoadTexture textureLoader;
                    textureLoader.load(texAbsPath.c_str());
                    // if texture load error, pass this loading
                    if (!textureLoader.loadStatus)
                        continue;
    
                    // if this texture have loaded
                    if (textureIsLoaded(texRelativePath))
                    {
                        shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader
                        continue;
                    }
                    unsigned int texChannel = Scene::currentActiveTextureChannel;
                    unsigned int textureUnitID = Scene::currentTextureLoaderIndex;   //current unique texture unit
                    Texture *tex = CreateTexture(textureLoader,texRelativePath,
                                                 Texture::BASECOLOR_MAP,
                                                 texChannel,
                                                 textureUnitID);
                    cout << "OPENGL->register <diffuse> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl;
                    Scene::currentTextureLoaderIndex+=1;
                    Scene::currentActiveTextureChannel+=1;
                    allTextures.emplace_back(tex);
                    shader->textures.emplace_back(tex);// make connection with pair shader
                }
    
                if(paramName == "specular")
                {
                    string texRelativePath = valueObject.get<string>();
                    string texAbsPath = project_dir + texRelativePath;
    
                    // create texture loader
                    LoadTexture textureLoader;
                    textureLoader.load(texAbsPath.c_str());
                    // if texture load error, pass this loading
                    if (!textureLoader.loadStatus)
                        continue;
    
                    // if this texture have loaded
                    if (textureIsLoaded(texRelativePath)){
                        shader->textures.emplace_back(getTextureByPath(texRelativePath)); // make connection with pair shader
                        continue;
                    }
                    unsigned int texChannel = Scene::currentActiveTextureChannel;
                    unsigned int textureUnitID = Scene::currentTextureLoaderIndex;   //current unique texture unit
    
    
                    Texture *tex = CreateTexture(textureLoader,texRelativePath,
                                                 Texture::SPECULAR_MAP,
                                                 texChannel,
                                                 textureUnitID);
                    cout << "OPENGL->register <specular> texture:" << texRelativePath <<" ID:"<<tex->id<< " channel:"<<tex->texChannel<< " unit:"<<tex->textureUnitID <<endl;
                    Scene::currentTextureLoaderIndex+=1;
                    Scene::currentActiveTextureChannel+=1;
    
                    allTextures.emplace_back(tex);
                    shader->textures.emplace_back(tex);// make connection with pair shader
                }
    
            } // end of mat param settings
    
            allShaders.emplace_back(shader); // place shader in our container
    
        }//end of loop material
    }
    
    void Scene::parseAssignMats() {
    
        // loop all model
        cout << ">> -------------- Parse Assign Mat Start--------------------- 
    ";
        json matTree = j["assignMaterial"];
        for(auto &tree: matTree.items()){
            json locationPWDObject = tree.key();
            json locationMatNameObject = tree.value();
    
            string locationPWD = locationPWDObject.get<string>();
            string locationMatName = locationMatNameObject.get<string>();
            LoadShader *shader = getShaderByName(locationMatName);
            if (!shader){
                cout << "ERROR Try to assign:"<< locationPWD <<",But can not find material in material pool:" << locationMatName <<endl;
                continue;
            }
    
    
            // loop all model, find the location
            for(auto &model: allModels){
                SceneLocation *loc = model->getLocationByPath(locationPWD);
                loc->mesh->assignMaterial(*shader);
                cout << "assign:" << shader->shaderName << " to:" << loc->pwd <<endl;
            }
    
        }
        cout << ">> -------------- Parse Assign Mat End--------------------- 
    ";
    }
    
    }// end of namespace
    #endif //TRIANGLE_ALG_SCENEDELEGATE_H
    scene.json
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <cstdlib>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include "ALG_LoadShader.h"
    #include "ALG_LoadTexture.h"
    #include "ALG_GLFWCamera.h"
    #include "ALG_FrameWindow.h"
    #include "ALG_ModelDelegate.h"
    #include "ALG_SceneDelegate.h"
    #include "ALG_DrawGrid.h"
    #include "ALG_DrawOriginGnomon.h"
    #include <cmath>
    
    #include "ALG_Random.h"
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    using namespace AlgebraMaster;
    
    
    const unsigned int SRC_WIDTH = 1400;
    const unsigned int SRC_HEIGHT = 720;
    
    
    static GLuint cubeVAO,VBO;
    static GLuint lightVAO;  //VBO stays the same; the vertices are the same for the light object which is also a 3D cube
    
    
    static LoadShader SurfaceShader;
    
    void init();
    void display();
    
    
    void processInput(GLFWwindow *window);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
    void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);
    
    
    // camera
    static GLFWCamera *camera;
    static float lastX =  float(SRC_WIDTH) / 2.0f;
    static float lastY =  float(SRC_HEIGHT) / 2.0f;
    static bool firstMouse = true;
    static bool firstMiddowMouse = true;
    // timing
    static float deltaTime = 0.0f;    // time between current frame and last frame
    static float lastFrame = 0.0f;
    
    // light define
    static glm::vec3 lightPos(0.0f, 4.0f,-2.0f);
    
    static Scene scene;
    static DrawGrid grid;
    static DrawOriginGnomon gnomon;
    const int amount = 10000;
    void init(){
    
    
    
        camera = new GLFWCamera;
        camera->pos.y = 5.0f;
        camera->pos.z = 25.0f;
        // GL depth zbuffer
        glEnable(GL_DEPTH_TEST);
    
    
        SurfaceShader.load("shaders/standard_surface/SurfaceShader.vert","shaders/standard_surface/SurfaceShader.frag");
    
    
        scene.read("scene/scene.json");
        scene.parseInitialize();
        scene.parseModel();
        scene.parseMats();
        scene.parseAssignMats();
    
        grid.initialize();
        gnomon.initialize();
    
    
        // Instance Array building:
    
        auto *modelMatrices = new glm::mat4[amount];
    
        RandomN1P1 xPosSet(amount, 1);
        RandomN1P1 zPosSet(amount, 2);
        RandomN1P1 rotAmount(amount,3);
        Random01 scaleAmount(amount,4);
        //cout << scaleAmount <<endl;
    
        for(int i=0;i<amount;i++)
        {
            // new translate
            glm::mat4 model(1.0f);
            model = glm::translate(model,glm::vec3(xPosSet[i]*100, 0.0, zPosSet[i]*100  )  );
            // new rot
            glm::mat4 rot(1.0f);
            rot = glm::rotate(rot,glm::radians(rotAmount[i]*360) , glm::vec3(0.0,1.0,0.0));
            // R S T order
            glm::mat4 scale(1.0f);
            scale = glm::scale(  scale,glm::vec3(scaleAmount[i])  );
    
            modelMatrices[i] = model * scale * rot  ;
        }
        //object share one mem buffer of instance
        unsigned int buffer;
        glCreateBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);
    
        for(auto &model: scene.allModels){
            for(auto &loc: model->locations)
            {
                glBindVertexArray(loc->mesh->VAO);
    
                glEnableVertexAttribArray(10);
                glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
    
                glEnableVertexAttribArray(11);
                glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));
    
                glEnableVertexAttribArray(12);
                glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));
    
                glEnableVertexAttribArray(13);
                glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));
    
                glVertexAttribDivisor(10, 1);
                glVertexAttribDivisor(11, 1);
                glVertexAttribDivisor(12, 1);
                glVertexAttribDivisor(13, 1);
                glBindVertexArray(0);
            }
        }
        delete [] modelMatrices;
    
    
    }
    
    // ----------- Render Loop ----------
    void display(){
    
        // per-frame time logic
                // --------------------
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
    
    
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // object .vert settings
        glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f,  1000.0f);
        glm::mat4 view = camera->GetViewMatrix();
        // object world transformation
        glm::mat4 model = glm::mat4(1.0f);
        scene.setMatrix(projection,view,model);
    
    
    
        for(auto &m: scene.allModels){
            for(auto &loc: m->locations){
                glBindVertexArray(loc->mesh->VAO);
    
                loc->mesh->shader.use();
                loc->mesh->shader.setInt("useInstance", 1);
                loc->mesh->shader.setMatrix(model,view,projection);
                loc->mesh->allocateTextureChannelFromShader(loc->mesh->shader);
                //loc->mesh->draw();
                //glDrawElements(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0);
                glDrawElementsInstanced(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0, amount);
                glBindVertexArray(0);
            }
        }
    
    
        grid.draw(projection,view);
        gnomon.draw(projection,view);
    
    
    
    }
    
    
    int main()
    {
        glfwInit();
        FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
        glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
        glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
        glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);
        init();
        // RENDER--------------
        while(!glfwWindowShouldClose(FrameWindow.getWindow())){
            processInput(FrameWindow.getWindow());
            display();
            glfwSwapBuffers(FrameWindow.getWindow());
            glfwPollEvents();
        }
        delete camera;
        return 0;
    }
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        // make sure the viewport matches the new window dimensions; note that width and
        // height will be significantly larger than specified on retina displays.
        glViewport(0, 0, width, height);
    }
    
    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
            camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
    }
    
    // ROTATE VIEW DIR
    void mouse_callback(GLFWwindow* window, double xpos, double ypos){
    
        int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE);
        int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
        int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
        // set up the camera view
        if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
        {
            if (firstMouse){
                lastX = xpos;
                lastY = ypos;
                firstMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->processMouseMove(xoffset,yoffset);
        }
        if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
            firstMouse = true;
        }
    
    
        // Move Camera Position
        if( middow_mouse_state == GLFW_PRESS) {
    
            if (firstMiddowMouse){
                lastX = xpos;
                lastY = ypos;
                firstMiddowMouse = false;
            }
            float xoffset = xpos - lastX;
            float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
            lastX = xpos;
            lastY = ypos;
            camera->pos.x += xoffset*0.01f;
            camera->pos.y += yoffset*0.01f;
    
        }
        if ( middow_mouse_state == GLFW_RELEASE){
            firstMiddowMouse = true;
        }
    
    }
    
    void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
        camera->processFov(yoffset);
    }
    main.cpp
    #version 450 core
    // INCOMING DATA
    layout ( location = 0 ) in vec4 v_position; //  pos
    layout ( location = 1 ) in vec3 v_normal;   //  norm
    layout ( location = 2 ) in vec2 v_texCoord; //  st
    
    
    layout ( location = 10 ) in  mat4 v_instanceMatrix; // instancer matrix , because have 4 * 4 row , so location 4 5 6 will use to construct this matrix
    
    // define out data
    out vec2 f_TexCoord;
    // normal at world matrix, we direct from C++ calcalation
    out vec3 f_Normal;  // to world matrix : mat3( transpose(inverse(model)) ) * v_normal;
    out vec3 f_Pos;
    
    
    // INCOMING THE MATRIX FROM CLIENT to transform the gl point position
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    // if use Instance Matrix
    uniform bool useInstance;
    
    void main(){
        // Transform the world matrix to view matrix
    
        if (useInstance){
            gl_Position = projection *  view * v_instanceMatrix * model  * v_position;
            f_Normal = mat3(transpose(inverse(v_instanceMatrix*model))) * v_normal;  // f_Normal at world matrix
        }
        else{
            gl_Position = projection *   view * model * v_position;
            f_Normal = mat3(transpose(inverse(model))) * v_normal;  // f_Normal at world matrix
        }
    
        //gl_Position = projection *   view * model * v_position;
        f_TexCoord = v_texCoord;          // out TexCoord
        f_Pos = vec3(model *v_position);  // out fragment position
    }
    SurfaceShader.vert
    #version 450 core
    // Final Color To export
    out vec4 FragColor;
    
    // from vert shader
    in vec3 f_Normal;
    in vec2 f_TexCoord;
    in vec3 f_Pos; // fragment position
    
    
    
    struct Material
    {
        float Kd;        // diffuse mult
        float kS;        // specular mult
        float shininess; // phong pow(,shine)
        sampler2D diffuse_map;
        sampler2D specular_map;
        sampler2D emission_map;
    
        bool have_diffuse_map;
        bool have_specular_map;
        bool have_emission_map;
    };
    
    uniform vec3 viewPos;
    uniform Material material;
    
    
    void main()
    {
        vec4 df_tex = vec4(1,0,0,0);
        vec4 spec_tex = vec4(0,1,0,0);
        int test = int(material.have_diffuse_map);
        if(material.have_diffuse_map){df_tex=texture(material.diffuse_map, f_TexCoord);}
        if(material.have_specular_map){spec_tex=texture(material.specular_map, f_TexCoord);}
        FragColor = vec4(df_tex.rgb,1.0);
    }
    SurfaceShader.frag

    由于我写的场景描述,到main中依然很轻松的访问绘制过程。

    for(auto &m: scene.allModels){
            for(auto &loc: m->locations){
                glBindVertexArray(loc->mesh->VAO);
    
                loc->mesh->shader.use();
                loc->mesh->shader.setInt("useInstance", 1);
                loc->mesh->shader.setMatrix(model,view,projection);
                loc->mesh->allocateTextureChannelFromShader(loc->mesh->shader);
                //loc->mesh->draw();
                //glDrawElements(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0);
                glDrawElementsInstanced(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0, amount);
                glBindVertexArray(0);
            }
        }
  • 相关阅读:
    跟着我学习-python-01-流程控制语句
    跟着我学习-python-01-用户交互
    跟着我学习-python-02-while循环
    基于Centos7.6上Ambari2.7.4+HDP3.1.4离线安装
    TDH(Transwarp Data Hub)社区版安装教程
    跟我学习日常写的shell脚本-设置系统selinux
    [Linux]常用命令“ll”失效或命令未找到
    NPOI
    Linq&lamda相关
    接口相关
  • 原文地址:https://www.cnblogs.com/gearslogy/p/12411367.html
Copyright © 2011-2022 走看看