OpenGL基础概念 — 基础篇

OpenGL基础概念 — 基础篇
OpenGL基础概念 — 基础篇一OpenGL中基础概念本文聚焦于 OpenGLOpen Graphics Library基础的渲染概念。了解这些概念后后续文章将以实际代码演示其操作与用法帮助你进一步掌握 OpenGL 的使用方式。本文不深入展开 OpenGL 的完整 API 细节仅围绕 OpenGL 进行渲染所必需的基础概念进行梳理为后续实战章节理清代码脉络。1.1 基础前置知识可以把 OpenGL 想象成一支画笔它能画出任何东西但在落笔之前你必须先明确三个问题——在哪画、如何画、画什么。在哪画你需要在画布上绘制但这里的画布不是纸张而是一个电子屏幕——不同分辨率的屏幕需要不同的系统 API 来对接。这个对接屏幕的抽象层专业术语叫窗口Window不同操作系统提供不同的窗口 API。在 Android 平台上这个窗口对接工作由EGLEmbedded-System Graphics Library完成。EGL 负责配置系统的渲染表面配置完成后你就拥有了一块可绘制的画布。这块画布可以是可见的最终显示到屏幕上也可以是不可见的。不可见的画布对应渲染管线中的帧缓冲对象FBOFramebuffer Object。只要你的绘制结果不需要立刻上屏就可以一直在 FBO 上操作直到最后一步才输出到屏幕。如何画这对应你编写的 OpenGL 程序。程序编译通过后相当于你手握一支能按预期工作的画笔。VAOVertex Array Object顶点数组对象、VBOVertex Buffer Object顶点缓冲对象等概念就是你在程序中需要操控的核心组件。画什么你可以画一张图片、一个 3D 模型、或一段线段。无论画什么最终呈现在屏幕上都要经过图形渲染管线顶点数据 → 图形装配Primitive Assembly → 光栅化Rasterization → 屏幕输出。这个管线中有些阶段你可以编程控制有些阶段是 GPU 硬件固定实现的——你只需要关注你能控制的部分即可。你画的内容在绘制之前就已经存在了不会凭空产生。例如画一张图片JPEG、Bitmap 等格式→ 借助**纹理Texture**承载图像数据画一段视频帧→ 解码后的帧数据通过纹理刷新到 GPU画一条线段→ 通过顶点数据定义线段的端点控制坐标系将它们连接起来画一个3D 模型如 .obj 文件 → 加载顶点数据通过 MVP 矩阵控制展示为 3D 或 2D 效果即使以 2D 形式展示物体本身仍是 3D 数据很多初学 OpenGL 的人之所以感到困惑正是因为图形绘制知识体系与传统的 UI 开发模式有显著差异导致不清楚这三点。因此在开始学习 OpenGL 时请始终牢记在哪画、如何画、画什么。举个例子使用 OpenGL 绘制一张图片。传统 Android 方式创建一个ImageView设置图片资源控件自动完成渲染。OpenGL 方式在哪画Android 提供了GLSurfaceView等控件封装了 EGL 环境与窗口系统的对接。如何画你需要实现自己的 OpenGL 渲染程序Shader、顶点数据等。画什么将图片加载为纹理Texture并绑定到 OpenGL由 Shader 采样输出到屏幕。注OpenGL 是跨平台的通用图形渲染标准。OpenGL ES 是面向嵌入式设备手机、平板等的精简子集WebGL 是面向浏览器的 Web 版本三者的核心渲染机制相同API 和 Shader 语法有所差异。1.2 顶点坐标和纹理坐标顶点坐标Vertex Coordinates和纹理坐标Texture Coordinates是 OpenGL 绘制中必须指定的两组坐标系。顶点坐标定义图形每个顶点在画布上的位置在上文的代码中直接使用了 NDCNormalized Device Coordinates归一化设备坐标范围[-1, 1]。纹理坐标定义要采样纹理的哪一部分范围通常是归一化的[0, 1]。/** * 方式一顶点坐标和纹理坐标合并在一个数组中 * 顶点坐标(x, y)范围[-1, 1]纹理坐标(u, v)范围[0, 1] */protectedfloat[]mVertexAndTex{-1f,-1f,0f,1f,// 左下顶点(-1,-1), 纹理(0,1)1f,-1f,1f,1f,// 右下顶点(1,-1), 纹理(1,1)-1f,1f,0f,0f,// 左上顶点(-1,1), 纹理(0,0)1f,1f,1f,0f,// 右上顶点(1,1), 纹理(1,0)};/** * 方式二顶点坐标和纹理坐标分开存储 */protectedfloat[]mVertex{-1f,-1f,// 左下1f,-1f,// 右下-1f,1f,// 左上1f,1f,// 右上};protectedfloat[]mTex{0f,1f,// 左下1f,1f,// 右下0f,0f,// 左上1f,0f,// 右上};注代码示例为 JavaC 中定义方式类似。如果顶点坐标不在[-1, 1]的 NDC 范围内——比如模型本身有自己的局部坐标系Local Space——就需要通过 MVP 矩阵Model-View-Projection模型-观察-投影矩阵将顶点从局部坐标系依次变换到世界坐标系、观察坐标系、裁剪坐标系最终映射到 NDC 屏幕空间。这一变换链路是 3D 渲染的基础在纯 2D 渲染场景中大部分情况下可以省略。1.3 顶点着色器和片段着色器顶点着色器Vertex Shader— OpenGL 2.0 / GLSL 1.10 语法attribute vec4 aPosition; // 顶点位置从CPU传入 attribute vec2 aTexCoord; // 纹理坐标从CPU传入 varying vec2 vTexCoord; // 传递给片段着色器的纹理坐标 void main() { vTexCoord aTexCoord; gl_Position aPosition; // 直接使用NDC坐标不做变换 }片段着色器Fragment Shader— OpenGL 2.0 / GLSL 1.10 语法#extension GL_OES_EGL_image_external : require // 启用OES外部纹理扩展 precision mediump float; // 指定float精度 varying vec2 vTexCoord; // 从顶点着色器接收的纹理坐标 uniform samplerExternalOES uTexture; // OES外部纹理采样器 void main() { gl_FragColor texture2D(uTexture, vTexCoord); }顶点着色器的主要作用是对输入的顶点数据进行处理。原始顶点数据存储在模型文件或内存缓冲区中渲染时需要将其传递到 GPU。数据到达顶点着色器时说明已经在 GPU 端了——你需要在此阶段编写程序对每个顶点进行变换计算如 MVP 矩阵变换并将结果输出给渲染管线的后续阶段。片段着色器可以理解为为每一个待输出的像素更准确地说是光栅化后生成的每一个片元 Fragment执行一次计算决定该像素最终的颜色值。例如你看到一个纯红色的正方形片段着色器会将覆盖范围内的每个片元都设置为红色——在 GLSL 中红色表示为(1.0, 0.0, 0.0)归一化浮点数而非 0-255 的整数值而正方形的显示范围则由之前的顶点坐标决定。1.4 VAO 和 VBOVAOVertex Array Object顶点数组对象存储顶点属性配置状态——包括哪些属性启用、各自的格式、以及绑定了哪个 VBO。注意VAO 是 OpenGL 3.0 才支持的特性OpenGL 2.0 中没有 VAO。VBOVertex Buffer Object顶点缓冲对象GPU 端的原始数据缓冲区用于存储顶点坐标、纹理坐标、法线等数据。EBOElement Buffer Object元素缓冲对象/ IBOIndex Buffer Object索引缓冲对象存储顶点索引用于复用顶点数据减少重复传输。VAO 和 VBO 各有分工、互相配合VBO 负责装数据VAO 负责描述数据格式。你在 1.2 节看到的顶点坐标数组需要通过 VBO 上传到 GPU再由 VAO或直接通过glVertexAttribPointer告诉 GPU 如何解析这些数据。顶点数据 → [VBO存储] → [VAO描述格式] → GPU渲染管线1.5 FBO帧缓冲对象FBOFramebuffer Object帧缓冲对象是 OpenGL 提供的离屏渲染Off-screen Rendering机制。正常情况下渲染结果会直接输出到屏幕。但有时我们需要做多步后处理中间步骤不需要被用户看到——这就是 FBO 的用武之地。你可以将 FBO 理解为一块不上屏的画布每当执行一次 Draw Call画面就渲染到 FBO 绑定的纹理上而非屏幕。典型场景给视频画面依次添加水印、饱和度调节和签名。这三步中只有最后一步需要上屏渲染原始画面 → FBO-A绑定纹理 A对纹理 A 做饱和度调节 → FBO-B绑定纹理 B对纹理 B 叠加签名 → 直接输出到屏幕每一步的 FBO 实际上就是绑定了一张纹理处理结果就写在这张纹理里供下一步使用。此外FBO 也是调试利器你可以将中间渲染结果输出到 FBO 绑定的纹理然后读取到 CPU 端——导出为 JPEG 文件、显示到 Bitmap 上或在 Debug 模式下逐帧检查。这在排查渲染问题时非常有用。1.6 MVP 矩阵MVP 矩阵由三个矩阵组成Model模型矩阵、View观察矩阵、Projection投影矩阵。它们的核心作用是将 3D 物体的顶点从局部坐标系变换到屏幕坐标系。但在纯 2D 渲染场景如渲染视频帧或单张图片中顶点坐标通常直接用 NDC 范围[-1, 1]MVP 矩阵并非必需。注以下代码采用 C 的 GLMOpenGL Mathematics数学库作为示例。M 矩阵Model Matrix模型矩阵— 处理物体的平移、旋转、缩放// 沿 Z 轴负方向平移 3 个单位glm::mat4 modelglm::mat4(1.0f);modelglm::translate(model,glm::vec3(0.0f,0.0f,-3.0f));// 绕 X 轴逆时针旋转 55 度modelglm::rotate(model,glm::radians(-55.0f),glm::vec3(1.0f,0.0f,0.0f));// 沿 X 轴缩放 2 倍modelglm::scale(model,glm::vec3(2.0f,1.0f,1.0f));V 矩阵View Matrix视图矩阵— 将顶点从世界坐标系变换到观察坐标系glm::mat4 viewglm::mat4(1.0f);viewglm::translate(view,glm::vec3(0.0f,0.0f,-3.0f));P 矩阵Projection Matrix投影矩阵— 有两种正交投影和透视投影。正交投影建立一个长方体区域落在内部的顶点才会被绘制外部的被裁切。透视投影以近大远小的视椎体为裁剪区域。// 正交投影矩阵 — 适合 2D 渲染或 UIglm::mat4 projglm::ortho(0.0f,// left1920.0f,// right0.0f,// bottom1080.0f,// top-1.0f,// near1.0f// far);// 透视投影矩阵 — 适合 3D 场景glm::mat4 projglm::perspective(glm::radians(45.0f),// FOV视野角度16.0f/9.0f,// 宽高比0.1f,// 近裁剪面距离100.0f// 远裁剪面距离);1.7 纹理Texture纹理Texture可以简单理解为 GPU 端存储的一张图像。平时看到的 JPEG、PNG 等格式的图片在 OpenGL 中展示时本质上是将图像数据上传为纹理再通过 Shader 采样输出到屏幕。unsignedinttexture;// 纹理句柄IDglGenTextures(1,texture);// 生成一个纹理对象glBindTexture(GL_TEXTURE_2D,texture);// 绑定为2D纹理// 设置纹理参数glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);// S轴水平环绕模式重复glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);// T轴垂直环绕模式重复glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);// 缩小时的过滤方式线性插值glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);// 放大时的过滤方式线性插值// 上传图像数据到GPUglTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,data);二OpenGL中的Shader编程概念2.1 渲染管线流程在深入 Shader 编程之前先了解**图形渲染管线Graphics Pipeline**的整体流程。渲染管线是将 3D/2D 数据最终转换为屏幕像素的一系列处理阶段OpenGL 渲染管线 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 顶点数据 │ │ (VBO/VAO) │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 顶点着色器 │ ◄── 可编程 ★ │ │ │ Vertex Shader│ 对每个顶点执行变换MVP、坐标转换 │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 几何着色器 │ ◄── 可编程可选 │ │ │Geometry Shader│ 对图元级别进行修改/生成 │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 图形装配 │ ◄── GPU 硬件固定 │ │ │Primitive Assy │ 将顶点组装为图元点、线、三角形 │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 光栅化 │ ◄── GPU 硬件固定 │ │ │Rasterization │ 将图元转换为片元Fragment │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 片段着色器 │ ◄── 可编程 ★ │ │ │Fragment Shader│ 为每个片元计算最终颜色值 │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ 测试与混合 │ ◄── GPU 硬件可配置 │ │ │Test Blend │ 深度测试、模板测试、Alpha混合 │ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ 屏幕输出 │ │ │ └─────────────────────────────────────────────────────────────────────┘ ★ 开发者可编程控制的核心阶段关键要点顶点着色器和片段着色器是渲染管线的两个必经可编程阶段也是开发者最常编写代码的地方。几何着色器是可选的位于顶点着色器之后、光栅化之前初学者可暂时跳过。图形装配和光栅化由 GPU 硬件自动完成开发者无法修改其内部逻辑但可以通过 API 配置其行为如指定图元类型为GL_TRIANGLES还是GL_LINES。测试与混合阶段可配置如开启/关闭深度测试、设置 Alpha 混合模式但不属于 Shader 编程范畴。理解渲染管线是学习 Shader 的前提——你需要知道数据从哪来、经过哪些处理、最终去了哪里才能写出正确的 Shader 代码。2.2 概念介绍在 OpenGL 渲染管线中共有三种可编程的着色器Shader顶点着色器Vertex Shader— 处理顶点数据位于几何阶段几何着色器Geometry Shader— 处理图元级别的生成与修改可选阶段OpenGL 3.2 才支持片段着色器Fragment Shader也称像素着色器 Pixel Shader— 处理每个片元的颜色输出位于光栅化阶段其中顶点着色器和片段着色器是必选的几何着色器是可选的。顶点着色器处理每个顶点的变换计算典型的应用场景是 MVP 矩阵变换旋转、平移、缩放、投影。它的输入是顶点坐标、纹理坐标等原始属性输出是变换后的顶点坐标gl_Position以及传递给片段着色器的插值数据如纹理坐标。几何着色器在顶点着色器之后、光栅化之前执行可对图元点、线、三角形进行修改或生成新的图元。它在渲染管线中是可选的。初学者如果没有特定需求可以暂时跳过。需要说明的是几何着色器并未被取代——桌面端 OpenGL 3.2 仍支持它只是在 Vulkan、Metal 等新一代 API 中Mesh Shader 提供了更灵活的替代方案。在复杂场景的 OpenGL 渲染中顶点着色器和片段着色器是开发者主要编程的两个阶段。3D 场景的 Shader 通常较为复杂包含光照计算、阴影映射等而 2D 场景的 Shader 则相对简单以纹理采样和色彩处理为主。Shader 语法在不同版本间有差异如 OpenGL 2.0 / GLSL 1.10 使用attribute/varyingOpenGL 3.3 / GLSL 330 使用in/out但核心机制不变顶点着色器负责输出变换后的顶点位置及插值数据纹理坐标、颜色、法线等片段着色器负责为每个片元计算最终的 RGBA 颜色值。2.3 关键参数介绍顶点着色器的关键参数说明// OpenGL 3.3 / GLSL 330 版本 #version 330 core layout(location 0) in vec3 aPosition; // 顶点位置location0 layout(location 1) in vec2 aTexCoord; // 纹理坐标location1 layout(location 2) in vec3 aColor; // 顶点颜色location2 uniform mat4 uModel; // Model 矩阵——CPU通过uniform传入 uniform mat4 uView; // View 矩阵 uniform mat4 uProjection; // Projection 矩阵 out vec3 vColor; // 传递给片段着色器的颜色插值后 out vec2 vTexCoord; // 传递给片段着色器的纹理坐标 void main() { // MVP 变换局部坐标 → 裁剪坐标 gl_Position uProjection * uView * uModel * vec4(aPosition, 1.0); vTexCoord aTexCoord; vColor aColor; }三个关键修饰符inOpenGL 3.3/attributeOpenGL 2.0从 CPU 端传入顶点着色器的属性数据uniformCPU 端传入的全局变量一次 Draw Call 内所有顶点共享如 MVP 矩阵outOpenGL 3.3/varyingOpenGL 2.0从顶点着色器输出传递给片段着色器值会被插值片段着色器的关键参数说明// OpenGL 3.3 / GLSL 330 版本 #version 330 core in vec3 vNormal; // 从顶点着色器接收的法线已插值 in vec2 vTexCoord; // 从顶点着色器接收的纹理坐标已插值 in vec3 vColor; // 从顶点着色器接收的颜色已插值 uniform sampler2D uTexture; // 2D纹理采样器 out vec4 fragColor; // 最终输出的片元颜色RGBA void main() { vec3 normal normalize(vNormal); // 法线归一化 vec4 texColor texture(uTexture, vTexCoord); // 从纹理采样 // 简单漫反射光照法线Z分量越大越朝向相机越亮 float diffuse max(dot(normal, vec3(0.0, 0.0, 1.0)), 0.0); fragColor texColor * diffuse; // 纹理色 × 光照强度 }三OpenGL的相关坐标系概念3.1 坐标系的种类局部坐标系Local Space建模软件中物体自身的坐标系每个模型以各自的参考点为原点互不关联。世界坐标系World Space将多个模型放置到同一个 3D 场景中时使用的全局坐标系各物体通过 Model 矩阵确定在世界中的位置、旋转和缩放。观察坐标系View Space以摄像机Camera为原点摄像机的视线方向为 -Z 轴、上方为 Y 轴、右侧为 X 轴的坐标系由 View 矩阵完成变换。裁剪坐标系Clip Space一个 4D 齐次坐标空间(x, y, z, w)由 Projection 矩阵变换得到超出[-w, w]范围的顶点将被裁剪不渲染。NDCNormalized Device Coordinates归一化设备坐标裁剪坐标经过透视除法除以 w 分量后得到的坐标空间范围为[-1, 1]。NDC 与屏幕分辨率无关。屏幕坐标系Screen Space最终映射到物理屏幕像素的坐标系由glViewport函数决定 NDC 到实际像素的映射。例如glViewport(0, 0, 1080, 1920)将 NDC 映射到 1080×1920 像素区域。3.2 坐标系的关系局部坐标系中的数据就是建模时的原始顶点数据。以backpack.obj文件为例用文本编辑器打开可以看到一系列顶点坐标——这些坐标都是相对于建模软件中的坐标原点定义的这就是局部坐标系。不同的人在不同建模软件中创建的模型各自拥有独立的坐标原点互不关联因此称为局部坐标系。世界坐标系是你定义的 3D 场景的全局坐标空间。在编写 OpenGL 程序之前你需要决定每个物体在 3D 世界中的摆放位置。例如你加载了一个桌子模型希望它出现在场景的左下方——通过 Model 矩阵设置平移分量将桌子的局部坐标变换到世界坐标的目标位置。此时世界坐标原点是你在场景中任意选定的一点。在世界坐标系中摆放好物体后需要将整个场景变换到观察坐标系也称相机坐标系以简化后续的投影计算。观察坐标系以摄像机的位置为原点视线方向看向屏幕内部为 -Z 轴摄像机的上方为 Y 轴右侧为 X 轴。这一变换由 View 矩阵完成。裁剪坐标系是一个关键的中间阶段。经过 Projection 矩阵变换后顶点进入裁剪空间。在这个空间中OpenGL 可以判断哪些顶点在视野范围内需要渲染以及哪些在视野范围外被裁剪掉不渲染。判断依据是顶点的 x、y、z 分量是否在[-w, w]范围内。之后经过透视除法除以 w裁剪坐标转化为 NDC。NDC 坐标范围[-1, 1]原点在中心经过glViewport映射后最终转换为屏幕像素坐标。glViewport(0, 0, 1080, 1920)表示将 NDC 映射到一个 1080×1920 像素的区域glViewport(0, 0, 540, 960)则映射到 540×960 像素区域。这意味着同样的 NDC 内容可以绘制到不同大小的屏幕上由glViewport决定最终输出的像素范围。各个坐标系之间的转换关系局部空间 ──×Model──→ 世界空间 ──×View──→ 观察空间 ──×Projection──→ 裁剪空间 ──÷w(透视除法)──→ NDC ──glViewport──→ 屏幕空间总结各坐标系的维度局部 / 世界 / 观察坐标系— 3D 笛卡尔坐标系x, y, z裁剪坐标系— 4D 齐次坐标系x, y, z, wNDC— 3D 坐标x, y, zz 保留用于深度测试屏幕坐标系— 2D 像素坐标系通过glViewport映射后3.3 坐标系变换图解为了让读者更直观地理解各个坐标系之间的变换过程下面用一个生活化的场景来类比场景你在客厅里拍照坐标系变换全景图 ┌──────────────────────────────────────────────────────────────────────────┐ │ │ │ ① 局部坐标系 ② 世界坐标系 ③ 观察坐标系 │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ 沙发模型 │ Model矩阵 │ 客厅中的沙发 │ View矩阵 │ 相机看到的 │ │ │ │ 出厂坐标 │ ────────→ │ 摆放好位置 │ ────────→ │ 场景视锥 │ │ │ │ (厂内原点) │ │ (客厅原点) │ │ (相机原点) │ │ │ └────────────┘ └────────────┘ └────────────┘ │ │ │ │ │ │ │ ▼ Projection矩阵 │ │ ┌────────────┐ │ │ │ ④ 裁剪坐标系 │ │ │ │ 决定哪些可见 │ │ │ │ (视锥体裁剪) │ │ │ └────────────┘ │ │ │ │ │ ▼ 透视除法÷w │ │ ┌────────────┐ │ │ │ ⑤ NDC │ │ │ │ 归一化坐标 │ │ │ │ [-1, 1]范围 │ │ │ └────────────┘ │ │ │ │ │ ▼ glViewport │ │ ┌────────────┐ │ │ │ ⑥ 屏幕坐标系 │ │ │ │ 实际像素输出 │ │ │ │ (如 1080p) │ │ │ └────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────────┘场景类比解析你现在要拍一张客厅的照片照片内容就是 OpenGL 最终渲染到屏幕上的画面。整个过程可以拆解为以下步骤步骤坐标系类比动作对应矩阵1局部坐标系沙发在出厂时厂家记录了它在工厂中的位置——这个位置只在工厂内部有意义—2世界坐标系你把沙发搬回家摆到客厅的东北角——沙发现在在你的世界里有了确定的位置× Model3观察坐标系你站在客厅门口举起相机——相机的位置和朝向决定了能看到什么× View4裁剪坐标系取景框范围内的景物会被拍下来范围外的比如背后的墙不会出现在照片中× Projection5NDC照片的构图比例被确定下来与你使用什么尺寸的相纸无关÷ w透视除法6屏幕坐标系你把照片冲印到 6 寸相纸或 10 寸相纸上——同样的构图不同的物理尺寸glViewport关键记忆点变换链路为Local → World → View → Clip → NDC → Screen其中前三步由矩阵乘法完成× Model → × View → × Projection后两步由 GPU 硬件自动处理÷ w → glViewport 映射。四关键术语速查表术语英文全称简要解释章节OpenGLOpen Graphics Library跨平台的 2D/3D 图形渲染 API 标准1.1GLSLOpenGL Shading LanguageOpenGL 着色器编程语言语法类似 C1.3EGLEmbedded-System Graphics Library连接 OpenGL 与操作系统窗口系统的中间层1.1NDCNormalized Device Coordinates归一化设备坐标范围 [-1, 1]与屏幕分辨率无关1.2VBOVertex Buffer ObjectGPU 端的顶点数据缓冲区1.4VAOVertex Array Object存储顶点属性配置状态格式、绑定关系1.4EBO / IBOElement/Index Buffer Object存储顶点索引用于复用顶点减少数据量1.4FBOFramebuffer Object帧缓冲对象支持离屏渲染不直接输出到屏幕1.5MVPModel-View-Projection模型-观察-投影矩阵将顶点从局部坐标变换到裁剪坐标1.6Vertex Shader—顶点着色器处理每个顶点的变换计算1.3 / 2.2Fragment Shader—片段着色器像素着色器计算每个片元的颜色值1.3 / 2.2Geometry Shader—几何着色器可选阶段对图元进行修改或生成2.2Texture—纹理GPU 端存储的图像数据1.7Fragment—片元光栅化后生成的候选像素经过测试后才成为最终像素1.3Rasterization—光栅化将图元三角形/线/点转换为片元的过程2.1Primitive—图元OpenGL 的基本绘制单位点、线、三角形2.1Draw Call—一次绘制指令将一组顶点数据提交给 GPU 渲染1.5Uniform—GLSL 修饰符表示一次 Draw Call 内所有顶点共享的全局变量2.3Attribute / in—GLSL 修饰符表示从 CPU 端传入每个顶点的属性数据2.3Varying / out—GLSL 修饰符表示从顶点着色器输出并传递给片段着色器的插值数据2.3Viewport—视口由glViewport定义决定 NDC 到屏幕像素的映射区域3.1GLMOpenGL MathematicsC 数学库提供向量和矩阵运算仅头文件1.6Orthographic Projection—正交投影无近大远小效果适合 2D 渲染1.6Perspective Projection—透视投影有近大远小效果适合 3D 渲染1.6五参考资料3D 模型示例backpack.obj