高级OPENGL, 利用uniform块接口

Posted hi3254014978

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级OPENGL, 利用uniform块接口相关的知识,希望对你有一定的参考价值。

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://learnopengl-cn.github.io/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/

以上是关于高级OPENGL, 利用uniform块接口的主要内容,如果未能解决你的问题,请参考以下文章

(Python OpenGL)Uniform变量 PyOpenGL

转载OpenGL ES 三种类型修饰 uniform attribute varying

OpenGL 从入门到成魔-第6章- Uniform 变量的使用

OpenGL ES 学习教程(十七) Unity GPU Instance 原理及 GLES 实现

openGL之API学习(一七六)GLSL变量类型uniform attribute varying in out

OpenGL ES 学习教程(十七) Unity GPU Instance 原理及 GLES 实现