图像渲染原理

如题所述

第1个回答  2022-07-29

最底层是图形硬件(GPU);上层是Metal和CoreGraphics,提供一些接口来访问GPU;再上层的CoreAnimation是OpenGL ES和Metal在窗口显示的载体,在此基础上封装了一套动画的API。最上面的UIKit属于应用层,处理与用户的交互。

总结一下具体流程如下:

几种不同类型的屏幕缓冲:用于写入颜色值的颜色缓冲,用于写入深度信息的深度缓冲,以及允许我们基于一些条件丢弃指定片段的模板缓冲。把这几种缓冲结合起来叫做 帧缓冲 ,它被储存于内存中。 OpenGL 给了我们自己定义帧缓冲的自由,我们可以选择性的定义自己的颜色缓冲、深度和模板缓冲。

虽然帧缓冲区的名称中包含了一个“缓冲区”字眼,但是其实他们根本不是缓冲区。实际上,并不存在与一个帧缓冲区对象( FBO )相关联的真正内存存储空间。相反,帧缓冲区对象( FBO )是一种容器,它可以保存其他确实有内存存储并且可以进行渲染的对象,例如纹理或渲染缓冲区。采用这种方式,帧缓冲区对象( FBO )能够在保存 OpenGL 管线的输出时将需要的状态和表面绑定到一起。

我们目前所做的渲染操作都是是在默认的帧缓冲之上进行的。当你创建了你的窗口的时候默认帧缓冲就被创建和配置好了( GLFW 为我们做了这件事)。通过创建我们自己的帧缓冲我们能够获得一种额外的渲染方式。

你也许不能立刻理解应用程序的帧缓冲的含义,通过帧缓冲可以将你的场景渲染到一个不同的帧缓冲中,可以使我们能够在场景中创建镜子这样的效果,或者做出一些炫酷的特效。

渲染缓冲对象(RBO) 是一种图像表面,它是专门为了绑定到 FBO 而设计的。它可以是一个颜色表面、模板表面、或者深度/模板组合表面。也是一个缓冲,它可以是一堆字节、整数、像素或者其他东西。渲染缓冲对象的一大优点是,它以 OpenGL 原生渲染格式储存它的数据,因此在离屏渲染到帧缓冲的时候,这些数据就相当于被优化过的了。

渲染缓冲对象(RBO) 将所有渲染数据直接储存到它们的缓冲里,而不会进行针对特定纹理格式的任何转换,这样它们就成了一种快速可写的存储介质了。然而,渲染缓冲对象通常是只写的,不能修改它们(就像获取纹理,不能写入纹理一样)。可以用glReadPixels函数去读取,函数返回一个当前绑定的帧缓冲的特定像素区域,而不是直接返回附件本身。

因为它们的数据已经是原生格式了,在写入或把它们的数据简单地到其他缓冲的时候非常快。当使用渲染缓冲对象时,像切换缓冲这种操作变得异常高速。我们在每个渲染迭代末尾使用的那个 glfwSwapBuffers 函数,同样以渲染缓冲对象实现:我们简单地写入到一个渲染缓冲对象,最后交换到另一个里。渲染缓冲对象对于这种操作来说很完美。

当我们使用单缓冲区的时候,帧缓存区里面是旧的数据,显示在屏幕上,GPU显示的时候是逐行扫描显示的,显示到一半的时候,然后又来了下一帧的数据,然后显示到屏幕上,所以就会出现下图所产生的屏幕撕裂。

这样屏幕撕裂问题解决了,说那是又会出现一个新的问题—— 掉帧

当我们启用了 垂直同步Vsync + 双缓冲区 DoubleBuffering 的时候,当我们接收到 垂直信号Vsync 的时候, CPU GPU 还没有准备好图片数据,所以视频控制器拿不到帧缓冲数据(Frame Buffer),所以就会出现 掉帧 现象。

三缓冲区使用一个前置缓存和两个后置缓存。在着色完第一个后置缓冲区的数据后,立即开始处理第二个后置缓冲区。就是 A数据 显示到屏幕上,两个后置缓冲区会帮我们去渲染 B数据 C数据 。但是即便这样,也还是有可能出现掉帧的,不过其掉帧几率会比双缓冲区好很多。

相似回答