1. OpenGL
OpenGL
仅仅是一个规范(Specification
)OpenGL
规范没有规定实现的细节,具体的OpenGL
库允许使用不同的实现,只要功能和结果与规范相匹配- 实际 OpenGL 库的开发者通常是
显卡的生产商
1.1 核心模式与立即渲染模式
- 早期 OpenGL 使用
立即渲染模式(Immediate mode)
- 优点:绘图方便,容易使用和理解
- 不足:缺少灵活性,效率低
OpenGL3.2
,废弃立即渲染模式(Immediate mode)
,鼓励开发者使用核心模式(Core-profile)
1.2 扩展
OpenGL 支持扩展,方便显卡公司提出新特性或者渲染的优化。
1.3 状态机
使用 OpenGL,遇到的一些状态设置函数(State-changing Function)
会改变上下文,以及 状态使用函数(State-using Function)
。
1.4 附加资源
- opengl.org:OpenGL 官方网站
- OpenGL registry:包含 OpenGL 各版本的规范和扩展
2. 创建窗口
2.1 GLFW
一个针对 OpenGL 的 C 语言库,提供一些渲染物体所需最低限度接口。
2.2 GLAD
解决 OpenGL 驱动版本多,并且根据这个版本加载所有相关的 OpenGL 函数。
3. 你好,窗口
3.1 双缓冲(Double Buffer)
单缓冲存在图像闪烁问题,因为生成图像不是瞬间被绘制,而是从左到右,从上到下。
前缓冲
:保存最终输出的图像,它会在屏幕上显示;后缓冲
:所有的渲染指令在此绘制;
所有渲染指令执行完毕之后,交换
(swap)前缓冲和后缓冲,消除不真实感。
4. 你好,三角形
VAO
:Vertex Array Object,顶点数组对象VBO
:Vertex Buffer Object,顶点缓冲对象EBO
:Element Buffer Object,元素缓冲对象IBO
:Index Buffer Object, 索引缓冲对象
4.1 图形渲染管线
大多译为管线(Graphics Pipeline),用来处理 3D 坐标转化为 2D 坐标,并将 2D 坐标转变为实际的有颜色的像素
4.2 管线阶段
- OpenGL 着色器是用 OpenGL 着色器语言(OpenGL Shading Language,
GLSL
) - 蓝色部分代表可以注入自定义着色器
4.3 渲染过程
- 顶点着色器:把 3D 坐标转为另一种 3D 坐标
- 图元装配:将顶点着色器输出的顶点作为输入,把所有的点装配为指定图元形状(eg:GL_POINTS、GL_TRIANGLES、GL_LINE_STRIP)
- 几何着色器:可以通过产生新顶点构造新的图元生成其他形状
- 光栅化:把图元映射为最终屏幕上的像素
- 片段着色器:计算一个像素的最终颜色,是所有 OpenGL 高级效果产生的地方。通常,包含 3D 场景数据(eg:光照、阴影、光颜色)
- Alpha 测试和混合:检测片段对应深度值,用来判断这个像素在前还是在后。
4.4 顶点输入
- OpenGL 仅当 3D 坐标在 3 个轴(x、y 和 z)上
-1.0
到1.0
的范围内时才处理。 - 这个范围内的坐标叫做
标准化设备坐标
- 定义数据之后,发送给顶点着色器
- 通过
VBO
管理内存,它会在 GPU 内存存储大量顶点 VBO
有一个独一无二的 ID
4.5 顶点着色器
4.6 编译着色器
- 创建着色器对象:
glCreateShader
- 将着色器源码附加到着色器对象:
glShaderSource
- 编译:
glCompileShader
4.7 片段着色器
4.8 着色器程序
- 创建程序:
glCreateProgram
- 将之前编译的着色器附加到程序对象:
glAttachProgram
- 链接:
glLinkProgram
- 激活:
glUseProgram
- 链接到程序对象之后删除:
glDeleteShader
4.9 链接顶点属性
- 解析顶点数据:
glVertexAttribPointer
- 启用顶点数据:
glEnableVertexAttribArray
4.10 顶点数组对象
4.11 元素缓冲对象
5. 着色器
OpenGL 着色器语言:GLSL。类 C 语言,为图形计算量身定制
5.1 数据类型
- 基础类型:
int
float
double
uint
bool
- 容器类型:
Vector
Matrix
5.2 输入输出
- 用
in
和out
关键字定义 - 从一个着色器向另一个着色器发送数据,必须在发送方着色器声明一个输出,在接收方着色器声明一个输入。OpenGL 会把两个变量链接在一起,实现数据发送。
5.3 Uniform
- 全局,在每个着色器程序中独一无二
- 被着色器程序任意着色器任意阶段访问
6. 纹理
6.1 环绕方式
GL_REPEAT
:默认。超出即重复GL_MIRRORED_REPEAT
GL_CLAMP_TO_EDGE
GL_CLAMP_TO_BORDER
6.2 纹理过滤
- 纹理坐标不依赖分辨率
GL_NEAREST
:默认。GL_LINEAR
:基于纹理坐标附近的纹理像素,计算出一个插值glTexParameter*
可以指定放大缩小的过滤方式glGenerateMipmaps
函数来处理多级渐远纹理
(主要使用于纹理被缩小的情况)
6.3 加载创建纹理
stb_image.h
图像加载器,把图像转化为字节序列glGenTextures
创建纹理glBindTexture
绑定glTexImage2D
生成
6.4 应用纹理
GLSL
的 texture
函数
6.5 纹理单元
7. 变换
通过多个矩阵(Matrix)对象实现变换(Transform)
7.1 GLM
- Open
GL
M
athematics 缩写 - 一个数学库
8. 坐标系统
将坐标从一个坐标系变换到另一个坐标系,需要用到变换矩阵。
8.1 局部空间
物体所在的坐标空间
8.2 世界空间
8.3 观察空间
8.4 裁剪空间
OpenGL 期望所有坐标落在特定范围
- 正射投影
- 透视投影
9. 摄像机
欧拉角:俯仰角 + 偏航角 + 滚转角