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 }
![](https://i-blog.csdnimg.cn/blog_migrate/9327fc0d59a0d48a62b892f3a392204f.jpeg)
学习网址:https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/