# mygl **Repository Path**: arthur1906/mygl ## Basic Information - **Project Name**: mygl - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-16 - **Last Updated**: 2025-09-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MyGL - 现代OpenGL核心概念学习指南 本项目是学习现代OpenGL核心概念的实践代码与笔记总结。旨在提供一份从零开始、结构清晰、内容全面的入门指南。 ## 目录 - [1. 如何编译与运行](#1-如何编译与运行) - [2. 文件功能概览](#2-文件功能概览) - [3. 整体架构图 (Mermaid)](#3-整体架构图-mermaid) - [4. 核心概念:渲染的基石](#4-核心概念渲染的基石) - [4.1. 项目的“脚手架”:GLFW & GLAD](#41-项目的脚手架glfw--glad) - [4.2. 数据与状态:VBO, VAO, EBO](#42-数据与状态vbo-vao-ebo) - [4.3. 可编程管线:着色器 (Shaders)](#43-可编程管线着色器-shaders) - [4.4. 纹理 (Textures)](#44-纹理-textures) - [5. 实践:渲染循环与状态机](#5-实践渲染循环与状态机) - [5.1. 渲染循环 (Render Loop)](#51-渲染循环-render-loop) - [5.2. OpenGL作为“状态机”](#52-opengl作为状态机) - [6. 资源管理](#6-资源管理) - [7. 后续学习方向](#7-后续学习方向) ## 1. 如何编译与运行 本项目使用 CMake 进行构建。请确保您已安装了兼容的C++编译器(如 Visual Studio, GCC, Clang)和 CMake。 ```bash # 1. 在项目根目录创建一个build文件夹并进入 mkdir build cd build # 2. 运行CMake来配置项目 cmake .. # 3. 编译项目 # 在Windows (Visual Studio)上 cmake --build . # 在Linux/macOS上 make ``` 编译成功后,可执行文件(如 `day1.exe`, `texture.exe`)会生成在 `build/Debug` 或 `build` 目录下。 ## 2. 文件功能概览 - **`CMakeLists.txt`**: 项目的构建脚本,管理所有源文件和库依赖。 - **`day1.cpp` / `day2.cpp` / `day3.cpp`**: 早期学习阶段的代码,演示了绘制三角形、使用不同着色器等基础知识。 - **`texture.cpp`**: 核心示例代码,演示了如何加载并应用纹理。 - **`shader_s.h`**: 一个轻量级的着色器封装类,简化了从文件加载、编译和链接着色器程序的过程。 - **`stb_image.h`**: 一个流行的单头文件图像加载库,用于从文件中读取PNG, JPG等格式的图片。 - **`/assets`**: 存放着色器文件 (`.vs`, `.fs`) 和图片资源 (`.png`)。 - **`/include`**: 存放项目依赖的头文件和库文件(GLAD, GLFW)。 ## 3. 整体架构图 (Mermaid) 下图展示了本示例程序(以`texture.cpp`为例)中,各个模块之间的数据流和依赖关系。 ```mermaid graph TD subgraph "用户与操作系统" A[用户输入/窗口事件] end subgraph "应用程序 (CPU)" B(texture.cpp) C(shader_s.h) D(stb_image.h) E[assets/login.png] F[assets/vetexShader.vs] G[assets/fragShader.fs] end subgraph "核心库" H[GLFW] I[GLAD] end subgraph "渲染管线 (GPU)" J[顶点着色器] K[片段着色器] L[纹理对象] end A --> H H --> B B -- 使用 --> I B -- 使用 --> C B -- 使用 --> D D -- 加载 --> E C -- 加载 --> F C -- 加载 --> G B -- 上传数据到 --> L[纹理对象] B -- 上传程序到 --> J B -- 上传程序到 --> K I -- 调用OpenGL指令驱动 --> J I -- 调用OpenGL指令驱动 --> K I -- 调用OpenGL指令驱动 --> L J --> K K -- 采样 --> L ``` ## 4. 核心概念:渲染的基石 ### 4.1. 项目的“脚手架”:GLFW & GLAD - **GLFW**: 一个辅助库,提供了创建窗口、处理用户输入(键盘、鼠标)、管理OpenGL上下文等我们与操作系统交互所需的功能。 - **GLAD**: 一个函数加载库。OpenGL本身只是一个规范,具体的函数(如`glGenBuffers`)由显卡驱动实现。GLAD在运行时为我们获取这些函数的地址,让我们能正常调用它们。 ### 4.2. 数据与状态:VBO, VAO, EBO 这是现代OpenGL最关键的概念。**VBO存数据,VAO存状态,EBO存索引**。 - **VBO (Vertex Buffer Object)**: **数据仓库**。它是在GPU显存中开辟的内存,用于存储所有顶点数据(位置、颜色、纹理坐标等)。 - **VAO (Vertex Array Object)**: **状态记录本**。它不存数据,而是存储“如何解释和使用VBO数据”的**所有配置**。这包括: - `glVertexAttribPointer`的设置(即数据格式、步长、偏移)。 - `glEnableVertexAttribArray`的启用状态。 - 它还记录了与EBO的绑定关系。 - **EBO (Element Buffer Object / IBO)**: **索引仓库**。用于存储顶点的**索引**,告诉GPU按什么顺序去VBO中取顶点来组成图形。这能有效减少顶点数据的重复,节省显存。 **要点**:VAO的价值在于,你只需在初始化时配置好一次,之后在渲染时仅需`glBindVertexArray(vao_id)`就可以**一键恢复所有顶点数据的解释方式**,极大简化了渲染逻辑。 ### 4.3. 可编程管线:着色器 (Shaders) 着色器是运行在GPU上的迷你程序,让我们能精确控制渲染的核心步骤。 - **顶点着色器 (Vertex Shader)**:对每个顶点运行一次,决定**“画在哪”**(例如,进行模型变换、坐标投影)。 - **片段着色器 (Fragment Shader)**:对每个像素大小的片段运行一次,决定**“画成什么颜色”**(例如,进行纹理采样、光照计算)。 - **着色器程序 (Shader Program)**:将顶点和片段着色器链接起来,形成一套完整的渲染方案。 ### 4.4. 纹理 (Textures) 纹理是贴在模型表面的2D图片,用以增加视觉细节。 > 下文使用“给模型贴贴纸”的比喻来解释相关概念。 - **纹理 (Texture)**: **“贴纸”**本身。是存储在GPU上的一张图片。 - **纹理坐标 (UV Coordinate)**: **“说明书”**。定义了模型上的点如何对应到贴纸上的点。 - **纹理像素 (Texel)**: **“墨水点”**。贴纸图片上的一个最小颜色单元。 - **纹理单元 (Texture Unit)**: **“卡槽”**。GPU上可以同时放置多张贴纸(纹理)的硬件位置。 - **采样器 (Sampler)**: **“取色工具”**。着色器中用来从指定卡槽的贴纸上读取颜色的工具。 **工作流程**: 1. **加载**: 把图片文件加载成一个纹理对象。 2. **绑定**: 把纹理对象放入一个空闲的**纹理单元**(卡槽)。 3. **链接**: 告诉**采样器**(取色工具)它应该从哪个编号的纹理单元去取色。 4. **采样**: 在片段着色器中,使用采样器和顶点对应的**纹理坐标**,从纹理中取出**纹理像素**的颜色。 ## 5. 实践:渲染循环与状态机 ### 5.1. 渲染循环 (Render Loop) 所有实时图形程序的心脏,`while`循环在每一帧都执行以下操作: 1. **输入处理**: 检查键盘、鼠标等输入。 2. **渲染指令**: 清空屏幕,并根据当前状态绘制所有物体。 3. **交换缓冲区**: 将后台绘制好的图像显示到屏幕上,并处理窗口事件。 ### 5.2. OpenGL作为“状态机” 你需要把OpenGL想象成一个只有一个控制面板的机器。面板上有“当前绑定的VAO”、“当前使用的着色器”、“当前激活的纹理单元”等插槽。 - `glBindVertexArray(VAO)` 就是把一个VAO插入到“当前VAO”的插槽里。 - `glUseProgram(program)` 就是把一个着色器程序插入到“当前着色器”的插槽里。 - `glActiveTexture(GL_TEXTURE0)` 切换到0号纹理单元插槽进行操作。 - 后续的`glDrawArrays()`或`glDrawElements()`指令,会**自动使用这些插槽里当前的对象**来执行渲染。 ## 6. 资源管理 VBO、VAO、着色器、纹理等都是在GPU上创建的“对象”,它们占用了显存。当不再需要它们时(例如程序结束时),**必须手动释放**,否则会造成GPU显存泄漏。 - 使用 `glDeleteBuffers`, `glDeleteVertexArrays`, `glDeleteProgram`, `glDeleteTextures` 等函数进行清理。 ## 7. 后续学习方向 1. **变换 (Transformations)**:学习使用矩阵(Matrix)在顶点着色器中对顶点进行移动、旋转和缩放,进入3D世界。 2. **坐标系 (Coordinate Systems)**:深入理解物体从模型空间到世界空间,再到最终屏幕空间的完整坐标变换流程。 3. **光照 (Lighting)**:模拟真实世界的光照效果,如环境光、漫反射光和镜面光。 4. **模型加载 (Model Loading)**:学习使用Assimp等库加载复杂的3D模型。