关注公众号

关注公众号

手机扫码查看

手机查看

喜欢作者

打赏方式

微信支付微信支付
支付宝支付支付宝支付
×

【技术解析】GPU如何实现三维渲染及非图形计算?(二)

2020.10.26

  视图(Viewport,或者视口)变换

  现在的实时渲染场景中包含的对象(模型)可以有很多个,但是只有被摄像机(或者说观察者,也即是设定的视角覆盖)的区域才会被渲染。这个摄像机在世界空间里有一个用来摆放的位置和面向的方向。

  

  为了实现接下来的投影、裁剪处理,摄像机和模型都需要进行视图变换这个操作,目的是将摄像机放置在坐标原点上,使其正对的方向为 Z 轴(负向),Y 轴指向上(上图是从摄像机正上方俯视,所以没法给出 Y 轴),X 轴指向右。

  顶点着色

  所谓着色就是指确定光照在物料上所呈现效果的操作,这类操作既可能运行于几何阶段的模型顶点上,也可能运行于光栅阶段的各个像素上,也就是所谓的顶点着色和像素着色。

  

  在顶点着色的时候,各个顶点需要存放若干个相关的物料数据,例如顶点位置、法线、色彩以及其他任何进行着色处理计算相关的数字信息。

  顶点着色的计算结果(可以是色彩、向量、纹理坐标以及任何其他着色数据)会被发送到光栅化阶段进行插值处理。

  投影

  在完成了着色处理后,渲染系统会把可视体转换为一个位于(-1, -1, -1)到(1, 1, 1)的单元立方体(unit-cube)中,这个立方体被称作正则观察体(canonical view volume),使用到的投影方式一般有两种:平行投影和透视投影。

  前一种主要在 CAD 等软件中使用,后一种因为模拟了我们人类的视觉体验,所以在游戏或者虚拟现实中经常使用:

  

  上图分别是一部 iPhone 6s Plus 以平行投影和透视投影的方式呈现在屏幕上的效果。

  三角形裁剪

  只有在可视体内的图元会被传送到在屏幕上绘制这些图元的光栅阶段,在进行裁剪动作的时候,如果图元有顶点落在可视体之外,裁剪的时候就会将可视体之外的这部分剪切掉并且在可视体与图元相交的位置生成新的顶点,而位于立方体外部的旧图元就会被抛弃掉。

  

  屏幕映射

  经过上一步裁剪后的位于可视体内的图元会被传递到屏幕映射阶段,此时的坐标信息依然是三维的。图元的 X、Y 坐标被变换到屏幕坐标系,屏幕坐标再加上 Z 轴坐标就被称作窗口坐标。

  

  我们假定场景要渲染到一个最小角落坐标为(x1, y1)和最大角落坐标为 (x2, y2)的窗口中,也就是 x1 《 x2,y1 《 y2。此时,屏幕映射执行的是一个缩放处理后的转换操作。Z 轴坐标并不受此操作的影响。

  现在,新的 x 轴、 y 轴坐标就是屏幕坐标,有对应的屏幕像素位置,不再是之前投影处理后的那个立方体所采用的映像坐标系统。

  光栅处理阶段要干些什么呢?

  在获得了经过变换和投影处理的顶点及其相关联的着色信息后,光栅化处理阶段的目的就是计算并设置好被对象覆盖区域的像素颜色。这个处理被称作光栅化或者扫描转换,也就是把二维坐标上包含深度(Z 轴)信息和各种相关着色信息的顶点到屏幕上像素的转换。

  

  这个处理阶段一般可以拆分为 4 个工位:

  1、三角形设定

  2、三角形遍历

  3、像素着色

  4、输出合并

  三角形设定

  这一步会进行三角形表面的微分以及其他关于三角形表面数据的计算,计算出来的数据会被用于扫描转换以及几何阶段所产生的各种着色数据的插值处理。在GPU上这一步会采用固定硬件功能单元来实现。

  三角形遍历

  这一步用作确定像素的中心是否被三角形覆盖 ,如果该像素被三角形覆盖的话,就会生成对应的片元(fragment)。

  查找哪些样本或者像素是否位于三角形内通常被称作三角形遍历或者扫描转换。

  每个三角形对应片元的属性都是由该三角形的三个顶点数据插值而成,例如片元的深度值以及来自几何阶段的着色数据。

  像素着色

  所有的逐像素(per-pixel)着色计算都在这一步执行,使用的输入数据是之前插值的着色数据。像素着色发送到下一个工位的计算的结果可能是一个色彩值也可能是多个色彩值。

  和三角形设定以及三角形遍历不同采用固定硬件功能单元不同的是,现在的像素着色都是由可编程的GPU内核执行。

  在像素着色所依赖的众多技术中最为重要的就是贴图(texturing),所谓贴图就是把一张或者多张图片“贴”到对象上。

  输出合并

  在这一步执行的操作主要是将之前步骤生成的色彩信息进行合并形成最终输出的像素色彩。

  用于存放像素色彩信息的缓存被称作色彩缓存,一般情况下是以红、绿、蓝三个色元的方式存放,此外还有一个用于存放像素对应深度信息值的深度缓存(一般采用 Z-Buffer)。

  

  在GPU中实现这一步的功能单元有几种叫法,例如 ROP、Output Merger 或者 Back-End。

  在这个阶段,Output Merger 会根据深度缓存(depth buffer 或者 Z-buffer)存放的深度信息判断是否更新色彩缓存中的色彩值。

  例如当前像素计算出来的深度值(例如是 0.1)比深度缓存中对应像素的值小(例如是 0.2),则表示当前像素的三角形比色彩缓存存放的像素所对应的三角形更靠近“摄像头”,于是GPU会对该图元的色彩进行计算并把新计算出来的色彩值和深度值更新到色彩缓存和深度缓存中,否则的话就不会更新当前像素的缓存。

  在整个场景完成渲染后,色彩缓存中存放的都是从摄像机视角位置看到的可视图元色彩值。

  这样处理的好处是三角形可以使用任意次序来渲染,但是如果图元或者说三角形是部分透明的话,则必须依照从远到近的三角形层次进行渲染。这是 Z-Buffer 的主要缺点之一。

  像素除了色彩缓存和深度缓存外,还有其他利用通道或者缓存的技术来用于过滤和捕捉片元(fragmet)信息。


推荐
关闭