正文
对于一个客户端开发来说,平时做的的最多的就是写页面,所以有必要了解从视图代码到图像显示到屏幕上的整个过程和原理。
下面以从视图代码到显示器图像的中间产物帧缓冲区图像位图为目标,分析从视图代码到帧缓冲区位图和从帧缓冲区位图到显示器图像这2个过程。 这里把这2个过程命名为:帧缓冲区数据怎么来的、帧缓冲区数据怎么用的。
帧数据怎么来的
帧数据产生主要分为2个阶段:把视图布局代码生成图像3D数据模型、把图像3D数据模型转成位图。
把视图布局代码生成图像3D数据模型
CPU创建视图对象,计算布局,生成图像3D数据模型,并将这个图像3D数据模型交给GPU图像处理器将它加工成页面展示的位图。
把图像3D数据模型转成位图
根据GPU的渲染流水线把这个步骤可分为六个步骤
第一步骤:顶点着色器(Vertex Shader)
GPU收到图像3D数据模型后,首先通过顶点着色器将3D图像模型计算成屏幕上展示的2D图像模型,并对顶点数据做一些处理。
第二步骤:形状装配(Shape Assembly),又称 图元装配
然后使用图元装配器将这些2D Vertex转成基本的图元信息,图元指屏幕中图像的基本表示单位(点,线,三角形)。
第三步骤:几何着色器(Geometry Shader)
然后将这些图元元素数组传递给几何着色器,由几何着色器根据图像效果生成更细微的图元信息,来表现图像效果。
第四步骤:光栅化(Rasterization)
然后使用光栅化将达到展示效果的图元信息转换成一系列的像素。转换成像素的规则是以三角形图元覆盖在屏幕像素图层上,按照每个像素中心是否在图元三角形的内层,在内侧的都被选中的成为图像像素,根据像素生成片段模型,每个片段模型存储了一个像素渲染所需要的所有信息。
第五步骤:片段着色器(Fragment Shader)
然后将这些片段数据传递给片段着色器,片段着色器会计算每个像素所在的坐标是否超出了屏幕展示之外,对于屏幕之外的像素直接剪裁掉,只留下对展示有用的片段,提示渲染效率。进行纹理处理,图像的创建是对顶点添加颜色显示图像细节。要想图像显得真实就需要足够多的顶点和颜色,这就很消耗性能,所以通常使用纹理来展示细节,纹理是一个2D图片,表现的是物体的颜色和材质。
第六步骤:测试与混合(Tests and Blending)
测试与混合,在一个UI页面中用两套对应关系的树,一个是视图树,一个图层树。对应稍微复杂一点的视图如:按钮,它里面可以设置背景色,标题,这两种属性在显示时是有上下级关系的。而GPU在往帧缓冲区通过画家算法做深度优先遍历不断绘制图形时,是以与视图树对应的图层树中的图层为单位的,所以再将图层绘制到帧缓冲区之前要把图层内的多层属性进行测试与混合。
测试与混合阶段的操作内容是根据每个像素片段的深度和alpha值进行计算,像素深度Z在上面的显示,下面的忽略。像素alpha值小于1的则会对应上下两个深度的像素进行混合计算,得出要展示的像素效果。
经过这2个阶段,GPU得到了整棵图层树的位图,为后面往帧缓冲区做画家算法深度优先绘制提供了位图数据。
帧数据怎么用的
帧缓冲区中数据的使用对应的就是屏幕图像显示原理了,屏幕图像显示的原理是和CRT 显示器原理一样的。
CRT 显示器原理
CRT电子枪从上到下进行逐行扫描,当一行像素扫描完后电子枪换行到下一行等待显示器时钟发送水平同步信号HSync,等收到HSync信号后开始扫描,扫描完成后换行到下一个行,继续等待水平同步信号。当一帧页面显示完成后,扫描枪会回到屏幕开始的位置等待显示器时钟发送垂直同步信号VSync, 等收到垂直同步信号后先进行双帧缓冲区交互,然后通知CPU,GPU开始渲染下一帧数据,然后再开始新一轮的帧画面的扫描。HSync水平同步信号和VSync垂直同步信号是为了同步显示器的显示过程和系统视频控制器的读取过程的。
显示器以固定的频率进行刷新,这个固定频率就是VSync垂直同步信号的频率。
CPU,GPU,显示器协调工作模式
CPU通过视图创建,布局计算,文本渲染生成图像3D数据模型传给GPU。GPU将这些3D图像模型数据转成屏幕2D图像模型,然后经过GPU渲染流程生成位图放入帧缓冲区。视频控制器读取帧缓冲区的数据,通过数模转换显示到屏幕上。
双缓存机制
在屏幕图像显示机制中最简单的是使用一个帧缓冲区,但会有性能问题,显示器读完一帧位图后,GPU才能渲染下一帧位图数据往帧缓冲区里放。这里引入双缓冲区机制,GPU先往第一缓冲区中写入一帧位图,等显示器读完第一个缓冲区数据时,GPU开始渲染下一帧数据往第二缓冲区写入,等第一帧图像渲染完成,视频控制器会直接交互指针,将指针指向第二缓冲区,然后重复这一个过程。
图像撕裂问题
引入了双缓存区后,图像显示效率提升了,但是又带来了一个新问题:图像撕裂。
当视频控制器读取到第一个帧缓冲区数据一半时,此时GPU写入第二帧缓冲区位图数据结束,并进行了缓冲区指针交互。此时屏幕的下半部分就显示的第二帧的图片,造成了图像上下部分不一致。为了解决这个问题,采用了时钟垂直信号机制,当视频控制器完成一帧扫描后回到初始位置,此时要等待VSync垂直信号,只有收到VSyn信号后,才会进行帧缓冲区指针的交互,然后开始显示下一帧数据同时GPU开始渲染后面一帧的位图数据。
CPU与GPU
CPU(Central Processing Unit)中央处理器:是计算机系统的控制单元和计算单元,可用于处理复杂的逻辑,拥有一定的并行计算能力。
GPU(Graphics Processing Unit)图像处理器:是用于绘图计算的图像处理器,能够生成2D/3D图像和视频,有非常强大的并行计算能力。
为什么要使用GPU作为图像的专门处理器呢,因为一个屏幕上的像素点是非常多的,在规定的时间内1/60s计算每一个像素点的样式是对并行计算的要求非常高,所以需要并行计算能力强的GPU来专门处理图像的计算工作。
GPU的内部层级结构。最底层是计算机的系统内存,其次是GPU的内部存储,然后依次是二级缓存L2,一级缓存L1。
GPU编程
OpenGL与DirectX 都一套可以对GPU进行调用的API。
GPU 及其相关驱动实现了图形处理中的 OpenGL 和 DirectX 模型,所以开发者可以通过调用这些API直接操作硬件。
OpenGL 严格来说并不是常规意义上的 API,而是一个第三方标准,它定义了每个函数该如何执行,以及它们的输出值。它的内部具体实现则是由 OpenGL 库的开发者自行决定。通常OpenGL 库的开发者通常是显卡的生产商。
DirectX 则是由 Microsoft 提供一套第三方标准。
名称解释
渲染:将代码中的图像模型(光照,纹理等信息)转化成图像的过程。
绘制:用工具,画笔画图的过程。
纹理:物体表面材质的凸凹波纹和颜色。
图片解码与编码:将本地图片(png, jpg)文件读取到内存,生成对接图像对象叫解码;反过程保存到本地叫编码。
图元:计算机中表现图像的基本元素,点(一个Vertex),线(二个Vertex),面(三个Vertex)。屏幕上展示的各种2D, 3D图像都是用这三种基本元素表示的。
Vsync垂直信号:电子枪从帧缓冲区将位图取出逐个扫描到显示器结束后,屏幕控制芯片DAC会发出一个Vsync垂直时钟信号,此时会触发2件事,1.系统会从当前帧缓冲区读取新的图像属性扫描显示到屏幕上,2.CPU+GPU会开始绘制下一帧图像数据绘制。
位图:GPU渲染完成后的产物,里面的每个单位颜色对应的是屏幕上的一个像素点。
位图中的像素有深度的概念,比如一个位图有m*n个像素,每个像素可以用1,2,4,8位字节进行表示,使用的字节数越多能表示的颜色值(如RGB)就越多,图像就越逼真。
参考文章: