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 << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << 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 << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; } } } #endif //TRIANGLE_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 ]\n"; 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\n"; } 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
// // 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 ] \n "; 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
// // 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
#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\n"; 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\n"; ElementGeoPtr geoPtr = MakeElementGeo(); init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int)); cout << ">>initialize to load textures\n"; 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); }
关键代码就是:
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\n"; 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\n"; ElementGeoPtr geoPtr = MakeElementGeo(); init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int)); cout << ">>initialize to load textures\n"; TexPtr tex01; TexPtr tex02; load_textures(tex01, tex02); /* cout << ">>initialize the Uniform buffer objects\n"; 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); }
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\n"; 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\n"; ElementGeoPtr geoPtr = MakeElementGeo(); init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int)); cout << ">>initialize to load textures\n"; TexPtr tex01; TexPtr tex02; load_textures(tex01, tex02); cout << ">>initialize the Uniform buffer objects\n"; 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); }
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\n"; 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\n"; 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\n"; ElementGeoPtr geoPtr = MakeElementGeo(); init_geo(geoPtr, vertices, sizeof(vertices) / sizeof(float) , indices, sizeof(indices) / sizeof(unsigned int)); cout << ">>initialize to load textures\n"; TexPtr tex01; TexPtr tex02; load_textures(tex01, tex02); cout << ">>initialize the Uniform buffer objects\n"; 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); }
上面代码输出:
>>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
posted on 2020-06-09 15:13 gearslogy 阅读(1861) 评论(0) 编辑 收藏 举报