几张图看明白VAOVBOEBO的关系和代码顺序

Posted guopinghai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了几张图看明白VAOVBOEBO的关系和代码顺序相关的知识,希望对你有一定的参考价值。

0.详细教程可看https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

1.可以简单地认为VAO的作用是这样的:

由于每渲染一次物体就要用一个VBO,而每次绑定一次VBO就要设置各个的顶点的属性,启动各个属性,代码十分复杂,复用性很差,因为每个物体的属性个数什么的都不一样(也就是说不是同构的),循环根本解决不了。所以就抽象出一层VAO来解决这个问题,相当于复用代码,使之简介快速。只在一开始将所有的VBO绑定对应的VAO就OK了,之后渲染的时候完全就可以绑定VAO,然后你就循环处理同构的VAO就好了。

2.其实EBO的作用也可以简单地理解为复用跟减少冗余,貌似还可以节约内存跟缓存:

否则的话VBO中储存大量的数据

3.VAO中存储着VBO的信息和EBO的信息

技术分享图片技术分享图片

所以正确的绑定顺序是VAO、VBO、EBO,将后两者的信息也绑定进VAO中去啊

技术分享图片

如果不适用VAO的话,那么最后一部分每次渲染都要设置第四部分的顶点属性,要好多行好多行,而用了VAO就一行绑定VAO就OK了啊,嘻嘻

4.创建相同的两个三角形,但对它们的数据使用不同的VAO和VBO:

技术分享图片
  1 #include <glad/glad.h>
  2 #include <GLFW/glfw3.h>
  3 
  4 #include <iostream>
  5 
  6 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  7 void processInput(GLFWwindow *window);
  8 
  9 // settings
 10 const unsigned int SCR_WIDTH = 800;
 11 const unsigned int SCR_HEIGHT = 600;
 12 
 13 const char *vertexShaderSource = "#version 330 core
"
 14     "layout (location = 0) in vec3 aPos;
"
 15     "void main()
"
 16     "{
"
 17     "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
"
 18     "}";
 19 const char *fragmentShaderSource = "#version 330 core
"
 20     "out vec4 FragColor;
"
 21     "void main()
"
 22     "{
"
 23     "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
"
 24     "}
