1. 图形API简介
-
OpenGL
是一套跨平台,跨编程语言的图形程序接口,是一种可以对图形硬件设备特性进行访问的软件库。OpenGL
不能开发程序,构建后台,它只是一套处理图形图像的统一规则。 -
OpenGL ES
是OpenGL
的子集,是针对手机和游戏主机等嵌入式设备而设计,去除了许多不必要和性能较低的API
接口 -
Metal
是苹果为了解决3D渲染而推出的框架,该技术能为3D图形提高10倍的渲染性能。2014年之前苹果一直是使用OpenGL ES
来处理底层渲染,之后慢慢的把渲染框架迁移成Metal
。到iOS12苹果已经弃用了OpenGL
,完全实现Metal
渲染底层
既然苹果底层已经放弃OpenGL
,是否意味着相关的图形开发者也要放弃OpenGL
,转投Metal
的怀抱呢?
其实不是的,主要有以下原因:
Metal
的核心处理思想还是源于OpenGL ES
OpenGL ES
是高度集成和封装的且系统有对应的GLKit
相关API
,来辅助开发者能快速使用OpenGL ES
- 苹果只是系统底层渲染放弃
OpenGL
,并没有不让开发者使用,因为OpenGL
是跨平台的且相当稳定,目前的Metal
还做不到这些
所以做为iOS
开发者,OpenGL
和Metal
都是需要学习的。普遍的学习方式也应该是OpenGL -> Metal
。
OpenGL有客户端和服务端的概念。编写的应用程序可以看作是客户端,计算机图形硬件厂商所提供的OpenGL实现可以看作是服务端。
复制代码
2.图形API的作用
日常开发中,开发者一般通过使用上层API
来构建和绘制界面,而调用API
时,系统最终就是通过OpenGL/Metal
来实现视图的渲染。
当然,开发者也可以通过主动使用OpenGL/Metal
来利⽤GPU
芯⽚⾼效渲染图形图像达到一些特殊的需求。
OpenGL
中涉及很多相关的专有名词,掌握专有名词的必是开启OpenGL
之旅的第一站。
3. 相关名词解析
- OpenGL状态机
状态机是一个抽象的模型,表示一组状态变量的集合。OpenGL
使用状态机来保存所有的状态变量。当一个状态变量被修改后,它会一直保持这个状态,直到再次修改它的状态。
可以使用函数很简单的对某个状态做打开,关闭,查询操作,以深度测试为例:
glEnable(GL_DEPTH_TEST); 打开深度测试
glDisable(GL_DEPTH_TEST);关闭深度测试
glIsEnabled(GL_DEPTH_TEST);是否打开深度测试
复制代码
不能因此把状态机理解成某个功能的开关,因为不是所有的状态变量都只是简单的关闭和打开。状态机还可以接受某种预定模型,枚举值,各种常见数据类型等。
在程序退出前,状态机总会先停止工作。
- 渲染
把图形数据转换成2d空间图像(显示在屏幕上)的操作叫做渲染
- 渲染管线
管线是个抽象的概念,就像工厂的流水线一般,生产产品是需要按照既定步骤和节点来的。显卡在处理数据的时候也是按照一个固定的顺序来的,而且严格按照这个顺序。OpenGL
渲染图形也是按照既定的步骤步步成型的。
如图所示,就是OpenGL
的管线及其各个步骤。
- 固定管线
固定管线
就像调用系统API
一样,只需要传入参数,管线就会按照默认的配置开始工作,得到输入对应的输出,快速完成图形渲染。这种情况我们往往不用关心它的底层实现。OpenGL
的使用场景非常丰富,固定管线无法完成每一个业务.这时相关部分就被开放成可编程管线。
- 可编程管线
可编程管线
不是调整渲染管线步骤,渲染管线的步骤是不可改变的(增加步骤,删除步骤,改变步骤顺序都不行)。可编程管线
只是对顶点着色器
和片元着色器
的操作可编程,开发者可以使用GLSL
语言自定义两者的处理逻辑。
- 顶点数组和顶点缓冲区
顶点指的是渲染图形时的顶点数据,它决定图像的位置,但是不决定图像的形状。
顶点数组
和顶点缓冲区
都是用来存储顶点数据的,区别在于,顶点数组把顶点数据存在内存
中,顶点缓冲区把顶点数据存在显存
中。
OpenGL
是驱动GPU
来工作,GPU
的计算速率也大大高于CPU
,所以,顶点数据存在顶点缓冲区
是更常用的手段。但是数据不会自动进入,开发中需要调用函数将数据拷贝到顶点缓冲区
。
拷贝到顶点缓冲区的通道默认是关闭的,需要使用glEnableVertexAttribArray()打开通道
- 顶点着色器
顶点着色器
处理从客户端输入的数据,应用变换(平移,旋转,缩放等),或者进行其他类型的数学运算来计算光照效果,位移,颜色值等。因此,顶点着色器
可能很简单也可能很复杂(比如最简单的值传递)。
对于绘制命令传输的每个顶点,OpenGL
都会调用顶点着色器来处理顶点相关的数据。不用担心存在大量顶点的效率问题,它是并行计算的。顶点着色器
的输出是片元着色器
的输入。
顶点着色器是可编程的两个着色器之一。
- 图元装配
在OpenGL
中,有3种类型的图元:点、线、三角形。图元装配决定顶点的连接信息,进而决定图像的形状。
图元 | 描述 |
---|---|
GL_POINTS | 每个顶点在屏幕上都是单独点 |
GL_LINES | 每⼀对顶点定义⼀个线段 |
GL_LINE_STRIP | 从第⼀个顶点依次经过每⼀个后续顶点⽽绘制的线条 |
GL_LINE_LOOP | 从第⼀个顶点依次经过每⼀个后续顶点⽽绘制的线条,并且连接第一个和最后一个顶点 |
GL_TRIANGLES | 每3个顶点定义⼀个新的三⻆形 |
GL_TRIANGLE_STRIP | 共⽤⼀条边上的顶点的⼀组三⻆形 |
GL_TRIANGLE_FAN | 以⼀个圆点为中⼼呈扇形排列,共⽤相邻顶点的⼀组三⻆形 |
三角形是较常用的连接方式。GL_TRIANGLES
和GL_TRIANGLE_STRIP
都可以绘制出四边形。它们的区别在于GL_TRIANGLES
需要六个顶点数据,GL_TRIANGLE_STRIP
共用两个顶点,只需要四个顶点数据即可。所以,两者都能用时通常使用GL_TRIANGLE_STRIP
提高渲染性能。
需要注意的是,OpenGL不存在正方形图元,正方形需要两个三角形图元组成。
- 裁剪
顶点可能会落在视口之外,视口就是可绘制的窗口区域,此时与顶点相关的图元会做出改动,保证相关的像素不会在视口外绘制。默认情况下,裁剪框与窗口同等大小,并且不会进行裁剪测试。我们可以指定裁剪框的大小,框外的内容不会被绘制。
- 光栅化
裁剪之后就需要做光栅化
的操作,就是将更新后的图元传递到光栅化单元,生成对应的片元。它决定窗口坐标中哪些栅格图元要被占用,就是像素点的范围。
简单来说,光栅化
就是把物体的数学描述以及与物体相关的颜⾊信息转换为屏幕上⽤于对应位置的像素及⽤于填充像素的颜⾊。
光栅化是
OpenGL
自动完成的,开发者无法影响。
- 片元着色器
通过光栅化产生的片元,需要通过片元着色器
确定最终显示在屏幕上的每个像素点的颜色值
和深度值
。通常来说,片元的个数是远大于顶点的个数,所以它也是并行计算的。
如果说顶点着色器
决定图形在屏幕上的位置,那片元着色器
是决定每个片元的显示属性(不一定是最终屏幕上的显示属性)。
片元着色器是可编程的两个着色器之一。
- 纹理
纹理就是图片,不过在OpenGL
中称为纹理,而不是图片。在进行渲染的时候,除了指定颜色值渲染,为了让结果更逼真,也可以使用纹理。
OpenG
L中纹理格式为tga
,OpenGL ES
中使用普通的PNG
,JPG
解压即可。
- 测试
经过片元着色器
得到的像素数据,需要经过测试,决定哪些数据可以被提交到帧缓冲区
。这些测试可以通过状态机来关闭和开启。测试发生的顺序如下:并且当前面的测试已经丢弃片元后,不会继续执行后面的测试。
① 裁剪测试:丢弃指定窗口之外的像素。默认情况下裁剪矩形和视口大小的一致的,并且默认是关闭裁剪的。
② 模版测试:通过模板测试程序去决定最终的像素是否丢弃。只有在建立窗口的过程中预先请求模版缓存才能够使用模版测试,否则模版测试总是通过的。
③ 深度测试:同一像素点可能存在多个颜色值,需要根据深度(离屏幕的远近)决定剔除哪个像素。
一般默认是离屏幕较近的像素保留,离屏幕较远的像素丢弃。
复制代码
- 混合
测试通过后,如果片元没有被丢弃。那么此片元的颜色(目标颜色
)将会和已经在帧缓冲区中(如果有的话)的颜色(源颜色
)进行混合计算,计算可以通过传入指定的参数到混合方程式
,也可以自定义混合方程式
。
通常来说,使用的固定的混合方程式即可。因为混合的结果基本区分不出来,大家也不关心混合的结果是什么。
- 帧缓冲区
帧缓冲区
就是显存
,也被叫做帧缓存
,它的作用是用来存储显卡芯片处理过或者即将提取的渲染数据。如同计算机的内存一样,显存是用来存储要处理的图形信息的部件。
最终”存活”下来的像素需要被显示到屏幕上,但是显示屏幕之前,这些像素是会被先提交在帧缓冲区
的。帧缓存区
的每一存储单元对应屏幕上的一个像素,整个帧缓存区
对应一帧图像。
在下一个刷新频率到来时,视频控制器
会把帧缓冲区
内的内容映射到屏幕上。iOS采用双缓冲机制
,存在两个帧缓冲区
。
4.渲染步骤总结
顶点数据
被提交到顶点缓冲区
,应用变换等操作计算出顶点的对应位置,根据预先定义好的图元装配
方式连接各个顶点,从而确认图像的形状,窗口区域之外的顶点会被裁剪
,不进入后续流程。形成的图像范围需要光栅化
,光栅化
的产物是片元,片元数据被提交到片元着色器
,片元着色器
计算每个像素的显示属性,然后开启测试
,确认哪些像素被保留,哪些被丢弃,通过测试
的片元直接绘制到帧缓冲区
,如果开启了混合
,片元的颜色会和该像素的当前颜色叠加,形成新的颜色写入帧缓冲区
。帧缓冲区
的内容依靠视频控制器
的刷新映射到显示器上。
顶点着色器
和片元着色器
需要我们重点关注,因为它们属于可编程着色器,一般是需要我们自行处理的。 顶点着色器决定一个图元应该位于屏幕的什么位置,而片元着色器决定某个片元的颜色应该是什么
5.写在后面
OpenGL
的渲染流程及其相关名词是图形图像学习的第一阶段,搞不懂这些术语在后续的学习或者看相关书籍的时候,必然是一头雾水。
下一章是OpenGL
系列的屏幕成像和渲染原理解析
。敬请关注。