关于《Thinking in Unity3D》


笔者在研究和使用Unity3D的过程中,获得了一些Unity3D方面的信息,同时也感叹Unity3D设计之精妙。不得不说,笔者最近几年的引擎研发工作中,早已习惯性的从Unity3D中寻找解决方案。

Unity3D虽比不上UE那么老练沉稳,气势磅礴。也比不上CE那样炫丽多姿,盛气凌人。但它的发展势如破竹,早已遍地生花!故而在此记录一些自己的心得体会,供大家参详交流。若有欠妥之处,还望各位及时指正。
 
Thinking in Unity3D由一系列文章组成,文章列表地址:http://www.cnblogs.com/geniusalex/p/5321545.html
 

HI,你好


Unity3D发展至今,已经是5.x版本了。对于一个引擎迭代来说,特性、效果、效率的提升,无不波及到渲染管线的改动。而与渲染管线最为紧密挂钩的就是材质系统和渲染流程,但由于材质系统和渲染流程涉及的范围和内容更广。我们将用单独的篇幅来描述。本文主要目标是渲染管线中的Rendering Path。
由于历史发展,以及各种平台、机型、版本兼容的原因。Unity3D中,目前保存了4种Rending Path.
1、Deferred Shading Rendering Path(延迟渲染)
2、Forward Rendering Path(前向渲染)
3、Lagacy Deferred Lighting Rendering Path(延迟光照)
4、Vertex Lit Rendering Path(顶点光照)
 

Forward Rendering Path(前向渲染)


传统的前向着色渲染方式是一种简单粗暴的方式。就是一次性将一个物体绘制完再绘制下一个。光照计算也是如此。前向着色最主要的问题就是光照问题。当光源过多的时候,就需要进行处理。 而Unity3D在光源处理方面,也结合了像素光照(per-pixel lighting) ,顶点光照(per-vertex lighting),球谐光照(Spherical Harmonics lighting)等多种方案,其复杂程度可见一斑。
 
Unity3D中前向渲染的光源策略
前向着色渲染由于效率和寄存器限制等原因。不可能老老实实地去处理所有的光源。因此,需要根据光源的远近,范围,重要程度等因子决定计算方式。
1、如果一个光源的RenderMode没有设置为重要(Important),那么它将永远是逐顶点或者球谐光照计算方式。
2、最亮的(Brightest)方向光源会做为逐像素光照计算。
3、如果一个光源的RenderMode设置为重要(Important),那么它将会采用逐像素光照计算方式
4、如果上面的结果中的用于逐像素计算的光源数目小于了Project Settings->Quality面板中的Pixel Light Count值。 为了减少亮度误差,有一些光源会被当作像素光源计算(PS:非像素光源无法完全计算阴影关系。会导致场景偏亮)。
5、Unity3D对顶点光照,像素光照做了最大限制。 分别为4个。而场景中不可能只有这么多光源。因此,使用了一个优先级判定。
左:光源位置图 右:光源分配图
 
从图中我们可以看到。 D参与了像素和顶点光照。 G参与了顶点光照和球谐光照。 这样的处理应该是为了做一个光照信息的平滑衔接,不至于变得很突兀。
 
 
Unity3D中前向渲染的光照的计算过程
前向渲染中,光照计算被分成了多个PASS。通常它们由1*FarwardBase Pass + N*FarwardAdd Pass组成。可以看出,光源的数目在前向渲染管线中是一个致命的效率杀手。
1、Base Pass 提交一个逐像素方向光和所有的逐顶点光照和球谐光照。
2、Additional Pass 提交一个逐像素的光照计算。 如果一个物体受更多的光源影响。那么就会有许多PASS需要进行绘制。
:在Shader中。可以指定FarwardBase来关掉Additional 功能。
:在前向渲染中,只能有一个方向光实时阴影。
 
