1.找到需要的uniform块的索引, 将程序对象的该uniform块索引绑定uniform 缓冲对象的绑定点
2.建立uniform缓冲对象,对象绑定GL_UNIFORM_BUFFER缓冲目标,为缓冲分配内存,将缓冲对象绑定到特定的绑定点,定义绑定点的缓冲范围
3.在渲染循环外绑定uniform块内不需更新的uniform,在渲染循环内绑定uniform块中需要更新的uniform
4.按正常思维,在渲染循环外或内,绑定不再uniform块中的uniform
下面是一个例子,将四个立方体平移到窗口的4个角,每个立方体显示不同的颜色
1 //输入变量gl_FragCoord能让我们读取当前片段的窗口空间坐标,并获取它的深度值,但是它是一个只读(Read-only)变量。 2 3 4 #define GLEW_STATIC 5 6 #include <GL/glew.h> 7 8 #include <GLFW/glfw3.h> 9 #define STB_IMAGE_IMPLEMENTATION 10 #include "stb_image.h" 11 12 #include <glm/glm.hpp> 13 #include <glm/gtc/matrix_transform.hpp> 14 #include <glm/gtc/type_ptr.hpp> 15 16 #include "Shader.h" 17 #include "camera.h" 18 //#include "Model.h" 19 #include <fstream> 20 #include <iostream> 21 using namespace std; 22 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 23 void mouse_callback(GLFWwindow* window, double xpos, double ypos); 24 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 25 void processInput(GLFWwindow *window); 26 unsigned int loadTexture(const char *path); 27 28 // settings 29 const unsigned int SCR_WIDTH = 800; 30 const unsigned int SCR_HEIGHT = 600; 31 32 // camera 33 Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 34 float lastX = (float)SCR_WIDTH / 2.0; 35 float lastY = (float)SCR_HEIGHT / 2.0; 36 bool firstMouse = true; 37 38 // timing 39 float deltaTime = 0.0f; 40 float lastFrame = 0.0f; 41 42 int main() 43 { 44 // glfw: initialize and configure 45 // ------------------------------ 46 glfwInit(); 47 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 48 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 49 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 50 51 #ifdef __APPLE__ 52 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X 53 #endif 54 55 // glfw window creation 56 // -------------------- 57 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 58 if (window == NULL) 59 { 60 std::cout << "Failed to create GLFW window" << std::endl; 61 glfwTerminate(); 62 return -1; 63 } 64 glfwMakeContextCurrent(window); 65 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 66 glfwSetCursorPosCallback(window, mouse_callback); 67 glfwSetScrollCallback(window, scroll_callback); 68 69 // tell GLFW to capture our mouse 70 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 71 72 // glad: load all OpenGL function pointers 73 // --------------------------------------- 74 glewExperimental = GL_TRUE; 75 if (glewInit() != GLEW_OK) 76 { 77 cout << "Failed to initialize GLEW!" << endl; 78 return -1; 79 } 80 // configure global opengl state 81 // ----------------------------- 82 glEnable(GL_DEPTH_TEST); 83 glDepthFunc(GL_LESS); 84 85 86 87 // build and compile shaders 88 // ------------------------- 89 Shader shaderRed("E:\\C++\\High_level_GLSL\\1.7ver1.txt", "E:\\C++\\High_level_GLSL\\1.7frag1.txt"); 90 Shader shaderGreen("E:\\C++\\High_level_GLSL\\1.7ver1.txt", "E:\\C++\\High_level_GLSL\\1.7frag2.txt"); 91 Shader shaderBlue("E:\\C++\\High_level_GLSL\\1.7ver1.txt", "E:\\C++\\High_level_GLSL\\1.7frag3.txt"); 92 Shader shaderYellow("E:\\C++\\High_level_GLSL\\1.7ver1.txt", "E:\\C++\\High_level_GLSL\\1.7frag4.txt"); 93 94 // set up vertex data (and buffer(s)) and configure vertex attributes 95 // ------------------------------------------------------------------ 96 float cubeVertices[] = { 97 98 // positions // texture Coords 99 -0.5f, -0.5f, -0.5f, 100 0.5f, -0.5f, -0.5f, 101 0.5f, 0.5f, -0.5f, 102 0.5f, 0.5f, -0.5f, 103 -0.5f, 0.5f, -0.5f, 104 -0.5f, -0.5f, -0.5f, 105 106 -0.5f, -0.5f, 0.5f, 107 0.5f, -0.5f, 0.5f, 108 0.5f, 0.5f, 0.5f, 109 0.5f, 0.5f, 0.5f, 110 -0.5f, 0.5f, 0.5f, 111 -0.5f, -0.5f, 0.5f, 112 113 -0.5f, 0.5f, 0.5f, 114 -0.5f, 0.5f, -0.5f, 115 -0.5f, -0.5f, -0.5f, 116 -0.5f, -0.5f, -0.5f, 117 -0.5f, -0.5f, 0.5f, 118 -0.5f, 0.5f, 0.5f, 119 120 0.5f, 0.5f, 0.5f, 121 0.5f, 0.5f, -0.5f, 122 0.5f, -0.5f, -0.5f, 123 0.5f, -0.5f, -0.5f, 124 0.5f, -0.5f, 0.5f, 125 0.5f, 0.5f, 0.5f, 126 127 -0.5f, -0.5f, -0.5f, 128 0.5f, -0.5f, -0.5f, 129 0.5f, -0.5f, 0.5f, 130 0.5f, -0.5f, 0.5f, 131 -0.5f, -0.5f, 0.5f, 132 -0.5f, -0.5f, -0.5f, 133 134 -0.5f, 0.5f, -0.5f, 135 0.5f, 0.5f, -0.5f, 136 0.5f, 0.5f, 0.5f, 137 0.5f, 0.5f, 0.5f, 138 -0.5f, 0.5f, 0.5f, 139 -0.5f, 0.5f, -0.5f 140 }; 141 142 float TexVertices[] = { 143 144 // positions // texture Coords 145 0.0f, 0.0f, 146 1.0f, 0.0f, 147 1.0f, 1.0f, 148 1.0f, 1.0f, 149 0.0f, 1.0f, 150 0.0f, 0.0f, 151 152 0.0f, 0.0f, 153 1.0f, 0.0f, 154 1.0f, 1.0f, 155 1.0f, 1.0f, 156 0.0f, 1.0f, 157 0.0f, 0.0f, 158 159 1.0f, 0.0f, 160 1.0f, 1.0f, 161 0.0f, 1.0f, 162 0.0f, 1.0f, 163 0.0f, 0.0f, 164 1.0f, 0.0f, 165 166 1.0f, 0.0f, 167 1.0f, 1.0f, 168 0.0f, 1.0f, 169 0.0f, 1.0f, 170 0.0f, 0.0f, 171 1.0f, 0.0f, 172 173 0.0f, 1.0f, 174 1.0f, 1.0f, 175 1.0f, 0.0f, 176 1.0f, 0.0f, 177 0.0f, 0.0f, 178 0.0f, 1.0f, 179 180 0.0f, 1.0f, 181 1.0f, 1.0f, 182 1.0f, 0.0f, 183 1.0f, 0.0f, 184 0.0f, 0.0f, 185 0.0f, 1.0f 186 }; 187 188 189 // cube VAO 190 unsigned int cubeVAO, cubeVBO; 191 glGenVertexArrays(1, &cubeVAO); 192 glGenBuffers(1, &cubeVBO); 193 glBindVertexArray(cubeVAO); 194 glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); 195 glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), NULL, GL_STATIC_DRAW); 196 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cubeVertices), &cubeVertices); 197 glEnableVertexAttribArray(0); 198 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); 199 glBindVertexArray(0); 200 201 //first ,we get the relevant block indices 202 unsigned int uniformBlockIndexRed = glGetUniformBlockIndex(shaderRed.ID, "Matrices"); 203 unsigned int uniformBlockIndexGreen = glGetUniformBlockIndex(shaderGreen.ID, "Matrices"); 204 unsigned int uniformBlockIndexBlue = glGetUniformBlockIndex(shaderBlue.ID, "Matrices"); 205 unsigned int uniformBlockIndexYellow = glGetUniformBlockIndex(shaderYellow.ID, "Matrices"); 206 207 //then we link each uniform block to this uniform binding point 208 glUniformBlockBinding(shaderRed.ID, uniformBlockIndexRed, 0); 209 glUniformBlockBinding(shaderGreen.ID, uniformBlockIndexGreen, 0); 210 glUniformBlockBinding(shaderBlue.ID, uniformBlockIndexBlue, 0); 211 glUniformBlockBinding(shaderYellow.ID, uniformBlockIndexYellow, 0); 212 213 //Now actually create the buffer 214 unsigned int uboMatrices; 215 glGenBuffers(1, &uboMatrices); 216 glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); 217 glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW); 218 glBindBuffer(GL_UNIFORM_BUFFER, 0); 219 //define the range of the buffer that links to a uniform binging point 220 glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4)); 221 222 //store the projection matrix (we only do this once now)(note: we're not using Zoom anymore by changeing the FOV) 223 glm::mat4 projection = glm::perspective(45.0f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); 224 glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); 225 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection)); 226 glBindBuffer(GL_UNIFORM_BUFFER, 0); 227 228 //unsigned int frontTexture = loadTexture("greenWall.jpg"); 229 //unsigned int backTexture = loadTexture("greenWall.jpg"); 230 231 //shader.use(); 232 //shader.setInt("frontTexture", 0); 233 ////shader.setInt("backTexture", backTexture); 234 //glUniform1i(glGetUniformLocation(shader.ID, "frontTexture"), 1); 235 236 ////创建一个uniform缓冲对象 237 //unsigned int uboExampleBlock; 238 //glGenBuffers(1, &uboExampleBlock); 239 //glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock); 240 //glBufferData(GL_UNIFORM_BUFFER, 152, NULL, GL_STATIC_DRAW); //分配152字节的缓冲内存 241 //glBindBuffer(GL_UNIFORM_BUFFER, 0); 242 ////为了将Uniform块绑定到一个特定的绑定点中,我们需要调用glUniformBlockBinding函数, 243 ////它的第一个参数是一个程序对象,之后是一个Uniform块索引和链接到的绑定点, 244 ////Uniform块索引(uniform bloack index )是着色器中已定义Uniform块的位置值索引,这可以通过调用glGetUniformBlockIndex来获取 245 ////它接受一个程序对象和uniform块的名称 246 //unsigned int lights_index = glGetUniformBlockIndex(shader.ID, "Light"); 247 //glUniformBlockBinding(shader.ID, lights_index, 2); 248 // 249 ////接下来,我们还需要绑定Uniform缓冲对象到相同的绑定点上,这可以使用glBindBufferBase或glBindBufferRange来完成 250 //glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboExampleBlock); //该函数需要一个目标,一个绑定点索引和一个uniform缓冲对象作为它的参数 251 ////glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152); 252 253 ////向uniform缓冲中添加数据 254 //glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock); 255 //int b = true; //GLSL中的bool是4字节的,所以我们将它存为一个integer 256 //glBufferSubData(GL_UNIFORM_BUFFER, 144, 4, &b); 257 //glBindBuffer(GL_UNIFORM_BUFFER, 0); 258 259 // render loop 260 // ----------- 261 while (!glfwWindowShouldClose(window)) 262 { 263 // per-frame time logic 264 // -------------------- 265 float currentFrame = glfwGetTime(); 266 deltaTime = currentFrame - lastFrame; 267 lastFrame = currentFrame; 268 269 processInput(window); 270 271 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 272 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // don't forget to clear the stencil buffer! 273 274 //set the view and projection matrix in the uniform block 275 glm::mat4 view = camera.GetViewMatrix(); 276 glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices); 277 glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view)); 278 glBindBuffer(GL_UNIFORM_BUFFER, 0); 279 280 //draw 4 cubes 281 //RED 282 glBindVertexArray(cubeVAO); 283 shaderRed.use(); 284 glm::mat4 model; 285 model = glm::translate(model, glm::vec3(-0.75f, 0.75f, 0.0f)); //move top-left 286 shaderRed.setMat4("model", model); 287 glDrawArrays(GL_TRIANGLES, 0, 36); 288 289 //GREEN 290 shaderGreen.use(); 291 model = glm::mat4(); 292 model = glm::translate(model, glm::vec3(0.75f, 0.75f, 0.0f)); //move top-right 293 shaderGreen.setMat4("model", model); 294 glDrawArrays(GL_TRIANGLES, 0, 36); 295 296 shaderYellow.use(); 297 model = glm::mat4(); 298 model = glm::translate(model, glm::vec3(-0.75f, -0.75f, 0.0f)); //move bottom-left 299 shaderYellow.setMat4("model", model); 300 glDrawArrays(GL_TRIANGLES, 0, 36); 301 302 shaderBlue.use(); 303 model = glm::mat4(); 304 model = glm::translate(model, glm::vec3(0.75f, -0.75f, 0.0f)); //move bottom-right 305 shaderBlue.setMat4("model", model); 306 glDrawArrays(GL_TRIANGLES, 0, 36); 307 308 309 glfwSwapBuffers(window); 310 glfwPollEvents(); 311 } 312 313 // optional: de-allocate all resources once they've outlived their purpose: 314 // ------------------------------------------------------------------------ 315 glDeleteVertexArrays(1, &cubeVAO); 316 317 glDeleteBuffers(1, &cubeVBO); 318 319 320 glfwTerminate(); 321 return 0; 322 } 323 324 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly 325 // --------------------------------------------------------------------------------------------------------- 326 void processInput(GLFWwindow *window) 327 { 328 if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS) 329 glfwSetWindowShouldClose(window, true); 330 331 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 332 camera.ProcessKeyboard(FORWARD, deltaTime); 333 if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 334 camera.ProcessKeyboard(BACKWARD, deltaTime); 335 if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 336 camera.ProcessKeyboard(LEFT, deltaTime); 337 if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 338 camera.ProcessKeyboard(RIGHT, deltaTime); 339 } 340 341 // glfw: whenever the window size changed (by OS or user resize) this callback function executes 342 // --------------------------------------------------------------------------------------------- 343 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 344 { 345 // make sure the viewport matches the new window dimensions; note that width and 346 // height will be significantly larger than specified on retina displays. 347 glViewport(0, 0, width, height); 348 } 349 350 // glfw: whenever the mouse moves, this callback is called 351 // ------------------------------------------------------- 352 void mouse_callback(GLFWwindow* window, double xpos, double ypos) 353 { 354 if (firstMouse) 355 { 356 lastX = xpos; 357 lastY = ypos; 358 firstMouse = false; 359 } 360 361 float xoffset = xpos - lastX; 362 float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top 363 364 lastX = xpos; 365 lastY = ypos; 366 367 368 369 370 camera.ProcessMouseMovement(xoffset, yoffset); 371 } 372 373 // glfw: whenever the mouse scroll wheel scrolls, this callback is called 374 // ---------------------------------------------------------------------- 375 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) 376 { 377 camera.ProcessMouseScroll(yoffset); 378 } 379 380 // utility function for loading a 2D texture from file 381 // --------------------------------------------------- 382 unsigned int loadTexture(char const * path) 383 { 384 unsigned int textureID; 385 glGenTextures(1, &textureID); 386 387 int width, height, nrComponents; 388 unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); 389 if (data) 390 { 391 GLenum format; 392 if (nrComponents == 1) 393 format = GL_RED; 394 else if (nrComponents == 3) 395 format = GL_RGB; 396 else if (nrComponents == 4) 397 format = GL_RGBA; 398 399 glBindTexture(GL_TEXTURE_2D, textureID); 400 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); 401 glGenerateMipmap(GL_TEXTURE_2D); 402 403 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 405 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 406 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 407 408 stbi_image_free(data); 409 } 410 else 411 { 412 std::cout << "Texture failed to load at path: " << path << std::endl; 413 stbi_image_free(data); 414 } 415 416 return textureID; 417 }