美文网首页
渲染流水线

渲染流水线

作者: NightChord | 来源:发表于2019-08-12 00:21 被阅读0次

    1 渲染流水线

    1.1 综述

    《Render-TimeRendering, Third Edition》一书中将一个渲染流程分成3个阶段:应用阶段 (Application Stage)、几何阶段(Geometry Stage)、光栅化阶段(RasterizerStage)。

    1.1.1 应用阶段

    在这一阶段中, 通过CPU负责实现,开发者有3个主要任务:

    l 我们需要准备好场景数据, 例如摄像机的位置、 视锥体、 场景中包含了哪些模型、 使用了哪些光源等等;

    l 为了提高渲染性能, 我们往往需要做一个粗粒度剔除(culling)工作, 以把那些不可见的物体·剔除出去, 这样就不需要再移交给几何阶段进行处理;

    l 我们需要设置好每个模型的渲染状态。 这些渲染状态包括但不限于它使用的材质(漫反射颜色、 高光反射颜色)、 使用的纹理、 使用的Shader等。

    这一阶段最重要的输出是渲染所需的几何信息, 即渲染图元(rendering primitives)。 通俗来讲, 渲染图元可以是点、 线、 三角面等。 这些渲染图元将会被传递给下一个阶段一几何阶段。

    1.1.2 几何阶段

    几何阶段负责和每个谊染图元打交道,进行逐顶点、逐多边形的操作。在GPU上进行。

    l 重要任务就是把顶点坐标变换到屏幕空间中,再交给光栅器进行处理

    输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等相关信息,并传递给下一阶段

    1.1.3 光栅化阶段

    使用几何阶段传递的数据来产生屏幕上的像素,井渲染出最终的图像。也是在 GPU 上运行。

    l 决定每个渲染图元中的哪些像素应该被绘制在屏幕上。

    对应几何阶段得到的逐顶点数据(例如纹理坐标、顶点颜色等)进行插值, 然后再进行逐像素处理。

    1.2 CPU和GPU之间的通信

    渲染流水线的起点是 CPU,即应用阶段,又可大致分为3阶段:

    1. 把数据加载到显存中;

    2. 设置渲染状态;

    3. 调用 Draw Call。

    1.2.1 把数据加载到显存中

    所有渲染所需的数据都需要从硬盘(Hard Disk Drive, I-IDD ) 中加载到系统内存 (Random Access Memory, RAM )中。然后,网格和纹理等数据又被 加载到显卡上的存储空间一一显存(Video Random Access Memory, VRAM)中。显卡对于显存的访问速度更快。

    l 渲染所需数据还包括:顶点的位置信息、 法线方向、 顶点颜色、 纹理坐标等。

    数据加载到显存后,RAM 中的数据部分数据CPU 仍然需要访问它们(例如, 我们希望 CPU 可以访问网格数据来进行碰撞检测)。

    1.2.2 设置渲染状态

    渲染状态:这些状态定义了场景中的网格是怎样被渲染的。例如使用哪个顶点着色器(Vertex Shader) I片元着色器(Fragment Shader)、 光源属性、 材质等。

    开发者需通过 CPU 来设置渲染状态, 从而 “指导 ” GPU 如何进行渲染工作。如

    在同一状态下渲染3个网格。由于没有更改渲染状态, 因此3个网格的外观看起来像是同一种材质的物体

    设置好渲染状态后,CPU就会调用一个渲染命令来告诉GPU按照设置状态开始渲染。而这个渲染命令就是 Draw Call。

    1.2.3 调用Draw Call

    l Draw Call 就是一个命令, 它的发起方是 CPU,接收方是 GPU 。

    CPU通过调用Draw Call来告诉GPU开始进行一个渲染过程。 一个Draw Call会指向本次调用需要渲染的图元列表,而不会再包含任何材质信息。

    当给定了一个 Draw Call 时, GPU 就会根据渲染状态(例如材质、 纹理、 着色器等)和所有 输入的顶点数据来进行计算, 最终输出成屏幕上显示的那些漂亮的像索。而这个计算过程, 就是 GPU 流水线。

    1.3 GPU 流水线

    当GPU从CPU那里得到渲染命令后,就会进行一系列流水线操作,最终把图元渲染到屏幕上。

    1.3.1 概述

    对于几何阶段和光栅化阶段,开发者无法拥有绝对的控制权,其实现的载体是GPU。GPU通过实现流水线化,大大加快了渲染速度。

    几何阶段和光栅化阶段可以分成若干更小的流水线阶段,这些流水线阶段由GPU实现,每个阶段GPU提供了不同的可配置性或可编程性。

    GPU的渲染流水线实现。颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实线表示该Shader必须由开发者编程实现, 虚线表示该Shader是可选的

    l 顶点着色器 Vertex Shader

    顶点着色器是完全可编程的,通常用于实现顶点的空间变换、顶点着色等功能。

    l 曲面细分着色器 Tessellation Shader

    曲面细分着色器是一个可选的着色器,用于细分图元。

    l 几何着色器 Geometry Shader

    几何着色器是一个可选的着色器,用于执行逐图元着色操作,或产生更多图元。

    l 裁剪 Clipping

    是将那些不在摄像机视野内的顶点剪裁掉,并剔除某些三角图元的面片。

    这个阶段可以配置,我们可以使用自定义的裁剪平面来配置裁剪区域,也可通过指令控制裁剪三角图元的正面或背面。

    l 屏幕映射 Screen Mapping

    屏幕映射是不可配置和编程的,负责把每个图元的坐标转换到屏幕坐标系。

    1.3.2 顶点着色器(Vertex Shader):完全可编程

    通常用于实现顶点的空间变换、顶点着色等功能。

    顶点着色器是流水线的第一个阶段,它的输入来自于CPU。顶点着色器的处理单位是顶点,输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身并不会创建或者销毁顶点,而且无法得到顶点与顶点之间的关系。

    例如:我们无法得知两个顶点是否属于一个三角网格。正因为这样的相互独立性,GPU可以利用本身的特性并行化处理每一个顶点。

    顶点着色器需要完成的工作主要有:坐标变换和顶点光照。当然还可以输出后续阶段所需的数据。

    1.3.3 裁剪(Clipping):可配置

    这一阶段的目的是将那些不再摄像机视野内的顶点裁减掉,并剔除某些三角图元的面片。

    目的:处理不在摄像机视野范围内的物体。

    一个图元和摄像机视野有三种关系:完全在视野内、部分在视野内、完全在视野外。完全在视野内的图元即系传递给下一个流水线阶段,完全在视野外的图元就不会向下传递,因为不需要被渲染。而那些部分在视野内的图元就需要进行一个处理,那就是裁剪。

    和顶点着色器不同,这一步是不可编程的。无法通过编程来控制裁剪的过程,是硬件上的固定操作

    但是可以自定义一个剪裁操作来对这一步进行配置

    1.3.4 屏幕映射(Screen Mapping):不可配置和编程的

    这一步输入的坐标仍然是三维坐标系下的坐标。

    负责把每个图元的坐标转换到屏幕坐标系中。

    1.3.5 三角形设置(Triangle Setup)和三角形变量(Triangle Traversal)阶段都是固定函数(Fixed-Function)的阶段

    这一阶段开始进入光栅化阶段。从上一个阶段输出的信息是屏幕坐标系下的顶点位置以及和它们相关的额外信息,如:深度值(Z)、法线方向、视角方向等。

    光栅化阶段有两个重要的目标:计算每个图元的覆盖了哪些像素,以及为这些像素计算颜色。

    三角形设置:计算光栅化一个三角网格所需的信息。具体来讲,上一个阶段输出的都是三角网格的顶点,即我们得到的是三角网格每条边的两个顶点。但是如果要得到整个三角形网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式。这样一个计算三角形网格表示数据的过程叫做三角形设置。

    三角形遍历:检查每个像素是否被一个三角网格所覆盖。如果覆盖的话,就会生成一个片段(fragment)。这样一个找到哪些像素被三角网格覆盖的过程就是三角形遍历,这个阶段也被称为扫描变换(Scan Conversion)。

    片段并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。

    1.3.6 片段着色器(Fragment Shader):完全可编程

    用于实现逐片元(Per-Fragment)的着色操作。

    片段着色器的输入是上一个阶段对顶点信息插值得到的结果,更具体来说,是根据那些从顶点着色器中输出的数据插值得到的。输出的是一个或者多个颜色值。

    这一个阶段可以完成很多重要的渲染技术,其中最重要的技术之一就是纹理采样。为了在片段着色器中进行纹理采样,通常会在顶点着色器阶段输出每个顶点对应的纹理坐标,然后经过光栅化阶段对三角网格的3个顶点对应的纹理进行插值后,就可以得到其覆盖的片段的纹理坐标了。

    1.3.7 逐片元操作(Per-Fragment Operations):不可编程,但具有很高的可配置性

    负责执行很多重要的操作,例如:修改颜色、深度缓冲、进行混合等。

    这一阶段OpenGL-逐片元操作 DirectX-输出合并阶段

    这一阶段有几个重要的任务:

    (1) 决定每个片元的可见性:这涉及了很多测试工作,例如:深度测试、模板测试

    (2) 如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经储存在颜色缓冲区中的颜色进行合并

    Unity

    Unity Render Pipeline 渲染管线(漫画)

    https://blog.csdn.net/baidu_16312167/article/details/75270896

    相关文章

      网友评论

          本文标题:渲染流水线

          本文链接:https://www.haomeiwen.com/subject/bniejctx.html