OpenGL(3)-渲染浅析

CPU&GPU

CPU

中央处理器(Central Processing Unit),作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU是计算机中负责读取指令,对指令译码并执行指令的核心部件。

CPU主要包括两个部分,即控制器、运算器,其中还包括高速缓冲存储器及实现它们之间联系的数据、控制的总线。

根据冯诺依曼体系,CPU的工作分为5个阶段:取指令阶段、指令译码阶段、执行指令阶段、访存取数和结果写回。

GPU

图形处理器(Graphics Processing Unit),是一种专门做图像和图形相关运算工作的微处理器。GPU使显卡减少了对CPU的依赖,并进行部分原本CPU的工作,尤其是在3D图形处理时GPU所采用的核心技术有硬件T&L(几何转换和光照处理)、立方环境材质贴图和顶点混合、纹理压缩和凹凸映射贴图、双重纹理四像素256位渲染引擎等。

图形处理器由以下器件组成:

  • 显示主芯片显卡的核心,俗称GPU,它的主要任务是对系统输入的视频信息进行构建和渲染。
  • 显示缓冲存储器用来存储将要显示的图形信息以及保存图形运算的中间数据,显示缓存的大小和速度直接影响着主芯片性能的发挥。
  • RAMD/A转换器把二进制的数字转换成为和显示器相适应的模拟信号。

渲染流程

早期,人们对像素的操作实际上仅仅能够称之为染色,对特效的处理只能通过固定的单元来实现,而对于像素的处理,也仅能局限与固化指令所能够允许的范围内,这种渲染流程也称之为传统渲染流程。随着技术的发展,可编程着色器诞生了,可编程着色器的渲染流程更加复杂,更加的多元化,渲染的过程中能实现更强大的功能。

传统渲染流程

传统的渲染流程包括几何处理阶段(Geometry Stage)和光栅化阶段(Rasterization Stage)。

几何处理阶段又称为T&L(transforming & lighting)阶段,主要负责将3D坐标系中的顶点(vertex)转换成2D坐标系中的点(transforming阶段)、并且对顶点做初步光照计算(lighting阶段)。通过几何阶段的处理,就可以得到初步的2D图像的骨架。

显示器实际显示的图像是由像素组成的,我们需要将上面生成的图形上的点和线通过一定的算法转换到相应的片元(fragment)。把一个矢量图形转换为一系列片元的过程就称为光栅化。一个片元就是一个数据结构,这个数据结构中包含位置、颜色、深度等信息。然后对这些片元进行贴图融合、光照计算、或者雾化等其他操作以形成最终图片中的像素。之后对这些像素做最后的缩放和抗锯齿处理,形成最终的图像。

可编程着色器的渲染流程

可编程渲染流程与传统渲染流程不同的是,顶点着色器(Vertex Shader)和片元着色器(Fragment Shader)是可编程的。

可编程着色器下的渲染流程.jpg
  • 顶点着色器主要的目的是把3D坐标转为另一种3D坐标,同时顶点着色器可以对顶点属性进行一些基本处理。
  • 图元(primitive)装配将顶点着色器输出的所有顶点作为输入,并将所有的点装配成指定图元的形状。
  • 光栅化把图元映射为最终屏幕上相应的像素,生成片元。
  • 片元着色器会对输入的片段进行裁切(Clipping)。裁切会丢弃超出视图以外的所有像素,用来提升执行效率。

屏幕图像显示原理

CRT显示器原理

屏幕图像显示的原理,需要先从CRT显示器原理说起,如下图所示。CRT的电子枪从上到下逐行扫描,扫描完成后显示器就呈现一帧画面。然后电子枪回到初始位置进行下一次扫描。为了同步显示器的显示过程和系统的视频控制器,显示器会用硬件时钟产生一系列的定时信号。当电子枪换行进行扫描时,显示器会发出一个水平同步信号(horizonal synchronization);而当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号(vertical synchronization)。显示器通常以固定频率进行刷新,这个刷新频率就是垂直同步信号产生的频率。后面出现的液晶屏,显示原理也类似。

ctr显示原理.png

CPU、GPU、显示器工作方式

CPU计算好显示内容提交至GPUGPU渲染完成后将渲染结果存入帧缓冲区,视频控制器会按照垂直同步信号逐帧读取帧缓冲区的数据,经过数据转换后最终由显示器进行显示。最初的时候,帧缓冲区只有一个,此时,帧缓冲区的读取和刷新都都会有比较大的效率问题。CPU的计算和GPU的渲染都是需要时间,如果只有一个缓存区,屏幕的显示就需要等待。为了解决效率问题,GPU通常会引入两个缓冲区,这就是双缓冲机制。在这种情况下,GPU会预先渲染一帧放入一个缓冲区中,用于视频控制器的读取。当下一帧渲染完毕后,GPU会直接把视频控制器的指针指向第二个缓冲器。

显示原理.jpg

画面撕裂

我们知道显示器都有一个自己的刷新频率,比如60Hz的显示器一秒钟就是刷新60张图片。根据画面的复杂度不同,GPU输出渲染结果的时间是不定的。所以双缓冲机制也带来了一个问题,那就是输入渲染结果的速度超过显示器的显示速度。比如,我们需要在显示器上逐次显示1、2、3。GPU绘制完1会先将结果输出到前缓冲区,然后接着绘制2将结果输出到后缓冲区,假如显示器还在逐行扫描显示1的时候,GPU已经绘制完了2,此时GPU就会接着绘制3,绘制完之后就会把结果覆盖前缓冲区中的1,这个时候显示器上部分就会显示1,而下部分读取到数据则是3,就会出现上面是1下面是3的情况。这种情况就是撕裂。

为了解决撕裂问题,就需要用到我们上面所说的垂直同步信号,GPU会等待显示器的垂直同步信号发出后,才进行新的一帧渲染和缓冲区更新。也就是在显示完1的时候,发出一个信号,然后GPU再去绘制3。但是垂直同步信号需要消耗更多的计算资源,也会带来部分延迟。比如说当我们移动了鼠标,这时候,电脑收到这个消息,直接把鼠标移动的距离输出给GPUGPU完成绘制后,把鼠标移动这个画面输出给显示器,那么这里就是瞬间完成,所有的请求都不会被延后,延迟就是电路延迟而已。

但是如果你开了垂直同步,GPU绘制完成后缓冲后,显示器还没显示完前缓冲,GPU只能在这里等着,那么鼠标移动的指令会和GPU一起等着,直到显示器绘制完成前缓冲,移动鼠标这个画面才会被写入显示器后缓冲。这样就增加了延迟。

掉帧

另外,垂直同步还会带来一个问题,即掉帧。由于垂直同步信号是和显示器的刷新频率相关的,比如说每秒60fps的刷新频率,每隔16.7ms就会有一次垂直同步信号,如果CPUGPU工作的总耗时超过16.7ms,也就是说GPU未能在规定时间内输出绘制的内容,显示器就会保留当前的内容不变,而且会丢弃当前绘制的这一帧内容,这就是掉帧。

解决掉帧问题可以从两个方面入手:

  1. 降低所需要渲染的图片的复杂度
    • 使用较小的纹理尺寸
    • 尽量减少视图数量和层次
    • 尽量减少使用透明的视图
    • 尽量避免离屏渲染
  2. CPUGPU的硬件出发,提升硬件的品质。

你可能感兴趣的:(OpenGL(3)-渲染浅析)