zoukankan      html  css  js  c++  java
  • 图形渲染管线——实时渲染4第二章

    1. 机制:

    流水线很常见,比如工厂中的生产流水线。为什么引入流水线?不引入的话,一个面包需要20分钟完成才能做下一个面包,引入流水线后,流水线的各个阶段能够并行执行,每个子阶段需要5分钟,每5分钟后就能做一个蛋糕的子阶段,各个子阶段并行执行则时间消耗为原来的时间消耗除以子阶段数。所以,流水线的主要特征是并行性,引入流水线的目的是提高效率。最慢的子阶段是这个流水线的瓶颈。

    图形渲染管线大致分为4个子阶段:应用阶段、几何阶段、光栅化阶段和像素处理阶段。这几个阶段自身又可能包含几个子阶段。

    渲染速度可以用fps、毫秒、hz表示。fps通常表示一秒钟渲染的帧数,一般用来表示某个特定帧花费的时间或者一段时间的平均帧率。毫米表示渲染一帧花费的时间,跟每帧需要的渲染的图片的复杂度有关。Hz一般跟硬件有关,比如显示器,一般是固定值。

    应用阶段一般在cpu上执行,cpu一般有多核心,所以能用多线程并行的方式执行。应用阶段上的任务一般有碰撞检测、接收输入信息并反应、全局加速算法、动画、物理模拟等,应用程序不同任务也不同。应用阶段也提供后面阶段需要的数据,比如图元位置、摄像机位置、灯光信息、图源着色信息、投影矩阵等。

    几何阶段处理转换、投影等操作,主要用来决定画什么,怎么画、在哪里画的问题。在gpu上执行,gpu上包含许多可编程核心和固定函数硬件。

    光栅化阶段一般输入3个顶点,组成一个三角形,并将所有在这个三角形中的像素输出到下个阶段。

    像素处理执行一个像素shader,得到像素颜色,也会进行深度测试,还可能做模板测试、颜色混合。

    光栅化阶段和像素处理阶段也完全在gpu上执行。

     2. 应用程序阶段:

    由于这个阶段一般是在cpu上执行的,所以开发者能完全控制。也有可能有些应用阶段的任务要在gpu上完成,比如一些计算可以用compute shader执行。这时,gpu不是传统意义的渲染功能,而是被当成高并行通用处理器。应用阶段的操作会影响后面管线的性能。

    应用阶段最后会将几何阶段需要的数据输出给后面阶段,比如图元信息,这是这个阶段的主要职责。

    应用阶段一般包含碰撞检测、动画、接收输入、加速算法、剔除算法等。

    3. 几何处理阶段:

    gpu上的几何处理阶段一般负责逐像素和逐顶点的操作,一般可包含顶点shader、投影、剔除、屏幕映射这几个子阶段。

    3.1 顶点shader

    计算坐标和着色需要的信息。模型坐标转换到世界坐标,世界坐标转换到相机坐标,相机坐标转换到投影坐标。投影又分正交投影和透视投影,正交投影是平行投影的一种。这两种投影都能用一个4*4的矩阵表示。投影变换后,顶点就位于裁剪坐标系中,也就是除以w之前,是齐次坐标系。为了下个阶段:裁剪阶段的正常工作,这个阶段必须输出裁剪坐标系的坐标。尽管这些矩阵将顶点从一个体积中变换到另一个体积中,为啥叫这个为投影呢?因为显示后,z存储到z-buffer中,不再存储在贴图中了。

    3.2 可选顶点处理阶段

    这些阶段不太常用,也是在gpu上执行,是否应用依赖于硬件和开发者意愿。这几个阶段是互相独立的。

    细分shader:当一个球面数很低的时候,离近看,效果不好;但如果这个球面数很高,离远了,性能会比较费。所以这时候就需要有细分阶段。经过细分,一个曲面能生成合适数目的三角形。顶点可以用来表示一个曲面,一个曲面由多个片构成,片由顶点集合构成。场景摄像机决定生成顶点的数目,片离得越近,生成的三角形越多;片离得越远,生成的三角形越少。

    几何shader:出现的比细分shader早,所以用的也更普遍。比细分shader简单,因为在规模和输出图元类型上有一些限制。几何shader一个普遍的应用是粒子生成,比如烟花,由一个顶点生成一个面对摄像机的四边形。

    Steam Output阶段:这个阶段让我们能把gpu当作几何引擎来用。每个顶点不是必须要映射到屏幕进行渲染,可以输出为数组,用来进一步处理,可以给cpu用,也可以给gpu自身用。这个阶段一般可以用来做粒子模拟。

    这3个阶段的执行顺序是:细分、几何和流输出,每个阶段都是可选的。如果我们继续往下,会有一些在裁剪坐标系中的顶点,用来判断是否对相机是可见的。

    3.3 裁剪

    完全在视锥体内的图元,会传输到下个阶段,完全不在视锥体内的图元,不会被传输到下个阶段。要进行裁剪的,是那些跟视锥体相交的图元。比如一个线段,一半在视锥体内,一半在视锥体外,那么,在相交的地方会生成一个新的顶点,代替原来的图元。投影矩阵的使用意味着图元要基于单位体积进行裁剪。进行投影变换也是为了裁剪操作能够统一。

    用户也能用额外的裁剪平面对物体进行裁剪。

    裁剪阶段用齐次裁剪坐标进行裁剪。插值不是在三角形中进行线性插值的,w值也会被考虑,这样用透视投影的时候,插值会更正确。

    最后,会应用透视除法,将坐标转换到ndc坐标系下。

    3.4 屏幕映射

    进入这个阶段时,坐标仍然是3维的,xy就会转换到屏幕坐标空间。屏幕坐标和z坐标一起成为窗口坐标。z坐标也被映射到一个范围,openGL(-1,1),DirectX(0,1).这个窗口坐标和重新映射后的z值被传输到光栅化阶段。

    对于OpenGL来说,左下角坐标为(0,0);对于DirectX来说,左上角为(0,0).

    4 光栅化阶段

    查找在一个图元中的所有像素。分为两个子阶段:三角形建立(图元组装)和三角形遍历。因为图元类型可能是线段等,但是三角形比较普遍,所以这两个阶段名称里都带着“三角形”。光栅化阶段也叫扫描转换阶段。将屏幕空间的二维坐标的顶点转化为屏幕上的像素。

    一个像素是否被认为和一个三角形重叠,取决于你怎么设置管线。最简单的方法,在一个像素的中心用点的采样,如果中心点在三角形中,那么说这个像素在三角形中。也可以用超级采样或者多采样抗锯齿技术,一个像素上进行1次以上的采样。也可以用保守的方法,只要像素的一部分在三角形中,就认为这个像素在三角形中。

    4.1 三角形建立阶段

    三角形的特征,边缘公式会被计算,用于三角形遍历阶段。三角形上顶点处理阶段输出的的着色数据也会被插值。这个任务用固定函数硬件实现。

    4.2 三角形遍历阶段

    这个阶段检测像素是否被三角形覆盖,会为被三角形覆盖的像素生成一个片元。查找哪些像素或者采样在三角形中的过程被称为遍历。每个片元的属性用三角形顶点的属性进行插值得到,这些属性包括深度和着色属性。插值过程中,透视正确被考虑到。图元中的所有采样和像素都会被送到像素处理阶段。

    5. 像素处理阶段

    分为像素着色和merge阶段。

    5.1 像素着色

    像素着色阶段会输出一个或者多个颜色。逐像素着色计算都在这个阶段进行,用插值的着色数据作为输入。纹理采样是这个阶段用的最多的技术。

    5.2 merge

    像素的颜色存储在colorbuffer中,merge阶段的目标是将像素输出的片元颜色与color buffer中的颜色进行混合。这个阶段不是完全可编程的,但是是可配置的。这个阶段会判断这个片元是否可见,通过z-buffer,z-buffer的复杂度为O(n),如果当前z比zbuffer的值小,则更新color buffer和zbuffer的值。zbuffer允许图元以任意顺序渲染,这是它流行的一个原因。但zbuffer的一个缺陷在于,它只能存一个值,他不能用于半透明物体。所以,半透明物体要以从后向前的顺序进行渲染或者用一种分开的,基于顺序的方式进行渲染。

    stencil buffer一般用来标识图元位置,用来实现一些效果,控制color buffer和zbuffer的渲染。一般stencil buffer有8位。

    管线最后的这些功能都被叫做光栅操作或者混合操作。将color buffer中的颜色和像素处理生成的颜色进行混合。一般是用api配置的,不是完全可编程的。

    经过光栅化,被摄像机看到的像素会输出到屏幕上。为了避免用户看到光栅化的过程,用双缓存机制。一定时间,交换buffer。

    6 总结

    这不是唯一一种管线方式,还有其他类型的管线比如光线追踪等。

  • 相关阅读:
    windows下读取utf-8文件
    mongodb c api编译
    JS学习笔记
    【已解决】关于SQL2008 “不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的标进行了更改或者启用了‘阻止保存要求重新创建表的更改’” 解决方案
    C#字符串截取
    C#通过WatiN操作页面中内嵌的Iframe
    C#查找以某个字母开头另一字母结尾的字符串
    HTML5+CSS3学习小记
    C#求任意范围内的质数
    C#中的委托
  • 原文地址:https://www.cnblogs.com/Shaojunping/p/11485638.html
Copyright © 2011-2022 走看看