zoukankan      html  css  js  c++  java
  • 渲染管线

    2.1为什么要介绍渲染管线?

      在微软DirectX10.0规范的统一渲染架构公布以前。渲染管线以前是选购显卡的一项重要指标。然而採用流处理器渲染架构,由于硬件工作效率更高,眼下已经逐渐代替了採用渲染管线的传统架构,在消费领域渲染管线的概念慢慢被淡化了。

    可是在计算机图形学领域,渲染管线却依旧有着举足轻重的地位。由于它依旧是实时渲染的基本原理。尽管在上一章提到了渲染管线这一概念,但并没有给出具体的解释。在这一章我要对渲染管线进行一个深入的分析。

    2.2什么是渲染管线

      渲染就是把3D场景转换到屏幕上2D图像的一个处理过程。

    这里写图片描写叙述
    3D渲染过程

      有了渲染概念,渲染管线的概念就更加清晰了,它是显示芯片内部处理图形信号相互独立的的并行处理单元。每一个阶段从上一个阶段接收输入。处理完毕后输出到下一个阶段,整个过程就是为了完毕一帧画面渲染。在某种程度上能够把渲染管线比喻为工厂里面常见的各种生产流水线,工厂里的生产流水线是为了提高产品的生产能力和效率,而渲染管线则是提高显卡的工作能力和效率。
      在这里还得解释一下渲染管线和GPU渲染管线的关系。

    在GPU问世的初期,处理能力非常有限。渲染管线非常大程度上依赖于CPU,整个管线的任务是由CPU和GPU共同协作完毕的。

    当然随着GPU日益强大,GPU承担了管线中全部的任务,所以如今渲染管线这一概念就等同于GPU渲染管线了。

    2.3渲染管线的结构

      在Real-Time Rendering一书中,作者把渲染管线分成了三个阶段:应用程序阶段、几何阶段以及光栅阶段。


      应用程序阶段。使用高级编程语言进行开发,主要和CPU 、内存打交道。诸如碰撞检測、场景图建立、空间八叉树更新、视锥裁剪等经典算法都在此阶段执行。

    在该阶段的末端,几何体数据(顶点坐标、法向量、纹理坐标、纹理等)通过数据总线传送到图形硬件。


      几何阶段,主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,该阶段基于 GPU 进行运算,在该阶段的末端得到了经过变换和投影之后的顶点坐标、颜色、以及纹理坐标。
      光栅阶段,基于几何阶段的输出数据,为像素正确配色,以便绘制完整图像。该阶段进行的都是单个像素的操作,每一个像素的信息存储在帧缓存中。
      可是我并不全然认同Real-Time Rendering中的阶段划分。眼下主流的阶段划分方式仅仅有后面两个阶段。

    尽管应用程序阶段是图形渲染的重要一环,可是它处理的任务仅仅是优化渲染过程的输入数据以及相关逻辑处理。并非真正的核心的渲染过程,并且该过程主要在CPU中完毕。所以在接下来我将具体地阐述这两个阶段的过程。
      渲染管线依据硬件架构的不同分为固定渲染管线和可编程渲染管线,焦点在于GPU是否具有可编程性。

    2.4固定渲染管线

      在可编程渲染管线出现之前,渲染管线就是指固定渲染管线,后来为了便于区分才加入了“固定”二字。固定渲染管线具备了渲染管线流水线作业的优势,将复杂的过程分解成小的阶段,几何数据按工作流程依次经过各个阶段的处理。大大增强了渲染作业的处理效率。

    同一时候几何阶段和光栅阶段算法都是固化在GPU中。编程人员在开发时无须关注几何阶段的各种变换算法以及光栅阶段的着色算法。开发效率大幅提高。图2- 2展示了固定渲染管线的整个流程。

    这里写图片描写叙述
    固定渲染管线流程

    2.4.1几何阶段

      几何阶段的主要工作就是三维顶点坐标变换和光照计算。由显卡中的“T&L”硬件来完毕。


      什么是“T&L”硬件?“T&L”英文全称是“Transform&Lingting”。中文意思几何变换和光照。“T&L”硬件事实上一个硬件级别的几何与光照转换引擎。它在GPU中的出现,使得CPU从复杂运算中解脱出来。

    这样一来。一个场景中能够加入很多其它的物体和几何细节,终于渲染效果更加细腻,同一时候渲染效率也大幅提升。
      那么为什么须要进行三维顶点坐标的变换?原因非常简单。我们的真实世界是一个三维的空间,而显示屏幕是二维的平面,为了将三维的数据更加真实地绘制到屏幕上。并达到“跃然纸上”的效果。我们就须要顶点变换。通过一系列顶点变换,物体在世界空间被转换到屏幕空间。


      依据顶点坐标变换的先后顺序,主要有这样几个坐标空间:物体空间、世界空间、观视空间以及屏幕空间。

    物体空间到世界空间

      物体空间的是一个相对独立的局部空间。与其它物体没有不论什么參照关系。物体空间中的坐标都是在3DS MAX这类建模工具中生成的。
      而世界空间与物体空间的关键差别就在于前者中全部的物体把须要坐标原点作为參考点。物体导入场景中之后,须要为物体指定一个位置。这个位置就是物体在世界空间的一个全局坐标。物体空间到世界空间的变换由一个一个四阶矩阵来完毕,称作世界矩阵。
      光照计算一般是在世界坐标空间中进行的,这也符合人类的生活常识。当然。也能够在观视空间中得到相同的光照效果,由于,在同一观察空间中物体之间的相对关系是保存不变的。


    在这里有一点非常重要。

    就是物体顶点的法相量是在物体空间中生成的。它也是须要变换到世界空间才干正常使用。和顶点坐标相似。可是二者的转换矩阵却是不一样的。法向量变换的矩阵是世界矩阵转置的逆矩阵。在固定管线中,尽管这一变换不须要我们手动完毕,可是理解清晰对于后面的可编程管线非常重要。

    世界空间到观视空间

      每一个人都是从各自的视点出发观察这个世界,不管是主观世界还是客观世界。相同,在计算机中每次仅仅能从唯一的视角出发渲染物体。

    在游戏中。都会提供视点漫游的功能,屏幕显示的内容随着视点的变化而变化。这是由于GPU 将物体顶点坐标从世界空间转换到了观视空间。


      所谓观视空间。即以视点为原点。由视线方向、视角和远近平面,共同组成一个梯形体的三维空间,称之为视锥。如图所看到的。近平面,是梯形体较小的矩形面。作为投影平面,远平面是梯形体较大的矩形,在这个梯形体中的全部顶点数据是可见的,而超出这个梯形体之外的场景数据。会被视锥裁剪去掉。

    这里写图片描写叙述
    视锥

    观视空间到投影空间

      理论上讲视锥剔除应该在投影之前完毕。事实上这样也是能够的。可是有一个问题就是视锥是一个不规则的几何体。在当中完毕多边形剔除并非一件非常easy的事。所以眼下採用的方式是先投影,后剔除。


      可是这个投影并非简简单单投影到一个二维平面上。而是将观视空间中的场景投影到一个单位立方体中。俗称CCV(Canonical view volume)[5]。三维场景投影到三维空间。听起来或许非常诧异。事实上本质上还是投影到了二维平面上。由于CCV近平面的X、Y坐标与屏幕坐标相相应,Z坐标表示像素的深度值。我们经常使用的投影方式有两种:正投影和透视投影。

    从人眼观察世界的物理原理上来看,透视投影更加符合人类的视觉习惯。
    从数学上来讲,这个投影过程就是观视空间的顶点坐标乘以投影矩阵。顶点就变换到了投影空间CVV中。


      视锥剔除过程如今变得简单一些了。由于视体由视锥变成了CVV,位于CVV外面的图元全部被裁剔除。部分位于CVV之外的须要进行裁剪。这一过程在以下的图元装配时完毕。

    图元装配

      顶点流经过变换后,依照管线的顺序,下一个流程就是图元装配。所谓图元装配,就是依据之前的图元分类信息把顶点装配成图元。

    在这个过程中,将生成一些三角形、线段和点。之前是对顶点处理,如今就是对图元即可裁剪。对于超出屏幕之外的图元进行裁剪。对于游戏来讲,一般装配的图元都是三角形。假设三角形的一部分在屏幕外面。那么经过裁剪之后就变成了四边形,这个四边形又须要切割成两个小三角形。到如今这个阶段,就仅仅剩下主要的图元,不存在复杂的几何图形。
      到此为止。渲染管线的几何阶段就完毕了,几何阶段的工作比較简单明晰。就是顶点变换和光照。

    接下来就是非常重要的光栅阶段。

    2.4.2光栅阶段

    光栅化

      图元装配后生成的图元要显示在屏幕上必须经过光栅化。光栅化就是决定哪些像素被几何图元覆盖的过程。每种图元依据指定的规则分别被光栅化,涉及一些填充算法如扫描线多边形填充算法、边界填充算法等,这里不做讨论。

    光栅化的结果就是片段位置的集合。当光栅化之后。一个图元拥有的顶点数目和产生的片段数目之间没有不论什么关系。比方。一个由三个顶点组成的三角形,占领整个屏幕须要上百万的片段。
      这个有必要解释一下片段的概念。说到片段。不得不提到像素。

    像素是图像元素的简称。一个像素代表帧缓存中某个指定位置的信息,比方颜色、深度和其它与这个位置关联的值。而片段就是像素形成之前的一个状态,能够算作潜在的像素。在完毕最后的光栅操作。更新片段信息至帧缓存后,片段就成了名副事实上的像素。

    插值、贴图以及着色

      当图元被光栅化成一个或者多个片段后,就会依据须要对片段进行插值、执行一系列的贴图以及数学操作。然后为每一个片段确定终于颜色。除了确定终于的颜色意外。还须要确定终于的深度值,或者丢弃这个片段以避免更新帧缓存中相应像素。

    光栅操作

      光栅操作是在更新帧缓存之前,执行的最后的一系列片段操作。这些操作是Direct3D和OpenGL的一个标准组成部分。
    光栅操作会依据很多測试来检查每一个片段,这些測试包含裁剪測试、alpha測试、模板測试以及深度測试。假设当中一项測试不通过,片段就会被丢弃。假设全部測试都通过,执行完兴许操作后。就会更新帧缓存中的相应像素值。
    这里写图片描写叙述
    标准OpenGL和Direct3D的光栅操作流程

    2.5可编程渲染管线

      固定渲染管线看似非常完美,预制好的算法。操作简单,整个流程各环节分工明白,配合紧密。可是这样经典的模型相同存在着诸多短板,导致整个渲染的效率和质量非常难再大幅提升。以前的优势随着科技的进步反倒成了劣势,算法都固化在硬件内部。全部开发者仅仅能採用同一种固定的渲染方式,这样极大的束缚了开发者的常造型思维。固定渲染管线已经全然不能满足时代对于渲染的要求,所以一种新的渲染模型——可编程渲染管线诞生了。
    可编程渲染管线顾名思义,它的关键就在于GPU内部提供了可编程性。这样的可编程性的出现,对开发者来说是一种思想的解放。

    2.5.1可编程渲染管线VS固定渲染管线

      对照一下可编程渲染管线与固定渲染管线的流程图,能够非常明显的发现他们之间的共性和差异。
      关于共性,整个渲染流程大体上都是一致的。都是分为几何阶段和光栅阶段,当中流水线中顶点变换、图元装配、光栅化、插值、光栅操作等关键操作都是一致的。仅仅是在具体操作中採用的方式不同而已。
      重点就在于二者的差异。能够看到图中的可编程渲染管线多了两条分支——可编程顶点处理器和可编程片段处理器。在几何阶段没有了一系列坐标变换的过程,这缘于“T&L”硬件被移除了,取而代之的是可编程顶点处理器,顶点变换和光照计算都由它来完毕。在光栅阶段,颜色计算过程由可编程片段处理器代替了。
      接下来将要具体介绍可编程处理器。

    2.5.2可编程处理器

      可编程处理器是内嵌在GPU上的一种可编程单元,拥有非常强大的并行计算能力,并且擅长不高于4阶的矩阵运算。并且随着技术的发展。对浮点运算能力越来越强大。
      可编程处理器还有个别名——着色器,使用的比較广泛。所以上面的两种可编程处理器也叫做顶点着色器和片段着色器(或者像素着色器)。
      可编程处理器仅仅是一个单纯的硬件,还须要有执行在处理器上的程序来驱动,而这样的程序叫做着色器程序,也叫shader程序。程序和处理器之间有一一相应关系,顶点shader程序执行在顶点着色器上,片段shader程序执行片段着色器上。前面已经提到顶点着色器接管了“T&L”硬件的任务。片段着色器负责颜色计算。那么shader程序也有各自分工,顶点shader程序负责顶点变换和光照计算,片段shader程序负责颜色计算,并且前者的输出是后者的输入。
      由于每一代可编程处理器的架构有一定差异,没有一个绝对统一的标准。

    本文将以遵循Shader Model 2.0规范的可编程处理器为例来介绍。

    可编程顶点处理器

      在渲染3D场景的时候,顶点信息是通过Direct3D或者OpenGL这类3D渲染API传递给GPU。当GPU接收到顶点信息,它会为应用程序提交的每一个顶点调用一次顶点着色器程序。图2- 8就是可编程顶点处理器的架构图。
    这里写图片描写叙述
    可编程顶点处理器架构

      从图中我们能够看到顶点信息是以流的形式传递进来。这些信息包含顶点坐标、纹理坐标、颜色等等。

    信息传递完毕后,会被存放顶点数据寄存器(也叫输入寄存器)中。输入寄存器是一种仅仅读寄存器,从图中能够看到输入寄存器有16个,v0到v15,说明最多能够存储16个顶点属性。

    然后,顶点处理器会通过訪问其它的一些寄存器来完毕几何阶段的任务。
      常量寄存器也是一种仅仅读寄存器。存储一些预先设定的静态參数。
      暂时寄存器能够进行读写操作,存放计算的中间结果。注意当中的a0和aL寄存器,他们主要用于循环计数和按索引寻址。
      由于顶点处理器能够任意訪问以上三种寄存器。所以编程人员能够依照自己的方式处理操作和处理寄存器中的数据。这在固定渲染管线时代是不可想象的事情。计算完毕,定点处理器要把计算结果存入输出寄存器。这里必须把屏幕空间的顶点坐标放入oPos寄存器中,当然还能够传递其它的信息比方颜色、纹理坐标等等到其它寄存器中。结果存放完毕后,接下来就进入了图元装配阶段和光栅化阶段,这个与固定渲染管线一致。不具备可编程性。

    可编程片段处理器

      光栅化操作完后,生成了一系列片段,这时候片段处理器会为每一个片段调用片段着色程序。
    这里写图片描写叙述
    可编程片段着色器架构图

      片段处理器内部架构和顶点处理器基本框架是几乎相同的,仅仅是有些细节上的差异。

    这里是输入寄存器变成了颜色寄存器和纹理寄存器,由于如今操作的对象是片段。寄存器v0和v1分别表示插值过以后的漫反射和镜面反射分量。t0到tN这一系列寄存是用于存储纹理查找坐标。在片段处理阶段,採样寄存器指向须要使用的纹理。常量寄存器和暂时寄存器基本一致。
      计算完毕后。输出寄存器要把计算出的终于颜色存入寄存器。这里的寄存器除了oC0以外,还有oDepth,它里面的深度值是在光栅操作中做深度測试用的。


      两种可编程处理器介绍完了,在这里有两点须要说明一下。第一点就是在本章最開始提到的统一渲染架构,已经取消了专门的可编程处理器。shader程序与处理器之间没有相应关系。取而代之的是统一的流处理器,能执行全部类型的shader程序,这样的优点是在各类场景渲染时能保持负载均衡。第二点是逻辑上的可编程处理器另一类可编程几何处理器。眼下仅仅有较新的硬件支持,应用不广泛,本文不做介绍。

    2.6本章小结

      本章介绍了GPU 图形渲染管线。并对相关的图形硬件进行了阐述。图形渲染管线是GPU 编程的基础,事实上顶点着色程序和片段着色程序正是依照图渲染制管线而划分的。

  • 相关阅读:
    Django学习日记04_模板_overview
    Python并发实践_01_线程与进程初探
    web自动化测试笔记(二)
    web自动化测试笔记(一)
    app版本升级的测试点
    移动测(APP)试与web端测试的区别
    Dubbo服务器与普通服务器的区别
    java的错误分类
    安卓手机与iOS手机的区别
    在webstorm里使用git
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7346610.html
Copyright © 2011-2022 走看看