与普通情况下 GPU 直接将渲染好的内容放入 Framebuffer 中不同,离屏渲染需要先额外创建离屏渲染缓冲区 ,将提前渲染好的内容放入其中,等到合适的时机再将 Offscreen Buffer 中的内容进一步叠加、渲染,完成后将结果再写入 Framebuffer 中。
为什么先要将数据存放在离屏渲染缓冲区呢?有两个原因,一个是被动的,一个是主动的。
- 一些特殊效果需要使用额外的 Offscreen Buffer 来保存渲染的中间状态(被动)
- 处于效率目的,可以将内容提前渲染保存在 Offscreen Buffer 中,达到复用的目的。(主动)
透明、阴影加圆角通常被称为 UI 三大宝,但这些效果在 iOS 的日常开发过程中却往往会导致被动的离屏渲染,下边是几个常见的会触发被动离屏渲染的场景。
触发离屏渲染的原因讲离屏渲染的原因不得不提画家算法,画家算法的整体思想是按层绘制,首先绘制距离较远的场景,然后用绘制距离较近的场景覆盖较远的部分。这里的层在 iOS 的渲染技术栈中就可以被对应到 layer。
通常对于每一层 layer,Render Server 会遵循“画家算法”,按次序输出到 frame buffer,后一层覆盖前一层,就能得到最终的显示结果,对于这个 layer 树则是以深度优先的算法将 layer 输出到 frame buffer。
作为“画家”的 GPU 虽然可以一层一层往画布上进行输出,但是却没有办法在某一层渲染完成之后,再回过头来改变其中的某个部分。因为在这一层之前的若干层 layer 像素数据,已经在渲染中被合成在一起了。其实这里和 photoshop 中的图层合并非常像,一旦多个图层被合并在一起,就无法再单独对某一个图层进行修改。所以需要在离屏缓冲区中把子 layer 依次画好,然后把四个角裁剪好之后再和之前的图层进行混合。