幾張圖看明白VAO、VBO、EBO的關係和代碼順序

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

1.能夠簡單地認爲VAO的做用是這樣的:ios

因爲每渲染一次物體就要用一個VBO,而每次綁定一次VBO就要設置各個的頂點的屬性,啓動各個屬性,代碼十分複雜,複用性不好,由於每一個物體的屬性個數什麼的都不同(也就是說不是同構的),循環根本解決不了。因此就抽象出一層VAO來解決這個問題,至關於複用代碼,使之簡介快速。只在一開始將全部的VBO綁定對應的VAO就OK了,以後渲染的時候徹底就能夠綁定VAO,而後你就循環處理同構的VAO就行了。git

2.其實EBO的做用也能夠簡單地理解爲複用跟減小冗餘,貌似還能夠節約內存跟緩存:github

不然的話VBO中儲存大量的數據緩存

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

因此正確的綁定順序是VAO、VBO、EBO,將後二者的信息也綁定進VAO中去啊oop

若是不適用VAO的話,那麼最後一部分每次渲染都要設置第四部分的頂點屬性,要好多行好多行,而用了VAO就一行綁定VAO就OK了啊,嘻嘻ui

4.建立相同的兩個三角形,但對它們的數據使用不一樣的VAO和VBO:this

 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\n"
 14     "layout (location = 0) in vec3 aPos;\n"
 15     "void main()\n"
 16     "{\n"
 17     " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
 18     "}\0";  19 const char *fragmentShaderSource = "#version 330 core\n"
 20     "out vec4 FragColor;\n"
 21     "void main()\n"
 22     "{\n"
 23     " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
 24     "}\n\0";  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\n" << 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\n" << 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\n" << 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
相關文章
相關標籤/搜索