Unity3D - Shader - 渲染过程

渲染过程

渲染过程 - 通常从是三维场景出发、生成一张二维图像,由CPU和GPU共同合作完成。且通常分为以下几个概念阶段:

Unity3D - Shader - 渲染过程_第1张图片

应用阶段

应用阶段通常有开发者主导,由CPU实现,并且输出渲染所需的几何信息 - 渲染图元(Renderding primitives),其主要有3个任务:

  1. 需要准备好场景数据(摄像机、视锥体、模型、光源)
  2. 做剔除(culling)操作
  3. 设置模型的渲染状态(漫反射颜色、高光反射颜色等等)

几何阶段

用于决定绘制的图元是什么、在哪里绘制、如何绘制等。

光栅化阶段

主要任务是决定每个渲染图元中那些像素应该被绘制在屏幕上。

如何开始渲染流程

渲染流程的起点是应用阶段,应用阶段大致分为三步:

  1. 加载数据到显存
  2. 设置渲染状态:状态就是网格如何被渲染,使用的何种着色器、光源、材质等
  3. 调用Draw Call:仅是一个命令,发起方是CPU接收方是GPU,其会指向一个需要被渲染的图元(primitives)列表。

经历过Draw Call后,GPU会根据渲染状态(材质、纹理、着色器等)和所有的图元(输入的顶点数据)来进行计算,最终输出成屏幕上的像素。

GPU流水

当GPU从CPU哪里得到Draw Call(渲染命令)后,就会进行一系列的操作,最终把图元渲染到屏幕上。

几何阶段和光栅化阶段的实现载体是GPU,其中又可以分为若干小的阶段,由GPU实现,每个阶段提供了可编程或可配置性。

Unity3D - Shader - 渲染过程_第2张图片

顶点着色器(Vertex Shader)

顶点着色器(Vertex Shader)是流水线的第一个阶段,输入来自CPU。顶点着色器的处理单元是顶点,每个顶点都会调用一次顶点着色器。

其主要工作有:坐标变换和逐顶点光照,以及输出后续阶段所需的数据。

坐标变换就是对顶点的坐标进行某种变换(矩阵),也可以在这一步改变顶点的位置。其中最基本也是必须完成的一个工作是,把顶点坐标从模型空间转换到齐次裁剪坐标空间。

// 将顶点坐标转换到齐次裁剪坐标系下,再通过透视法
// 得到归一化的设备坐标(NDC normalized device coordinate)
o.pos = mul(UNITY_MATRIX_MVP, v.position);

Unity3D - Shader - 渲染过程_第3张图片

裁剪(Clipping)

一个图元与摄像机视野的关系有:

  1. 完全在视野内
  2. 部分在视野内
  3. 完全在视野外

完全在视野内的图元会继续传递给下一个阶段,完全不在视野内的就不会被继续传递,而部分在视野内的图元则需要进行裁剪处理。裁剪过程会使用一些新顶点代替旧顶点。

Unity3D - Shader - 渲染过程_第4张图片

屏幕映射

屏幕映射(Screen Mapping)的任务是把三维坐标系下的坐标,转换到屏幕坐标系(Screen Coordinates)下。

此外,屏幕坐标系和z坐标一起构成了窗口坐标系(Windows Coordinate)。

Unity3D - Shader - 渲染过程_第5张图片

几何阶段结束

几何阶段结束所输出的信息是屏幕坐标系下的顶点位置以及和他们相关的额外信息,如:深度值(z坐标)、法线方向、视角方向。

三角形遍历

三角形遍历(Triangle Traversal)阶段将检查每个像素是否被一个三角网格所覆盖,如果覆盖就会生成一个片元(fragment),这样一个过程就是三角形遍历。

遍历后还会对覆盖区域的像素进行插值。输出结果是一个片元序列,其是包含了很多状态的集合,用于计算最终颜色(屏幕坐标、深度信息、顶点信息、法线、纹理等)。

Unity3D - Shader - 渲染过程_第6张图片

片元着色器(Fragment Shader)

片元着色器是重要的可编程阶段。前面阶段产出的片元用于存储一系列的信息。真正对像素产生影响的是下一个阶段 - 逐片元操作。

片元着色器的输入是插值后得到的,而输出是一个或多个颜色。

Unity3D - Shader - 渲染过程_第7张图片

逐片元操作

逐片元操作(Per-Fragment Operations)步骤的主要目的是合并,其用于:

  1. 决定每个片元的可见性。(深度测试、模板测试)
  2. 与颜色缓冲区中的颜色进行混合。

模型图元经过各种计算和测试后,就会显示在屏幕上。为了避免看到正在光栅化的图元,GPU会使用双重缓冲(Double Buffering)策略。对场景的渲染时在幕后发生的,在后置缓冲(Back Buffer)中。一旦被渲染到后置缓冲中,GPU就会交换后置缓冲区与前置缓冲区(Front Buffer),而前置缓冲区是之前显示在屏幕上的图像。

你可能感兴趣的:(Unity3D,Unity3D教程学习)