OpenGL 渲染的基础
大纲:
1、CPU 和 GPU
2、计算机渲染原理
3、屏幕成像与卡顿情况
1、CPU 和 GPU
1.1、CPU(Central Processing Unit)
现代计算机整个系统的运算核心、控制核心。
处理依赖性非常高的事情
Control控制单元、ALU运算单元、Cache显存
1.2、GPU(Graphics Processing Unit)
可进行绘图运算工作的专用微处理器,是连接计算机和显示终端的纽带
处理依赖性非常低的事情,因为有非常多的计算单元高并发。
拥有更多的计算单元
2、计算机渲染原理
计算机的渲染,是通过CPU去计算然后一行一行的去扫描显示到显示器上,如果说这个屏幕上半部分正在扫描显示上一帧的位图数据,到下半部分的时候,帧缓存去完成了计算后新的帧缓冲区数据。那么下半部分显示的是新的位图数据,这样上下是对不上的,这就是屏幕撕裂
这种一行一行扫描显示利用的是人的视觉停留来完成显示。
屏幕撕裂原因:
屏幕的刷新频率是固定的(一般是60Hz)。如果显卡的输出高于60fps,刷新频率和输出频率不同步就会出现上面示意图的屏幕撕裂情况。
也就是说视频控制器的显示速度比不上GPU处理图形的速度。在GPU拿到位图数据之后,会通过GPU进行图形处理,然后显示到屏幕上。
GPU渲染成位图 -> 帧缓冲区 -> 显示控制器刷新 -> 屏幕。
详细一点是:
GPU渲染->存入帧缓存区-> 视频控制器 -> 读取帧缓存区信息 -> 数模转化(数字信号处->模拟型号) -> 逐行显示到屏幕上。
当前一帧缓冲区中的图像正在逐行的显示在屏幕上的时候(还未显示完),GPU新的图像已经处理完成要存入帧缓冲区。这个时候存入帧缓冲区会吧之前帧缓冲区内的内容清除掉,现在帧缓冲区里面剩下的就是新渲染的图像。屏幕显示逐行进行显示,现在这一屏幕还未进行完,是不会从头再来进行显示的,而是继续往下去逐行显示。这个时候屏幕的下边部分显示出来的就是新存入帧缓存区的图像跟上边的不是同一个图像,这种出现图像上下不一致的情况就是图片撕裂
如下是实际效果图:
为了解决屏幕撕裂,引入 双缓冲区(doubleBuffering)+ 垂直信号(vSync)技术。
3、垂直信号、双缓冲区及屏幕卡顿
3.1、双缓冲区
其实是两个帧缓冲区,屏幕想去读取一个缓冲区上的内容,系统这个时候回去渲染下一个要显示的内容并存放到梁歪一个帧缓冲区中。然后屏幕切换去读取先渲染后存放的缓冲区内的内容,系统继续渲染下一个要显示的内容,同步存放到之前的那个缓冲区。
例如:
GPU开辟A、B两个帧缓冲区。当GPU处理完一帧图像数据后存入A帧缓冲区,给A帧缓冲区加锁。屏幕开始读取A帧缓冲区数据,GPU处理完新的一帧数据,因为A有锁,就会存入B帧缓冲区并加锁。屏幕读取显示完A帧缓冲区后,A帧缓冲区解锁,去读B帧缓冲区
3.2、垂直信号(VSync)
为了解决屏幕撕裂的问题,引入了垂直信号的概念。也就是在CPU 和GPU 处理数据的时候,等待垂直信号,垂直信号到来的时候,CPU 和GPU 都处理完了,那么就去存入帧缓冲区,否者不会。
3.3、卡顿掉帧
垂直信号,对于屏幕撕裂是解决了,但会存在另一个问题,如果垂直信号到来的时候CPU 和 GPU两个没有都处理完的时候帧缓冲区中还是上一帧内容,并没有更新,显示出来还是上一帧内容。那么就认为是卡顿掉帧的情况
在iOS中,每一帧的处理时间是1/60 秒 (≈ 1.67ms )。垂直信号到来之后,如果上一帧已经完成,CPU会开始新一帧的计算,编解码工作,完成后将处理结果交给GPU,GPU在进行渲染等工作,完之后存入帧缓冲区。当下一个垂直信号到来的时候,如果前面CPU+GPU都处理完存入帧缓冲区了,就会去读取帧缓冲区中的内容逐行显示到屏幕上。如果垂直信号到来的时候CPU+GPU没有处理完那么帧缓冲区中存放的仍然是上一帧的数据,当前屏幕显示出来的也是上一帧的内容。因为我们看到的图像是没有变化的所以这个就是 卡顿 / 掉帧
卡顿的解决
为了尽可能减少掉帧问题,从而引入了三级缓存(目前苹果使用的是双缓冲区)。本质就是再增加一个离屏缓存区。
基本流程是,在显示A缓存区数据的时候,同时B和C缓存区会渲染下两帧的数据,周而复始的,CPU/GPU会不停的循环处理、渲染下两帧的数据,从而缓解掉帧的问题。
4、图像 / 图像的渲染流程
在显示器显示之前,必须完成从 数据 -> 位图 的渲染,最后才送交帧缓冲区等待显示。
顶点数据(存在内存中,CPU处理)-> 几何运算-> 光栅化-> 片元/像素 -> 位图 -> 显示
再详细的分解,就会如下如所示
- CPU 处理存储在内存中的顶点数据(数组)
- GPU 几何操作:将顶点数据进行顶点转换、坐标转换、旋转平移缩放或者光照计算等处理
- GPU 顶点着色器处理:将顶点转成图元
- GPU图元装配:连接信息线条
- GPU 光栅化处理转成栅格化数据
- GPU 片元着色器会对栅格化数据的每一个像素进行位运算,决定每一个像素的颜色