Unity3D中的球谐光照
球谐光照是一个CPU光照算法。它可以处理大规模的光源信息,非常适合一些很小的动态点光源。但是它存在以下几个问题。
1、球谐光照是基于物体顶点的算法,并非像素级。这就意味着它不能使用一些像素级的效果增强手段。比如法线贴图。
2、基于效率的考虑,球谐光照的更新频率非常低。如果光源移动过快,就会穿邦。
3、球谐光照是基于全局空间的计算,当一个面离点光源或者聚光灯很近时,效果是错的。
 

Deferred Shading Rendering Path(延迟渲染)


 
延迟渲染技术简介
延迟渲染技术已经是一个成熟且稳定的技术。已经广泛用于各种商业引擎中。它主要解决的是当光源数目过多时带来的复杂光照计算的开销。 在传统前向渲染中,假设一个场景中有M个物体,N个光源。 那么理论上进行的光照计算次数为 M*N。 而DS管线可以使其变为M+N。
但是DS管线并非万能的。有以下情况需要注意
 
延迟渲染技术缺陷
1、DS需要多渲染目标(MRT)的支持、深度纹理、双面模板缓存。
     这个特性,需要显卡支持SM3.0的API。2006年以后的PC显卡应该不成问题。比如GeForce 8xxxx,AMD Radeon X2400,Intel G45以后的显卡。
2、DS管线会消耗更多的显存,用于缓存G-Buffer。同时,会要求显卡拥有更大的位宽(bit counts)。
     在手机上目前(2016年)还不实现。
3、DS管线无法处理半透明物体。
     半透明物体需要退回到传统前向渲染中进行
4、硬件抗锯齿(MSAA)无法使用。
     只能使用一些后期算法,如FXAA等。
5、这句话中的内容目前未测试,故无法准确体会其中的意思:There is also no support for the Mesh Renderer’s Receive Shadows flag and culling masks are only supported in a limited way. You can only use up to four culling masks. That is, your culling layer mask must at least contain all layers minus four arbitrary layers, so 28 of the 32 layers must be set. Otherwise you will get graphical artefacts.
 
延迟渲染技术在Unity3D中的实现方案
Unity3D中,延迟渲染管线为分两个阶段进行。G-Buffer阶段和光照计算(Lighting)阶段。
 
G-Buffer阶段
Unity3D渲染所有的非透明对象到各个RT中,RT的内容分布见 G-Buffer内容。Unity3D将各个RT做成了全局变量,方面Shader中进行操作。像这样:CameraGBufferTexture0 .. CameraGBufferTexture3
 
光照计算阶段
这个阶段的主要目的就是根据G-Buffer的内容进行光照计算。由于是屏幕空间的计算,显然要比之前的前向渲染来得容易得多。
 
:实时阴影的计算是在光照计算之前的。 DS管线并不能减少实时阴影的开销。应该怎么整还得怎么整。最后,每个物体受到的实时阴影的影响会叠加到RT3中。一些特殊的爆光效果,Lightmap光影贴图效果等都会进入RT3。 参见G-Buffer内容
 
 
G-Buffer内容
RT0, ARGB32 format: Diffuse color (RGB), occlusion (A).
RT1, ARGB32 format: Specular color (RGB), roughness (A).
RT2, ARGB2101010 format: World space normal (RGB), unused (A).
RT3, ARGB2101010 (non-HDR) or ARGBHalf (HDR) format: Emission + lighting + lightmaps + reflection probes buffer.
Depth+Stencil buffer.
 
:为了减少显存和渲染开销。当前场景的摄像机开启了HDR模式时,RT3将不会被创建。而是直接使用摄像机的HDR RT。
 
自定义DS管线
Unity3D中,标准的DS管线是Standard系列。如果你想修改某一个部分。你可以新建一个自己的Shader。然后替换掉默认的即可。
替换的位置在Edit->Project Settings->Graphics面板中。把Deferred属性下拉框变成Custom,就可以进行替换操作了。
 
内置Shader设置

