前言
我们在前面,首先进行了针对 iOS中的多媒体技术相关几个框架概述:
- 进而 用 两篇文章 对 其中的
UIKit
相关要点 进行了分述:- 然后我们 针对 Core Animation框架的要点 进一步展开分述:
- 紧接着 我们快速回顾了 2D绘图引擎Core Graphics框架的要点
- 再然后 我们 围绕 滤镜框架Core Image、GPUImage框架的要点 进行了快速回顾:
- 我们 在此篇文章 ,将 针对 底层渲染框架Metal、OpenGL ES框架的要点 进一步展开分述:
一、图形API简介(OpenGL ES、Metal)
1. 走向3D图形世界
关于3D图形世界
的更详细介绍,我推荐阅读书籍: 《OpenGL超级宝典》第一章: 3D图形和OpenGL简介.
幸运的是,已经有图形开发爱好者,将一些重点整理在博文上:3D图形和OpenGL简介
三维(3D)表示一个正在描述或显示的物体具有3个维度:宽度
、高度
和深度
。例如
- 放在书桌上的一张画是一个二维物体,因为它没有可以令人感受得到的深度。
- 而旁边的药瓶却能感受到它是3D,因为它具备
高度
、深度
、宽度
。
几个世纪以来,艺术家们已经知道如何让一幅画有立体感
并且具有真实的深度。
- 通过颜料在二维画布上所创作的作品,它其实本质上画的是一个二维物体
- 类似,计算机3D图像实质上也是平面的,它只是在计算机屏幕上所显示的二维图像,但它可以提供深度的错觉。
2D + 透视 = 3D
2. 图形API简介
无论是2D还是3D图形界面,它们都有相关的编程接口,这里介绍几个图形API:
- OpenGL(Open Graphics Library)
- 是一种
跨平台
的图形API,用于开发2D和3D图形应用
程序 - 它将计算机的资源抽象称为一个个OpenGL的对象
- 对这些资源的操作抽象为一个个的OpenGL指令。
- 是一种
- OpenGL ES(OpenGL for Embedded Systems )
- 是OpenGL三维图形API的子集
- 针对手机、PDA和游戏主机等嵌入式设备而设计的,
去除了许多不必要和性能较低的API接口
- DirectX
- 是由很多API组成的,DirectX并不是一个单纯的图形API。
- 最重要的是DirectX是属于Windows上一个多媒体处理API。
- 并不支持Windows以外的平台,所以不是跨平台框架。
- 按照性质分类,可分为四大部分:
显示部分
、声音部分
、输入部分
和网络部分
- Metal
- Apple为游戏开发者推出了新的平台技术,该技术能够为3D图像提高10倍的渲染性能。
- Metal是Apple为解决3D渲染而推出的框架
3. 学习OpenGL ES和Metal的选择
我们首先 引入苹果 官方提供的OpenGL ES
编程指南:OpenGL ES Programming Guide 从指南中,苹果已经提及,在iOS12以后,对OpenGL ES弃用,转向对Metal的支持。
苹果都弃用了OpenGL/OpenGL ES,那还需要学OpenGL ES?
- 1、苹果自身系统迁移到Metal是花费了4年时间
- 2、在没有推出Metal时,苹果对于OpenGL ES是高度集成且配合相应图层和GLKit来辅助开发者能快速使用
OpenGL ES
- 3、
OpenGL ES
的弃用,只是针对苹果内部系统底层API依赖而言- 并不是想让iOS开发者从此不使用
OpenGL ES
- 只是角色变成了第三方,毕竟它的跨平台以及稳定是很难让现有的开发放弃,而这几点Metal目前很难做到
- 并不是想让iOS开发者从此不使用
- 4、目前大多数类似百度地图、高德地图和音视频处理的项目组已经很庞大了,暂时不会迁移到Metal,所以只学习Metal是不够用的
- 5、所以学习需要一步一步的走
OpenGL
->OpenGL ES
->Metal
4. 图形API用于解决什么问题
实现图形的底层渲染
比如:
- 在游戏开发中,对
游戏场景/游戏任务
的渲染 - 在音视频开发中,对于
视频解码后的数据
渲染 - 在地图引擎,对于
地图上的数据渲染
- 在动画中,
实现动画的绘制
- 在视频处理中,对于
视频加上滤镜
效果 - ...
图形API工作的本质
- 图形API工作的本质:就是利用GPU芯片来高效渲染图形图像
- 图形API是iOS开发者唯一接近GPU的方式
二、渲染工作流水线简介
以iOS平台为例。我们先回顾一下渲染工作流水线,再过渡到图形API(如OpenGL ES、Metal)的在流水线上的工作环节和工作流程。再介绍一下流程内涉及到的一些 3D图形技术 术语。如此,我们学习 3D图形技术就不那么突兀了。
1. 渲染工作流水线说明(点击查看详情)
- ①-应用交互前端UIKit/AppKit →
- ②-Core Animation →
- ③ OpenGL ES/ Metal →
- ④ GPU Driver →
- ⑤ GPU →
- ⑥ Screen Display
在屏幕成像的过程中,CPU
和GPU
起着至关重要的作用
- CPU(Central Processing Unit,中央处理器)
CPU的主要任务是进行对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码、图像的绘制(Core Graphics) - GPU(Graphics Processing Unit,图形处理器)
GPU的主要任务是对纹理的渲染 - 小结:
从CPU准备渲染数据(纹理),交由GPU进行渲染
2. Core Animation 渲染流水线详细说明(点击查看详情)
- ①-
CPU阶段
: Core Animation (Commit Transaction )CPU阶段
→ 数据缓存 →GPU阶段
- 注:
- CPU、GPU无法直接交换数据
- 从⼀块内存中将数据复制到另⼀块内存中, 传递速度是非常慢的,内存复制数据时, CPU和GPU 都不能 操作数据(避免引起错误)
- OpenGL API 可以 在CPU(
C端
)工作、也可以在GPU(S端
)工作,是两者的桥梁 - Buffers数据 用于
C端
与S端
交互
- ②-
GPU阶段
: → Render Server (OpenGL ES、Metal等图形API在工作)
3. GPU图形渲染流水线(点击查看详情)
1. (CPU 负责的时期)Application 应用处理阶段:得到图元
- 这个阶段具体指的就是图像在应用中被处理的阶段,此时还处于 CPU 负责的时期。
- 在这个阶段应用可能会对图像进行一系列的操作或者改变,最终将新的图像信息传给下一阶段
- 这部分信息被叫做图元(primitives),通常是
三角形
、线段
、顶点
等。
2. Geometry 几何处理阶段:处理图元
- 进入这个阶段之后,以及之后的阶段,就都主要由 GPU 负责了
- 此时 GPU 可以拿到上一个阶段传递下来的图元信息,GPU 会对这部分图元进行处理,之后输出新的图元。这一系列阶段包括:
顶点着色器(Vertex Shader)
:这个阶段中会将图元中的顶点信息进行视角转换、添加光照信息、增加纹理等操作。形状装配(Shape Assembly)
:图元中的三角形、线段、点分别对应三个 Vertex、两个 Vertex、一个 Vertex。这个阶段会将 Vertex 连接成相对应的形状。几何着色器(Geometry Shader)
:额外添加额外的Vertex,将原始图元转换成新图元,以构建一个不一样的模型。简单来说就是基于通过三角形、线段和点构建更复杂的几何图形。
3. Rasterization 光栅化阶段:图元转换为像素
光栅化的主要目的是将几何渲染之后的图元信息,转换为一系列的像素,以便后续显示在屏幕上
- 这个阶段中会根据图元信息,
计算出每个图元所覆盖的像素信息
等,从而将像素划分成不同的部分。
4. Pixel 像素处理阶段:处理像素,得到位图
- 经过上述光栅化阶段,我们得到了图元所对应的像素
- 此时,我们需要给这些像素
填充颜色
和效果
GPU 图形渲染流水线的主要工作可以被划分为两个部分:
- 把 3D 坐标转换为 2D 坐标
- 把 2D 坐标转变为实际的有颜色的像素
4. OpenGL ES工作过程(点击查看详情)
前面提及的 →②几何处理阶段
→③光栅化阶段
→④像素处理阶段
都属于OpenGL ES
的工作环节。它又可以细分为,上图的6个小阶段:
- ②
几何处理阶段
顶点着色器(Vertex Shader)
形状装配(Shape Assembly)
几何着色器(Geometry Shader)
- ③
光栅化阶段
光栅化(Rasterization)
- ④
像素处理阶段
片段着色器(Fragment Shader)
测试与混合(Tests and Blending)
接下来,我们就由OpenGL ES
的工作环节,引入图形API相关的技术术语
三、3D图形技术概念
1. OpenGL状态机
- OpenGL上下文
Context
- 上下文是一个非常庞大的状态机,保存了OpenGL中的各种状态
- 不管在哪个语言中,都是类似C语言一样面向过程的函数
OpenGL状态机
- 描述了一个对象的生命周期经历各种状态,发生转变时的
动因
、条件
及转变中所执行的活动
- 有记忆功能
- 能记住其当前的状态(如当前所使用的颜色、是否开启了混合功能等):
glClearColor(1,1,1,1)
设置颜色glEable(GL_DEPTH_TEST)
开启深度测试glEable(GL_BLEND)
开启混合
- 可以接收输入
根据输入
的内容和自己的原先状态
,修改自己当前
状态,并且可以有对应输出
- 当进入特殊状态(停机状态)时便不再接收输入,停止工作
- 描述了一个对象的生命周期经历各种状态,发生转变时的
2. 渲染管线
渲染
:- 将
图形/图像数据
转换成3D空间图像的操作
叫做渲染(Rendering) - 即
数据->可视化界面
的过程,也就是我们口中所说的绘制
- 将
顶点数组
(VertexArray)和顶点缓冲区
(VertexBuffer):顶点数据
是由GPU处理的顶点数组
是存在内存中,GPU通过操作内存来处理顶点数据
顶点缓冲区
存在显卡显存中,使得GPU的操作更为简单- 在调用绘制方法的时候,直接有内存传入
顶点数据
,也就是这部分数据之前是存储在内存中的,被称为顶点数组
; - 性能更高的做法是,提前分配一块显存,将
顶点数据
预先传入到显存当中,这块显存就是顶点缓冲区
管线
:- 可以理解为流水线。在OpenGL下渲染图形,就会经历一个一个节点,这样的操作可以理解为管线。
- 之所以称为管线是因为显卡在处理数据的时候是按照一个固定的顺序来的
固定管线/存储着色器
:- 在早期OpenGL版本中,开发者只需要传入相应的参数,就能快速完成图形的渲染。
- 开发者只需要调用API使用封装好的固定shader程序段,并不需要关注底层实现原理
3. 着色器程序
着色器程序Shader
- 是一段程序代码,是用来操作GPU进行计算的,主要的着色器有:
- 顶点着色器(VertexShader)
- 片元着色器(Metal叫片元函数)/片段着色器(FragmentShader)/像素着色器(PixelShader)
- 几何着色器(GeometryShader)
- 曲面细分着色器(TessellationShader)
- 在绘制的时候
- 首先由
顶点着色器
对传入的顶点数据进行运算,将顶点转换为图元; - 然后进行
光栅化
转化为栅格化数据; - 最后传入
片元着色器
进行运算
- 首先由
- 是一段程序代码,是用来操作GPU进行计算的,主要的着色器有:
顶点着色器
(VertexShader)- 用来处理图形每个顶点变换------旋转/平移/投影
- 每一个顶点都会执行一次
片元着色器
(FragmentShader)- 用来处理图形中每个像素点的颜色计算和填充
- 每个像素都会执行一次片元着色器(并行执行)
GLSL
(OpenGL Shading Language)- 是用来在OpenGL中着色编程的语言,即开发人员写的短小的自定义程序
- 代替了固定渲染管线,使渲染管线中不同层次具有可编程性,比如:视图转换、投影转换等
- 用来操作
顶点着色器
和片元着色器
4. 纹理相关
光栅化
(Rasterization)- 是把
顶点数据
转换成片元
的过程,具有将图转化为一个个栅格组成的图像的作用(像素数据) - 其实就是将
几何图元变为二维图像
的过程。- 该过程包含了两部分工作:
- 决定窗口坐标中的那些整形栅格区域被基本图元占用;
- 分配
一个颜色值
和一个深度值
到各个区域
- 该过程包含了两部分工作:
- 把
物体的数学描述
以及与物体相关的颜色信息
转换为屏幕上用于对应位置的像素
及用于填充像素的颜色
,这个过程称为光栅化
- 是把
缓存
:- OpenGL ES 部分运行在 CPU 上,部分运行在 GPU 上,为了协调这两部分的数据交换,定义了缓存(Buffers) 的概念。
- CPU 和 GPU 都有独自控制的内存区域,缓存可以避免数据在这两块内存区域之间进行复制,提高效率。缓存实际上就是指一块连续的 RAM 。
纹理
:可以简单理解成图片(位图)- 纹理 是一个用来保存图像颜色的元素值的缓存
- 渲染是指将数据生成图像的过程。
- 纹理渲染则是将保存在内存中的颜色值等数据,生成图像(位图)的过程。
5. 其它
混合
:两种颜色的视图叠在一起后的颜色就叫混合变换矩阵
(Transformation):图形发生平移、缩放、旋转变换投影矩阵
(Projection):将3D坐标转换为二维屏幕坐标渲染上屏/交换缓冲区
(SwapBuffer)- 常规的OpenGL程序至少都会有两个缓冲区
- 显示在屏幕上的成为
帧缓冲区 frame buffer
,没有显示的成为离屏缓冲区 offscreen buffer
。 - 在一个缓冲区渲染完成之后,通过将屏幕缓冲区和离屏缓冲区交换,实现图像在屏幕上的显示
- 显示在屏幕上的成为
- 为了防止交换缓冲区的时候屏幕上下区域的图像分属于两个不同的帧,因此交换一般会等待显示器刷新完成的信号,在显示器两次刷新的间各种进行交换,这个信号就成为
垂直同步信号
,这个技术成为垂直同步
- 常规的OpenGL程序至少都会有两个缓冲区
6. 坐标系
6.1 2D 笛卡尔坐标系
- 2D笛卡尔坐标系:
拥有x轴、y轴的平面坐标系(用来描述平面图形)
6.2 3D 笛卡尔坐标系
- 3D笛卡尔坐标系:
拥有x轴、y轴、z轴(z轴表示深度)的立体坐标系(用来描述立体图形)
6.3 投影: 从 3D 到 2D
- 视口: 显示的窗口区域,OpenGL使用
glViewPort
来设置视口 - 投影方式
- 正投影: 用来渲染平面图形(远近物体大小一样)
- 透视投影: 用来渲染立体图形(远小近大)
待抽空整理
objc
# 四、OpenGL
## 1. OpenGL 基础渲染
## 2. OpenGL 深度测试
## 3. OpenGL 基础变化
## 4. OpenGL 基础纹理
# 五、3D数学
## 1. 从坐标到向量
## 2. 从矩阵基础到矩阵与线性变换
## 3. 旋转矩阵原理
## 4. GLSL语法
# 六、OpenGL ES
## 1. 顶点着⾊器与片元着色器
## 2. 着⾊器渲染过程
## 3. 基本图形硬件流⽔线设计
## 4. ...
# 四、Metal
## 1. Metal 与 OpenGL ES 区别
## 2. Metal 与 Metal Kit 区别
## 3. Metal 与 OpenGL ES 对⽐比学习
## 4. Metal Shading Language
Metal 程序中的Metal 着色语言
## 5. Metal 向量和矩阵数据类型
推荐
-
- 红宝书 OpenGL Programming Guide,出到第八版
-
- 蓝宝书 OpenGL SuperBible,出到第六版
-
- OpenGL ES 开篇 : 以 Q&A 的形式,列举出在学习 OpenGL ES 之前会存在的一些疑惑。权衡是否该继续学习 OpenGL ES。
-
- OpenGL ES 基础概念:扫盲篇,先介绍一些必须了解的知识,便于之后能直接进入实战阶段。
-
- OpenGL ES 环境搭建:详解 OpenGL ES 接入方式,以最基础效果(设置背景色)来阐述。
-
- OpenGL ES 渲染基本图元:详细介绍可编程图形渲染管线是如何工作的。
-
- GLSL 详解(基础篇):详细介绍 OpenGL ES 2.0 着色器语言 GLSL 基础语法。
-
- GLSL 详解(高级篇):详细介绍 OpenGL ES 2.0 着色器语言高级特性。