几张图看明白VAO、VBO、EBO的关系和代码顺序

几张图看明白VAO、VBO、EBO的关系和代码顺序0.详细教程可看https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 1.可以简单地认为VAO的作用是这样的: 由于每渲染一次物体就要用一个VBO,而每次绑定一次VBO就要设置各个的顶点的属性,启

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、VBO、EBO的关系和代码顺序

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

几张图看明白VAO、VBO、EBO的关系和代码顺序

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

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

几张图看明白VAO、VBO、EBO的关系和代码顺序
几张图看明白VAO、VBO、EBO的关系和代码顺序

  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

 

今天的文章几张图看明白VAO、VBO、EBO的关系和代码顺序分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/56269.html

(0)
编程小号编程小号
上一篇 2023-08-26
下一篇 2023-08-26

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注