Lagacy Deferred Lighting Rendering Path(延迟光照)


:从5.0开始,DL渲染已经不被Unity3D推荐,Unity3D更推荐大家新项目使用DS管线方式。因为DL方式不好实现基于PBR着色的Standard材质,以及场景反射。
:如果摄像机设置为了正交投影。会强制退回前向渲染
:DL也不会降低实时阴影的开销
 
和DS渲染管线一样,DL的出现同样是为了解决光照计算的复杂度问题。然后不同的是,DL仅仅把光照计算拿出去了。简单说来,DL管线工作流程如下。
步骤一、渲染场景中的对象,输出光照计算需要的RT(深度、法线、高光信息)
步骤二、使用上面的RT进行光照计算
步骤三、再次渲染场景中的对象,并与计算机来的光照信息结合。
 
不难看出,DL相比DS而言,不需要大量的G-Buffer支持。甚至不需要MRT的支持。但是对深度图的要求是必须的。如果遇上无法访问深度BUFFER的情况。那就需要做一次Pre-Depth Pass渲染。
 
比起DS而言,DL由于不需要MRT的支持。在硬件特性需求和位宽上,少了许多开销。
1、SM3.0
2、PC:GeForce FX、Radeon X1300、Intel 965 / GMA X3100
3、Mobile:所有支持OpenGL ES 3.0的设备,部分支持OpenGL ES 2.0的设备。
 

Vertex Lit Rendering Path(顶点光照)


注:这不是一个通用的技术名词,只有Unity3D中有。
注:主机平台这个不顶用。
注:不支持实时阴影和高精度高光计算。
 
Vertex Lit Rendering就是指,所有的光照计算都通过顶点进行。而在Unity3D中,它的主要目的是为了支持那些没有可编程管线的设备。VL也提供了几种方法,用于支持不同的材质类型。
1、Vertex 使用Blinn-Phong进行光照处理,针对没有lightmap的对象使用。
2、VertexLMRGBM 针对lightmap贴图使用RGBM加密(PC和主机平台)的对象, 没有额外的光照计算。
3、VertexLMM 针对lightmap贴图使用double-LDR加密(移动平台)的对象,没有额外的光照计算。
 

Unity3D对几种渲染管线的统一处理


在上面我描述中,我们发现,不管哪一种管线。都会涉及到几个部分。 1、光照计算 2、透明渲染 3、阴影计算 4、图像输出。 那Unity3D又是如何对这些进行统一流程控制的呢。我们看下面的图就明白了。
 Unity3D渲染管线图
 
从图中我们可以看到。Unity3D的传统渲染管线和延迟渲染管线,在非透明物体渲染和光照阶段是分离的。当处理完以后,紧接着处理非透明图像效果->天空盒->透明物体渲染->后期效果。
 
结束语

总的来说,Unity3D的渲染管线还算稳定和易用,其的渲染管线包含了常见的三种方案。最主要目的还是在想着光照计算和效果显示的处理。同时保持对上层透明。其Graphics Commander Buffer提供了扩展管线的能力。而Graphics设置面板里,也提供了自定义延迟管线Shader的功能。然而也有诸多的美中不足,比如,正交摄像机模式下,不能使用延迟渲染技术。 延迟光照下无法实现PBR和实时环境反射抽取等等。
 
参考文献