";
 25 
 26 int main()
 27 {
 28     // glfw: initialize and configure
 29     // ------------------------------
 30     glfwInit();
 31     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
 32     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 33     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 34 
 35 #ifdef __APPLE__
 36     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
 37 #endif
 38 
 39     // glfw window creation
 40     // --------------------
 41     GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
 42     if (window == NULL)
 43     {
 44         std::cout << "Failed to create GLFW window" << std::endl;
 45         glfwTerminate();
 46         return -1;
 47     }
 48     glfwMakeContextCurrent(window);
 49     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 50 
 51     // glad: load all OpenGL function pointers
 52     // ---------------------------------------
 53     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
 54     {
 55         std::cout << "Failed to initialize GLAD" << std::endl;
 56         return -1;
 57     }
 58 
 59 
 60     // build and compile our shader program
 61     // ------------------------------------
 62     // vertex shader
 63     int vertexShader = glCreateShader(GL_VERTEX_SHADER);
 64     glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
 65     glCompileShader(vertexShader);
 66     // check for shader compile errors
 67     int success;
 68     char infoLog[512];
 69     glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
 70     if (!success)
 71     {
 72         glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
 73         std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << std::endl;
 74     }
 75     // fragment shader
 76     int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 77     glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
 78     glCompileShader(fragmentShader);
 79     // check for shader compile errors
 80     glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
 81     if (!success)
 82     {
 83         glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
 84         std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << std::endl;
 85     }
 86     // link shaders
 87     int shaderProgram = glCreateProgram();
 88     glAttachShader(shaderProgram, vertexShader);
 89     glAttachShader(shaderProgram, fragmentShader);
 90     glLinkProgram(shaderProgram);
 91     // check for linking errors
 92     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
 93     if (!success) {
 94         glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
 95         std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << std::endl;
 96     }
 97     glDeleteShader(vertexShader);
 98     glDeleteShader(fragmentShader);
 99 
100     // set up vertex data (and buffer(s)) and configure vertex attributes
101     // ------------------------------------------------------------------
102     float firstTriangle[] = {
103         -0.9f, -0.5f, 0.0f,  // left 
104         -0.0f, -0.5f, 0.0f,  // right
105         -0.45f, 0.5f, 0.0f,  // top 
106     };
107     float secondTriangle[] = {
108         0.0f, -0.5f, 0.0f,  // left
109         0.9f, -0.5f, 0.0f,  // right
110         0.45f, 0.5f, 0.0f   // top 
111     };
112     unsigned int VBOs[2], VAOs[2];
113     glGenVertexArrays(2, VAOs); // we can also generate multiple VAOs or buffers at the same time
114     glGenBuffers(2, VBOs);
115     // first triangle setup
116     // --------------------
117     glBindVertexArray(VAOs[0]);
118     glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
119     glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
120     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);    // Vertex attributes stay the same
121     glEnableVertexAttribArray(0);
122     // glBindVertexArray(0); // no need to unbind at all as we directly bind a different VAO the next few lines
123     // second triangle setup
124     // ---------------------
125     glBindVertexArray(VAOs[1]);    // note that we bind to a different VAO now
126     glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);    // and a different VBO
127     glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
128     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); // because the vertex data is tightly packed we can also specify 0 as the vertex attribute‘s stride to let OpenGL figure it out
129     glEnableVertexAttribArray(0);
130     // glBindVertexArray(0); // not really necessary as well, but beware of calls that could affect VAOs while this one is bound (like binding element buffer objects, or enabling/disabling vertex attributes)
131 
132 
133     // uncomment this call to draw in wireframe polygons.
134     //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
135 
136     // render loop
137     // -----------
138     while (!glfwWindowShouldClose(window))
139     {
140         // input
141         // -----
142         processInput(window);
143 
144         // render
145         // ------
146         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
147         glClear(GL_COLOR_BUFFER_BIT);
148 
149         glUseProgram(shaderProgram);
150         // draw first triangle using the data from the first VAO
151         glBindVertexArray(VAOs[0]);
152         glDrawArrays(GL_TRIANGLES, 0, 3);
153         // then we draw the second triangle using the data from the second VAO
154         glBindVertexArray(VAOs[1]);
155         glDrawArrays(GL_TRIANGLES, 0, 3);
156  
157         // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
158         // -------------------------------------------------------------------------------
159         glfwSwapBuffers(window);
160         glfwPollEvents();
161     }
162 
163     // optional: de-allocate all resources once they‘ve outlived their purpose:
164     // ------------------------------------------------------------------------
165     glDeleteVertexArrays(2, VAOs);
166     glDeleteBuffers(2, VBOs);
167 
168     // glfw: terminate, clearing all previously allocated GLFW resources.
169     // ------------------------------------------------------------------
170     glfwTerminate();
171     return 0;
172 }
173 
174 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
175 // ---------------------------------------------------------------------------------------------------------
176 void processInput(GLFWwindow *window)
177 {
178     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
179         glfwSetWindowShouldClose(window, true);
180 }
181 
182 // glfw: whenever the window size changed (by OS or user resize) this callback function executes
183 // ---------------------------------------------------------------------------------------------
184 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
185 {
186     // make sure the viewport matches the new window dimensions; note that width and 
187     // height will be significantly larger than specified on retina displays.
188     glViewport(0, 0, width, height);
189 }
View Code

 

以上是关于几张图看明白VAOVBOEBO的关系和代码顺序的主要内容,如果未能解决你的问题,请参考以下文章

几张图看懂区块链技术到底是什么?

一张图看明白云计算数据中心总体分层架构

一张图看明白 Android Handler 消息机制

一张图看明白云计算架构核心竞争力

一张图看懂Function和Object的关系及简述instanceof运算符

3张图看懂分布式架构与微服务架构的关系