# 02_hello_triangle **Repository Path**: open-gl_3/02_hello_triangle ## Basic Information - **Project Name**: 02_hello_triangle - **Description**: Demostration 2: 使用OpenGL画一个三角形。涉及到的概念:VBO, VAO。GLSL代码加载,Vertex Shader, Fragment Shader(片段着色器),shader program(着色器程序)。 - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-05-10 - **Last Updated**: 2024-06-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # README 官方教程:[Getting started](https://www.glfw.org/docs/latest/quick.html) ## 0. 哔哩哔哩视频教程 - [大名鼎鼎的Learn OpenGL的视频教程](https://www.bilibili.com/video/BV1Sv411g7pp/) ## 1. 说明 `OpenGL`练习项目代码,学习`VBO`,`VAO`,`Shader`,编写GLSL着色器代码,绘制三角形。练习教程章节链接[你好,三角形](https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/)。 ## 2. 笔记: VBO, EBO, VAO 之间的关系 `VBO` 和 `EBO` 的作用是在 `GPU` 显存中开辟一块存储空间来缓存顶点数据或者图元索引数据,避免每次绘制时 `CPU` 内存到 `GPU` 显存的数据拷贝,从而提升渲染性能。 `VAO(Vertex Array Object)`,主要作用是用于管理 `VBO` 或 `EBO`,减少 `glBindBuffer`、`glEnableVertexAttribArray`、`glVertexAttribPointer` 这些调用操作,高效地实现在顶点数组配置之间切换。 `VAO` 记录的是: 1. `vertex attribute` 的格式,由 `glVertexAttribPointer` 设置。 2. `vertex attribute` 对应的 `VBO` 的名字, 由一对 `glBindBuffer` 和 `glVertexAttribPointer` 设置。 3. **当前**绑定的 `GL_ELEMENT_ARRAY_BUFFER` 的名字,由 `glBindBuffer` 设置。 当你打算绘制多个物体时,你首先要生成/配置所有的 `VAO`(和必须的 `VBO` 及属性指针),然后储存它们供后面使用。当我们打算绘制物体的时候就拿出相应的 `VAO`,绑定它,绘制完物体后,再解绑 `VAO`。 ### 2.1 VBO, EBO, VAO 内存布局关系 通过看内存布局,更清楚具体的看到 `VBO` 和 `EBO` 与 `VAO` 的关系: 1. VAO 只管理 VBO 时,布局格式 ![VBO, EBO, VAO 内存布局关系](notes/image/vertex_array_objects.webp) 2. VAO 管理 VBO 和 EBO 时,布局格式 ![VBO, EBO, VAO 内存布局关系](notes/image/vertex_array_objects_ebo.webp) ### 2.2 VAO 管理 VBO,EBO 时,初始化及循环绘制代码样例 ```cpp // ..:: 初始化代码 :: .. // 1. 绑定顶点数组对象 glBindVertexArray(VAO); // 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 3. 设定顶点属性指针 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 4. 解绑VAO(不是EBO!) glBindVertexArray(0); // [...] // ..:: 绘制代码(游戏循环中) :: .. glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0) glBindVertexArray(0); ``` ## 3. 一些笔记 ### 3.1 glDrawArrays 函数说明 ![glDrawArrays](notes/image/glDrawArrays.png) 参数 `count` 指绘制的顶点个数,例如如果`vertices`数字定义的三角形有6个顶点,则`count`为6。 ### 3.2 glVertexAttribPointer 函数说明 ![glVertexAttribPointer](notes/image/glVertexAttribPointer.png) 这里的参数 `size` 指定顶点属性的大小(即GLSL中的`vec3`,最大只有`vec4`),在该 Demo 中,顶点属性是一个vec3,它由3个值组成,所以大小是3。 ## 4. Demo 代码说明 1. `src/main.cc`: 演示基本的 OpenGL 绘制流程,包括创建窗口、编译着色器、创建 `VBO`、`VAO`、`EBO`、绑定 `VAO`、绘制、解绑 `VAO`。 2. `src/2triangles/main.cc`:演示定义两个`vertices`三角形,并绘制(两个`VAO`/`VBO`)。 3. `src/IBO/main.cc`:演示使用`IBO`索引绘制流程(一个简化的`vertices`,一个`indices`,一个`VAO`/`VBO`/`EBO`)。 4. `src/2triangles_2shaders/main.cc`:演示使用两个着色器绘制两个`vertices`三角形(两个`vertices`,两个`VAO`/`VBO`,两个fragment shader,两个GLSL program)。 ## 5. 笔记参考 - [VAO和EBO解绑定的坑?](https://www.zhihu.com/question/39082624) - [一看就懂的 OpenGL 基础概念(3):各种 O 之 VBO、EBO、VAO丨音视频基础](https://zhuanlan.zhihu.com/p/585126881) - [NDK OpenGLES3.0 开发(四):VBO、EBO 和 VAO](https://mp.weixin.qq.com/s/phSSa-2SoiSZqxKBo5SWGg)