zoukankan      html  css  js  c++  java
  • OpenGL Bindless Texture

    OPENGL有一种不用绑定贴图单元的方法,直接一次性加载到uniform buffer中。

    这就是加载时候稍微用时间,之后

    的效率大大高于glActiveTexture(GL_TEXTUREi)之类这样的方法。

    但是依然你要在每个材质写出这个uniformbuffer object的入口。

    如2个贴图:

     

    1,使用贴图单元:

    glsl得vert shading以下全部不变

    #version 450 core
    
    layout (location = 0) in vec3 P;
    layout (location = 1) in vec3 Cd;
    layout (location = 2) in vec2 texCoords;
    
    out vec3 FS_Cd;
    out vec2 FS_texCoords;
    
    
    
    void main() {
        gl_Position = vec4(P, 1.0);
        FS_Cd = Cd;
        FS_texCoords = texCoords;
    }

    fragment:

    #version 450 core
    #extension GL_ARB_bindless_texture : require
    
    
    
    in vec3 FS_Cd;
    in vec2 FS_texCoords;
    
    // ----------this is for test---------------
    uniform sampler2D img1;
    uniform sampler2D img2;
    // ----------this is for test---------------
    
    
    out vec4 color;
    
    void main() {
        vec3 img1rgb =  texture(img1, FS_texCoords).rgb ;
        vec3 img2rgb =  texture(img2, FS_texCoords).rgb ;
    
        img1rgb = pow(img1rgb,vec3(1/2.2) );
        img2rgb = pow(img2rgb,vec3(1/2.2) );
        color = vec4(img1rgb, 1.0);
    
    }
    //
    // Created by admin on 2020/6/8.
    //
    
    #ifndef TRIANGLE_ERRORCHECK_H
    #define TRIANGLE_ERRORCHECK_H
    #include <iostream>
    #include <string>
    namespace AlgebraMaster {
    using namespace std;
    
    #include <GL/glew.h>
        void CHECK_PROGRAM(const GLuint &program);
        void CHECK_PROGRAM(const GLuint &program){
            GLint success;
            GLchar infoLog[1024];
            glGetProgramiv(program, GL_LINK_STATUS, &success);
            if(!success)
            {
                glGetProgramInfoLog(program, 1024, NULL, infoLog);
                std::cout << "ERROR::PROGRAM_LINKING_ERROR of ID: " << program << "
    " << infoLog << "
     -- --------------------------------------------------- -- " << std::endl;
            }
        }
    
        void CHECK_SHADER(const GLuint & shader,const char *shaderType);
        void CHECK_SHADER(const GLuint & shader,const char *shaderType){
            GLint success;
            GLchar infoLog[1024];
            glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
            if(!success)
            {
                glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << shaderType << "
    " << infoLog << "
     -- --------------------------------------------------- -- " << std::endl;
            }
        }
    
    }
    
    #endif //TRIANGLE_ERRORCHECK_H
    errorCheck.h
    //
    // Created by admin on 2020/6/8.
    //
    
    #ifndef TRIANGLE_LOADTEXTURE_H
    #define TRIANGLE_LOADTEXTURE_H
    #define STB_IMAGE_IMPLEMENTATION
    #include "stb_image.h"
    
    #include <GL/glew.h>
    #include <memory>
    #include <iostream>
    
    namespace AlgebraMaster {
        struct Texture{
            ~Texture(){
                std::cout << "[ SYS::Texture Release Texture ]
    ";
                glDeleteTextures(1,&id);
            }
            GLuint id;
            int nrchans;
            GLenum imageFormat;
            GLenum pixelFormat;
            int width;
            int height;
            GLuint64 handle;
        };
        using TexPtr = std::shared_ptr<Texture>;
    
        TexPtr loadTexture(const char * path);
    
        TexPtr loadTexture(const char * path){
            TexPtr texPtr = std::make_shared<Texture>();
            glGenTextures(1, &texPtr->id);
            cout << "create texture :" << texPtr->id << endl;
            stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
            unsigned char *data = stbi_load(path,&texPtr->width, &texPtr->height, &texPtr->nrchans,0);
            if(data){
                if (texPtr->nrchans == 1){
                    texPtr->imageFormat = GL_RED;
                    texPtr->pixelFormat = GL_RED;
                }
    
                else if (texPtr->nrchans == 3){
                    texPtr->imageFormat = GL_SRGB;
                    texPtr->pixelFormat = GL_RGB;
                }
    
                else if (texPtr->nrchans == 4){
                    texPtr->imageFormat = GL_SRGB_ALPHA;
                    texPtr->pixelFormat = GL_RGBA;
                }
    
            }
            else{
                cout << "ERROR::can not load image
    ";
            }
    
            glBindTexture(GL_TEXTURE_2D, texPtr->id);
            // create opengl image
            glTexImage2D(GL_TEXTURE_2D, 0, texPtr->imageFormat,texPtr->width, texPtr->height, 0, texPtr->pixelFormat, GL_UNSIGNED_BYTE, data);
            // gen MipMap
            glGenerateMipmap(GL_TEXTURE_2D);
    
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
            texPtr->handle = glGetTextureHandleARB(texPtr->id);
            glMakeTextureHandleResidentARB(texPtr->handle);
            cout << "create texture handle :" << texPtr->handle << endl;
            stbi_image_free(data);
            return texPtr;
        }
    
    
    
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    #endif //TRIANGLE_LOADTEXTURE_H
    loadTexture.h
    //
    // Created by admin on 2020/6/8.
    //
    
    #ifndef TRIANGLE_GEOPTRS_H
    #define TRIANGLE_GEOPTRS_H
    #include <GL/glew.h>
    #include <memory>
    
    namespace AlgebraMaster {
        struct Geo{
            GLuint VAO{}, VBO{};
        };
    
        struct ElementGeo:public Geo {
            ElementGeo(){
                glCreateVertexArrays(1, &VAO);
                glBindVertexArray(VAO);
                glGenBuffers(1, &VBO);
                glGenBuffers(1, &EBO);
            }
    
            ~ElementGeo() {
                std::cout << "[ SYS::ElementGeo Release the geometry ] 
     ";
                glDeleteVertexArrays(1, &VAO);
                glDeleteBuffers(1, &VBO);
                glDeleteBuffers(1, &EBO);
            }
    
            // members
            GLuint EBO{};
        };
    
        using ElementGeoPtr = std::shared_ptr<ElementGeo>;
        ElementGeoPtr MakeElementGeo() {
            return std::make_shared<ElementGeo>();
        }
    
    }
    
    
    
    #endif //TRIANGLE_GEOPTRS_H
    geoPtrs.h
    //
    // Created by admin on 2020/6/3.
    //
    
    #ifndef TRIANGLE_UTILS_H
    #define TRIANGLE_UTILS_H
    
    #include <string>
    #include <sstream>
    #include <fstream>
    #include <iostream>
    
    namespace AlgebraMaster {
        using namespace std;
    
    
    
    
        // -------------- function decl-------------------------
        string readFile(const char *path);
    
    
        // ------------ function imp ------------------------
        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;
        }
    
    
    
    }
    
    
    #endif //TRIANGLE_UTILS_H
    utils.h
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <chrono>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include "utils.h"
    #include "errorCheck.h"
    #include "geoPtrs.h"
    #include "loadTexture.h"
    
    using namespace std;
    using namespace AlgebraMaster;
    
    const int width = 800;
    const int height = 800;
    
    
    static GLuint shaderProgram;
    static GLuint UBO;
    
    
    void init_geo(const ElementGeoPtr& geoPtr, GLfloat *data, int numVertdata, unsigned int *indices, int numIndices){
        glBindBuffer(GL_ARRAY_BUFFER, geoPtr->VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * numVertdata, data, GL_STREAM_DRAW);
        //glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STREAM_DRAW);
        //glNamedBufferData(VBO,sizeof(data),data,GL_STREAM_DRAW);
        //glNamedBufferStorage(VBO,sizeof(data),data, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geoPtr->EBO);
        glNamedBufferData(geoPtr->EBO,sizeof(unsigned int) * numIndices, indices , GL_STREAM_DRAW);
        glBindVertexArray(geoPtr->VAO);
        // Position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) 0);
        glEnableVertexAttribArray(0);
        // Cd
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
        // tex coords
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(2);
    
    }
    
    void init_ubo(){
        glGenBuffers(1, &UBO);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(unsigned int), NULL, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
        // define the range of the buffer that links to a uniform binding point
        glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(int));
    }
    
    void initShader(){
        string vert_code =  readFile("shaders/bindless/surf.vert");
        string frag_code =  readFile("shaders/bindless/surf.frag");
    
        const char * vertexShaderSrc = vert_code.c_str();
        const char * fragShaderSrc = frag_code.c_str();
        // Compile shaders
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
        glCompileShader(vertexShader);
        CHECK_SHADER(vertexShader,"VERTEX");
    
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragShaderSrc, nullptr);
        glCompileShader(fragmentShader);
        CHECK_SHADER(vertexShader,"FRAGMENT");
    
        // Create shaderProgram and specify transform feedback variables
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
    
        glLinkProgram(shaderProgram);
        glUseProgram(shaderProgram);
        CHECK_PROGRAM(shaderProgram);
    
        // no more need
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }
    
    void load_textures(TexPtr &tex01, TexPtr &tex02){
        tex01 = loadTexture("shaders/texs/container.jpg");
        tex02 = loadTexture("shaders/texs/ground.png");
    }
    
    void display(){
        // render
        // ------
        glUseProgram(shaderProgram);
        glDrawElements(GL_TRIANGLES,6, GL_UNSIGNED_INT, nullptr);
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    
    
    int main(){
    
    
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //glfwWindowHint(GLFW_VISIBLE,GL_FALSE);
        GLFWwindow * window = glfwCreateWindow(width,height,"Hello",NULL,NULL);
        glfwSetCursorPosCallback(window, cursor_pos_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwMakeContextCurrent(window);
        glewInit();
    
    
        cout << ">>initialize shaders
    ";
        initShader();
        float vertices[] = {
                // positions          // colors           // texture coords
                0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
                0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
                -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
                -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
    
        unsigned int indices[] = {
                0, 1, 3, // first triangle
                1, 2, 3  // second triangle
        };
        cout << ">>initialize geometry
    ";
        ElementGeoPtr geoPtr = MakeElementGeo();
        init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int));
    
        cout << ">>initialize to load textures
    ";
        TexPtr tex01;
        TexPtr tex02;
        load_textures(tex01, tex02);
    
    
    
        glUseProgram(shaderProgram);
        cout << ">>binding texture->" << tex01->id << endl;
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, tex01->id);
        cout << ">>binding texture->" << tex02->id << endl;
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, tex02->id);
        glUniform1i(glGetUniformLocation(shaderProgram,"img1"), 0);
        glUniform1i(glGetUniformLocation(shaderProgram,"img2"), 1);
    
    
        auto t_prev = std::chrono::high_resolution_clock::now();
        while( !glfwWindowShouldClose( window ) ) {
            // Clear the screen to black
            glClearColor(0.2f, 0.2f, 0.2f, 0.2f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Calculate delta time
            auto t_now = std::chrono::high_resolution_clock::now();
            float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_prev).count();
            t_prev = t_now;
    
            // Render content
            display();
    
            // then swap buffers
            glfwSwapBuffers(window);
            glfwPollEvents();
    
        }
    
        glfwTerminate();
        glfwDestroyWindow(window);
    
        return 0;
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y){
    
    }
    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);
    
    }
    main.cpp

    关键代码就是:

    cout << ">>binding texture->" << tex01->id << endl;
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex01->id);
    cout << ">>binding texture->" << tex02->id << endl;
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, tex02->id);
    glUniform1i(glGetUniformLocation(shaderProgram,"img1"), 0);
    glUniform1i(glGetUniformLocation(shaderProgram,"img2"), 1);

    2,使用bindless方法:

    frag其实没啥变化:

    #version 450 core
    #extension GL_ARB_bindless_texture : require
    
    in vec3 FS_Cd;
    in vec2 FS_texCoords;
    
    // --------- bindless texture ---------------
    uniform sampler2D tex0;
    uniform sampler2D tex1;
    // --------- bindless texture ---------------
    out vec4 color;
    
    void main() {
        vec3 tex0rgb = texture(tex0, FS_texCoords).rgb;
        vec3 tex1rgb = texture(tex1, FS_texCoords).rgb;
    
        color = vec4(tex0rgb, 1.0);
    }

    cpp设置关键两句:

    glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex0"), tex01->handle);
    glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex1"), tex02->handle);
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <chrono>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include "utils.h"
    #include "errorCheck.h"
    #include "geoPtrs.h"
    #include "loadTexture.h"
    
    using namespace std;
    using namespace AlgebraMaster;
    
    const int width = 800;
    const int height = 800;
    
    
    static GLuint shaderProgram;
    static GLuint UBO;
    
    
    void init_geo(const ElementGeoPtr& geoPtr, GLfloat *data, int numVertdata, unsigned int *indices, int numIndices){
        glBindBuffer(GL_ARRAY_BUFFER, geoPtr->VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * numVertdata, data, GL_STREAM_DRAW);
        //glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STREAM_DRAW);
        //glNamedBufferData(VBO,sizeof(data),data,GL_STREAM_DRAW);
        //glNamedBufferStorage(VBO,sizeof(data),data, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geoPtr->EBO);
        glNamedBufferData(geoPtr->EBO,sizeof(unsigned int) * numIndices, indices , GL_STREAM_DRAW);
        glBindVertexArray(geoPtr->VAO);
        // Position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) 0);
        glEnableVertexAttribArray(0);
        // Cd
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
        // tex coords
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(2);
    
    }
    
    void init_ubo(){
        glGenBuffers(1, &UBO);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(GLuint), NULL, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
        // define the range of the buffer that links to a uniform binding point
        glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(GLuint));
    }
    
    void initShader(){
        string vert_code =  readFile("shaders/bindless/surf.vert");
        string frag_code =  readFile("shaders/bindless/surf.frag");
    
        const char * vertexShaderSrc = vert_code.c_str();
        const char * fragShaderSrc = frag_code.c_str();
        // Compile shaders
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
        glCompileShader(vertexShader);
        CHECK_SHADER(vertexShader,"VERTEX");
    
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragShaderSrc, nullptr);
        glCompileShader(fragmentShader);
        CHECK_SHADER(vertexShader,"FRAGMENT");
    
        // Create shaderProgram and specify transform feedback variables
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
    
        glLinkProgram(shaderProgram);
        glUseProgram(shaderProgram);
        CHECK_PROGRAM(shaderProgram);
    
        // no more need
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }
    
    void load_textures(TexPtr &tex01, TexPtr &tex02){
        tex01 = loadTexture("shaders/texs/container.jpg");
        tex02 = loadTexture("shaders/texs/ground.png");
    }
    
    void display(){
        // render
        // ------
        glUseProgram(shaderProgram);
        glDrawElements(GL_TRIANGLES,6, GL_UNSIGNED_INT, nullptr);
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    
    
    int main(){
    
    
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //glfwWindowHint(GLFW_VISIBLE,GL_FALSE);
        GLFWwindow * window = glfwCreateWindow(width,height,"Hello",NULL,NULL);
        glfwSetCursorPosCallback(window, cursor_pos_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwMakeContextCurrent(window);
        glewInit();
    
    
        cout << ">>initialize shaders
    ";
        initShader();
        float vertices[] = {
                // positions          // colors           // texture coords
                0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
                0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
                -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
                -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
    
        unsigned int indices[] = {
                0, 1, 3, // first triangle
                1, 2, 3  // second triangle
        };
        cout << ">>initialize geometry
    ";
        ElementGeoPtr geoPtr = MakeElementGeo();
        init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int));
    
        cout << ">>initialize to load textures
    ";
        TexPtr tex01;
        TexPtr tex02;
        load_textures(tex01, tex02);
    
        /*
        cout << ">>initialize the Uniform buffer objects
    ";
        init_ubo();
        unsigned int ubid = glGetUniformBlockIndex(shaderProgram, "alltex");
        cout << "get the blocks id :" << ubid << endl;
        glUniformBlockBinding(shaderProgram,    ubid, 0);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLuint), &(tex01->handle));
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(GLuint), sizeof(GLuint), &(tex02->handle));
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    */
        glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex0"), tex01->handle);
        glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex1"), tex02->handle);
    
    
        auto t_prev = std::chrono::high_resolution_clock::now();
        while( !glfwWindowShouldClose( window ) ) {
            // Clear the screen to black
            glClearColor(0.2f, 0.2f, 0.2f, 0.2f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Calculate delta time
            auto t_now = std::chrono::high_resolution_clock::now();
            float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_prev).count();
            t_prev = t_now;
    
            // Render content
            display();
    
            // then swap buffers
            glfwSwapBuffers(window);
            glfwPollEvents();
    
        }
    
        glfwTerminate();
        glfwDestroyWindow(window);
    
        return 0;
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y){
    
    }
    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);
    
    }
    全部代码main.cpp

    3,使用uniform buffer block object

    #version 450 core
    #extension GL_ARB_bindless_texture : require
    
    in vec3 FS_Cd;
    in vec2 FS_texCoords;
    
    // --------- bindless texture ---------------
    layout (binding=0) uniform alltexs{
        sampler2D tex0;
        sampler2D tex1;
    };
    
    // --------- bindless texture ---------------
    out vec4 color;
    
    void main() {
        vec3 tex0rgb = texture(tex0, FS_texCoords).rgb;
        vec3 tex1rgb = texture(tex1, FS_texCoords).rgb;
    
        color = vec4(tex1rgb, 1.0);
    }

    关键语句:

    init_ubo();
    unsigned int ubid = glGetUniformBlockIndex(shaderProgram, "alltex");
    cout << "get the blocks id :" << ubid << endl;
    glUniformBlockBinding(shaderProgram,    ubid, 0);
    glBindBuffer(GL_UNIFORM_BUFFER, UBO);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLuint64), &(tex01->handle));   // tex0
    glBufferSubData(GL_UNIFORM_BUFFER, sizeof(GLuint64), sizeof(GLuint64), &(tex02->handle)); //tex1
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <chrono>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include "utils.h"
    #include "errorCheck.h"
    #include "geoPtrs.h"
    #include "loadTexture.h"
    
    using namespace std;
    using namespace AlgebraMaster;
    
    const int width = 800;
    const int height = 800;
    
    
    static GLuint shaderProgram;
    static GLuint UBO;
    
    
    void init_geo(const ElementGeoPtr& geoPtr, GLfloat *data, int numVertdata, unsigned int *indices, int numIndices){
        glBindBuffer(GL_ARRAY_BUFFER, geoPtr->VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * numVertdata, data, GL_STREAM_DRAW);
        //glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STREAM_DRAW);
        //glNamedBufferData(VBO,sizeof(data),data,GL_STREAM_DRAW);
        //glNamedBufferStorage(VBO,sizeof(data),data, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geoPtr->EBO);
        glNamedBufferData(geoPtr->EBO,sizeof(unsigned int) * numIndices, indices , GL_STREAM_DRAW);
        glBindVertexArray(geoPtr->VAO);
        // Position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) 0);
        glEnableVertexAttribArray(0);
        // Cd
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
        // tex coords
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(2);
    
    }
    
    void init_ubo(){
        glGenBuffers(1, &UBO);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(GLuint64), NULL, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
        // define the range of the buffer that links to a uniform binding point
        glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(GLuint64));
    }
    
    void initShader(){
        string vert_code =  readFile("shaders/bindless/surf.vert");
        string frag_code =  readFile("shaders/bindless/surf.frag");
    
        const char * vertexShaderSrc = vert_code.c_str();
        const char * fragShaderSrc = frag_code.c_str();
        // Compile shaders
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
        glCompileShader(vertexShader);
        CHECK_SHADER(vertexShader,"VERTEX");
    
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragShaderSrc, nullptr);
        glCompileShader(fragmentShader);
        CHECK_SHADER(vertexShader,"FRAGMENT");
    
        // Create shaderProgram and specify transform feedback variables
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
    
        glLinkProgram(shaderProgram);
        glUseProgram(shaderProgram);
        CHECK_PROGRAM(shaderProgram);
    
        // no more need
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }
    
    void load_textures(TexPtr &tex01, TexPtr &tex02){
        tex01 = loadTexture("shaders/texs/container.jpg");
        tex02 = loadTexture("shaders/texs/ground.png");
    }
    
    void display(){
        // render
        // ------
        glUseProgram(shaderProgram);
        glDrawElements(GL_TRIANGLES,6, GL_UNSIGNED_INT, nullptr);
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    
    
    int main(){
    
    
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //glfwWindowHint(GLFW_VISIBLE,GL_FALSE);
        GLFWwindow * window = glfwCreateWindow(width,height,"Hello",NULL,NULL);
        glfwSetCursorPosCallback(window, cursor_pos_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwMakeContextCurrent(window);
        glewInit();
    
    
        cout << ">>initialize shaders
    ";
        initShader();
        float vertices[] = {
                // positions          // colors           // texture coords
                0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
                0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
                -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
                -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
    
        unsigned int indices[] = {
                0, 1, 3, // first triangle
                1, 2, 3  // second triangle
        };
        cout << ">>initialize geometry
    ";
        ElementGeoPtr geoPtr = MakeElementGeo();
        init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int));
    
        cout << ">>initialize to load textures
    ";
        TexPtr tex01;
        TexPtr tex02;
        load_textures(tex01, tex02);
    
    
        cout << ">>initialize the Uniform buffer objects
    ";
        init_ubo();
        unsigned int ubid = glGetUniformBlockIndex(shaderProgram, "alltex");
        cout << "get the blocks id :" << ubid << endl;
        glUniformBlockBinding(shaderProgram,    ubid, 0);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLuint64), &(tex01->handle));
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(GLuint64), sizeof(GLuint64), &(tex02->handle));
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    
        //glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex0"), tex01->handle);
        //glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex1"), tex02->handle);
    
    
        auto t_prev = std::chrono::high_resolution_clock::now();
        while( !glfwWindowShouldClose( window ) ) {
            // Clear the screen to black
            glClearColor(0.2f, 0.2f, 0.2f, 0.2f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Calculate delta time
            auto t_now = std::chrono::high_resolution_clock::now();
            float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_prev).count();
            t_prev = t_now;
    
            // Render content
            display();
    
            // then swap buffers
            glfwSwapBuffers(window);
            glfwPollEvents();
    
        }
    
        glfwTerminate();
        glfwDestroyWindow(window);
    
        return 0;
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y){
    
    }
    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);
    
    }
    全部代码main.cpp

    4,使用数组

    #version 450 core
    #extension GL_ARB_bindless_texture : require
    
    in vec3 FS_Cd;
    in vec2 FS_texCoords;
    
    // --------- bindless texture ---------------
    layout (std140,binding=0) uniform alltexs{
        sampler2D tex[2];
    };
    
    // --------- bindless texture ---------------
    out vec4 color;
    
    void main() {
        vec3 tex0rgb = texture(tex[0], FS_texCoords).rgb;
        vec3 tex1rgb = texture(tex[1], FS_texCoords).rgb;
        // todo the gamma correct
        // todo the tone mapping
        color = vec4(tex0rgb, 1.0);
    }

    关键代码:

    cout << ">>initialize the Uniform buffer objects
    ";
    init_ubo();
    unsigned int ubid = glGetUniformBlockIndex(shaderProgram, "alltex");
    cout << "get the blocks id :" << ubid << endl;
    struct samplers{
        GLuint64 tex[2];
    };
    samplers allSamplers{}; allSamplers.tex[
    0] = tex01->handle; allSamplers.tex[1] = tex02->handle; glUniformBlockBinding(shaderProgram, ubid, 0); glBindBuffer(GL_UNIFORM_BUFFER, UBO); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(allSamplers), allSamplers.tex);
    #define GLEW_STATIC
    // GLEW
    #include <GL/glew.h>
    #include <chrono>
    #undef GLFW_DLL
    // GLFW
    #include <GLFW/glfw3.h>
    #include "utils.h"
    #include "errorCheck.h"
    #include "geoPtrs.h"
    #include "loadTexture.h"
    
    using namespace std;
    using namespace AlgebraMaster;
    
    const int width = 800;
    const int height = 800;
    
    
    static GLuint shaderProgram;
    static GLuint UBO;
    
    
    void init_geo(const ElementGeoPtr& geoPtr, GLfloat *data, int numVertdata, unsigned int *indices, int numIndices){
        glBindBuffer(GL_ARRAY_BUFFER, geoPtr->VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * numVertdata, data, GL_STREAM_DRAW);
        //glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STREAM_DRAW);
        //glNamedBufferData(VBO,sizeof(data),data,GL_STREAM_DRAW);
        //glNamedBufferStorage(VBO,sizeof(data),data, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geoPtr->EBO);
        glNamedBufferData(geoPtr->EBO,sizeof(unsigned int) * numIndices, indices , GL_STREAM_DRAW);
        glBindVertexArray(geoPtr->VAO);
        // Position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) 0);
        glEnableVertexAttribArray(0);
        // Cd
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
        // tex coords
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(2);
    
    }
    
    void init_ubo(){
        glGenBuffers(1, &UBO);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(GLuint64), NULL, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
        // define the range of the buffer that links to a uniform binding point
        glBindBufferRange(GL_UNIFORM_BUFFER, 0, UBO, 0, 2 * sizeof(GLuint64));
    }
    
    void initShader(){
        string vert_code =  readFile("shaders/bindless/surf.vert");
        string frag_code =  readFile("shaders/bindless/surf.frag");
    
        const char * vertexShaderSrc = vert_code.c_str();
        const char * fragShaderSrc = frag_code.c_str();
        // Compile shaders
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShader, 1, &vertexShaderSrc, nullptr);
        glCompileShader(vertexShader);
        CHECK_SHADER(vertexShader,"VERTEX");
    
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShader, 1, &fragShaderSrc, nullptr);
        glCompileShader(fragmentShader);
        CHECK_SHADER(vertexShader,"FRAGMENT");
    
        // Create shaderProgram and specify transform feedback variables
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexShader);
        glAttachShader(shaderProgram, fragmentShader);
    
        glLinkProgram(shaderProgram);
        glUseProgram(shaderProgram);
        CHECK_PROGRAM(shaderProgram);
    
        // no more need
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }
    
    void load_textures(TexPtr &tex01, TexPtr &tex02){
        tex01 = loadTexture("shaders/texs/container.jpg");
        tex02 = loadTexture("shaders/texs/ground.png");
    }
    
    void display(){
        // render
        // ------
        glUseProgram(shaderProgram);
        glDrawElements(GL_TRIANGLES,6, GL_UNSIGNED_INT, nullptr);
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y);
    void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    
    
    int main(){
    
    
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //glfwWindowHint(GLFW_VISIBLE,GL_FALSE);
        GLFWwindow * window = glfwCreateWindow(width,height,"Hello",NULL,NULL);
        glfwSetCursorPosCallback(window, cursor_pos_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwMakeContextCurrent(window);
        glewInit();
    
    
        cout << ">>initialize shaders
    ";
        initShader();
        float vertices[] = {
                // positions          // colors           // texture coords
                0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
                0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
                -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
                -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
    
        unsigned int indices[] = {
                0, 1, 3, // first triangle
                1, 2, 3  // second triangle
        };
        cout << ">>initialize geometry
    ";
        ElementGeoPtr geoPtr = MakeElementGeo();
        init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int));
    
        cout << ">>initialize to load textures
    ";
        TexPtr tex01;
        TexPtr tex02;
        load_textures(tex01, tex02);
    
    
        cout << ">>initialize the Uniform buffer objects
    ";
        init_ubo();
        unsigned int ubid = glGetUniformBlockIndex(shaderProgram, "alltex");
        cout << "get the blocks id :" << ubid << endl;
        struct samplers{
            GLuint64 tex[2];
        };
        samplers allSamplers{};
        allSamplers.tex[0] = tex01->handle;
        allSamplers.tex[1] = tex02->handle;
    
        glUniformBlockBinding(shaderProgram,    ubid, 0);
        glBindBuffer(GL_UNIFORM_BUFFER, UBO);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(allSamplers), allSamplers.tex);
    
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    
        //glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex0"), tex01->handle);
        //glUniformHandleui64ARB(glGetUniformLocation(shaderProgram,"tex1"), tex02->handle);
    
    
        auto t_prev = std::chrono::high_resolution_clock::now();
        while( !glfwWindowShouldClose( window ) ) {
            // Clear the screen to black
            glClearColor(0.2f, 0.2f, 0.2f, 0.2f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // Calculate delta time
            auto t_now = std::chrono::high_resolution_clock::now();
            float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_prev).count();
            t_prev = t_now;
    
            // Render content
            display();
    
            // then swap buffers
            glfwSwapBuffers(window);
            glfwPollEvents();
    
        }
    
        glfwTerminate();
        glfwDestroyWindow(window);
    
        return 0;
    }
    
    void cursor_pos_callback(GLFWwindow *w, double x, double y){
    
    }
    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);
    
    }
    全部代码main.cpp

    上面代码输出:

    >>initialize shaders
    >>initialize geometry
    >>initialize to load textures
    create texture :1
    create texture handle :4294969856
    create texture :2
    create texture handle :4294969857
    >>binding texture->1
    >>binding texture->2
    [ SYS::Texture Release Texture ]
    [ SYS::Texture Release Texture ]
    [ SYS::ElementGeo Release the geometry ]

    REF:

    OpenGL programming guide 9th

    https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/     For Uniform block object

    https://www.khronos.org/opengl/wiki/Bindless_Texture#Extension_implementation

    https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/

    http://www.steps3d.narod.ru/tutorials/bindless-tutorial.html

    http://cpp-rendering.io/opengl-azdo-bindless-textures/

  • 相关阅读:
    网络状态码含义——(比如204,304, 404, 504,502)
    Vue两个简易代替vuex的方法(eventBus,observable)
    单页面首屏加载慢解决方案
    前端监控和前端埋点
    ES5 和 ES6的继承
    mysql 隔离级别
    mysql 事务
    Seata
    Sentinel Dashboard 部署
    java 垃圾回器
  • 原文地址:https://www.cnblogs.com/gearslogy/p/13072817.html
Copyright © 2011-2022 走看看