Thinking in Unity3D:渲染管线中的Rendering Path的更多相关文章

  1. 【原】实时渲染中常用的几种Rendering Path

    [原]实时渲染中常用的几种Rendering Path 本文转载请注明出处 —— polobymulberry-博客园 本文为我的图形学大作业的论文部分,介绍了一些Rendering Path,比较简 ...

  2. 渲染路径-实时渲染中常用的几种Rendering Path

    http://www.cnblogs.com/polobymulberry/p/5126892.html?utm_source=tuicool&utm_medium=referral 回到顶部 ...

  3. Unity 的“Vertex Lit Rendering path“中 shader Pass 的注意事项

    "MADFINGER/Environment/Unlit (Supports Lightmap)"是 ShadowGun 示例中最简单的 shader 了,如下: // Unlit ...

  4. Rendering Path

    Rendering Path:渲染路径 设置:1.Player Setting,2.Camera(会覆盖PlayerSetting中的设置) 选择:根据渲染内容和目标平台来选择合适的Rendering ...

  5. Unity5 的新旧延迟渲染Deferred Lighting Rendering Path

    unity5 的render path ,比4的区别就是使用的新的deferred rendering,之前的4的deferred rendering(其实是light prepass)也被保留了下来 ...

  6. Unity3D光照前置知识——Rendering Paths(渲染路径)及LightMode(光照模式)译解

    简述 Unity supports different Rendering Paths. You should choose which one you use depending on your g ...

  7. Unity Lighting - Choosing a Rendering Path 选择渲染路径(三)

      Choosing a Rendering Path 选择渲染路径 Unity supports a number of rendering techniques, or ‘paths’. An i ...

  8. 渲染路径-Unity5 的新旧推迟渲染Deferred Lighting Rendering Path

    Unity5 的新旧延迟渲染Deferred Lighting Rendering Path unity5 的render path ,比4的区别就是使用的新的deferred rendering,之 ...

  9. shader 3 rendering path

    渲染通道, rendering path. vertexlit, forward 和 Deferred lighting 旧有的非统一架构下: 分为顶点着色引擎和像素渲染通道 渲染通道是GPU负责给图 ...

随机推荐

  1. ASP.NET Core HTTP 管道中的那些事儿

    前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情.首先是 NPOI ...

  2. 前端学HTTP之字符集

    前面的话 HTTP报文中可以承载以任何语言表示的内容,就像它能承载图像.影片或任何类型的媒体那样.对HTTP来说,实体主体只是二进制信息的容器而已.为了支持国际性内容,服务器需要告知客户端每个文档的字 ...

  3. PHP 获取 特定时间范围 类

    目录  前序 用途 功能及事项 使用方法 代码及注释 前序: 总体来说,我更应该是一个 android 移动开发者,而不是一个 phper,如果说只做移动端的 APP ,我也不会学这么多,这 2年来, ...

  4. 微信小程序开发日记——高仿知乎日报(下)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  5. DevOps对于企业IT的价值

    其实从敏捷延展开的 DevOps 概念很早就已经被提出,不过由于配套的技术成熟度水平层次不齐, DevOps 的价值一直没有有效地发挥出来.现如今,随着容器技术的发展, DevOps 在企业中的实践难 ...

  6. [转]thinkphp 模板显示display和assign的用法

    thinkphp 模板显示display和assign的用法 $this->assign('name',$value); //在 Action 类里面使用 assign 方法对模板变量赋值,无论 ...

  7. HTML5- Canvas入门(五)

    今天要介绍的是canvas对图形对象的操作,包括图像.视频绘制,和操作像素对象的方法. 图片/视频的绘制 在canvas中,我们可以通过 drawImage() 的方法来绘制图片或视频文件,其语法为: ...

  8. 浅谈浏览器http的缓存机制

    针对浏览器的http缓存的分析也算是老生常谈了,每隔一段时间就会冒出一篇不错的文章,其原理也是各大公司面试时几乎必考的问题. 之所以还写一篇这样的文章,是因为近期都在搞新技术,想“回归”下基础,也希望 ...

  9. 分享我对 ASP.NET vNext 的一些感受,也许多年回过头看 So Easy!

    写在前面 阅读目录: Visual Studio "14" CTP 关于 ASP.NET vNext ASP.NET vNext 实践 后记 ASP.NET vNext 发布已经过 ...

  10. python 学习总结

    背景:本文类似文章的目录部分,以系统学习python 新知识和复习总结用 摘要: python 基本语法 numpy库 matplotlib绘图库 pandas库 scikit-learn 机器学习库 ...