【学习&分享】UCTS(Unity Chan Toon Shader)卡通渲染项目解析

        Unity Chan Toon Shader(简称UCTS)是一款专为Unity引擎设计的卡通着色器,旨在满足创作者在创建卡通风格3DCG动画时的需求。UCTS由Unity3DJapan社区开发,是一个开源项目,展示了如何使用Unity创建具有动漫风格的3D角色和场景,提供实时可调的卡通渲染效果,包括阴影、高光、轮廓光等多种效果,以及丰富的参数供用户自定义。

        官网链接: 这是官网,日语上手的话,可以直接去官网学习、下载各种资源。

        GitHub开源项目链接:这是Github,日语苦手的话,可以直接下载开源项目。

       进了项目可以到处摸一摸,Sample Scenes下有不少示例场景,做的很可爱,可以进去看一看。

        

(可爱)

一、项目内容整理

        UCTS项目主要还是为了实现对美术的支持,如果能把这些对美术支持的操作都学会了,之后就可以潇洒地给自己项目组里的美术提供技术支持了。

         1.1 编辑器拓展        

        由于UCTS的Shader设计以功能全面为主要目标,后续实战使用的时候一般以裁剪Shader为主,UCTS的原始Shader有大量的Property供美术表现调整使用,如果按照原本默认的Shader面板来展示的话,势必会乱成一锅粥。这里项目里准备了一系列编辑器拓展脚本来完成这些功能,位于Assets/Toon/Editor下,包括一个编排ShaderProperty的ShaderGUI脚本UTS2GUI,以及3个关联了。

(UTS2GUI把这一部分做得漂漂亮亮的)

(拓展了Material的上下文菜单)

  (对应的脚本)

        UTS2GUI这个脚本是把项目的Shader面板做的漂亮的关键,但其中的代码都是纯苦力活,而且这个Shader牵涉到的参数很多,相对而言会比较枯燥比较累,不难想象开发时的精神状态。

         1.2 后处理效果

        Unity的Built-in管线下,后处理效果需要在MonoBehavior的OnRenderImage()、OnPreRender()、OnPostRender()中编写代码,找到使用的Shader并传参。UCTS项目中为了方便操作和管理,后处理效果的实现统一写在了Post-Processing Behavior中,并通过继承ScriptableObject的PostProcessingProfile来控制场景后处理效果的开启和参数。

        这堆后处理效果中,比较明显的是Bloom辉光效果,画面中的hdr效果由其实现,对整体画面影响比较显著。

(左:Bloom On   右:Bloom Off)

        1.3 着色器和材质

        从整个项目的角度来说,编辑器拓展和后处理效果只是锦上添花的一部分,卡通渲染着色器和材质是UCTS项目最重要的部分。材质可以认为是着色器的实例(类似于UE中的材质和材质实例的关系,但实现上不一样),因此我们主要还是从着色器的角度来分析。总体而言,UCTS是一个相对比较全面的卡通渲染着色器,并且为了更好地控制细节,使用了大量的贴图来控制单一着色技术的使用与范围,如使用裁剪贴图Clipping Mask手动控制裁剪区域、使用Transparent Level+Transclipping Mask控制着色的透明度通道、使用MatCap Mask和MatCap Normal控制球面朝向映射的范围和法向等。通过这些手段,我们可以精确地控制渲染结果的细节。

二、UCTS渲染过程

        在我们正式进入茫茫多的着色器代码之前,我们最好首先使用帧分析器来分析一下UCTS渲染一帧的流程,以此对着色器中各个Pass之间的顺序关系有个初步了解。打开帧分析器(Windows->Analysis->Frame Debugger),点击Enable,截取当前帧的渲染过程。如无其他光源、物体和额外的渲染过程的话,截取的渲染过程将如下图所示(编辑器模式下可能出现渲染了DepthNormalPass的情况)。

        

        (我截取的一帧,红圈中的DrawCall来自同一Pass)

        以当前这一帧为例,渲染的过程大致可以分为以下过程:

        1.ShadowCaster Pass,这个Pass主要解决光照贴图和阴影贴图。卡通渲染的角色通常使用分级的阴影,在后面还需要对阴影进行额外的处理,这里是获取默认的情况,即三维模型之间的光照/阴影关系。这个过程还需要细分为三个渲染过程:深度贴图的渲染、光照贴图的渲染、阴影贴图的渲染,其中深度贴图和阴影贴图都是对摄像机而言的,光照贴图是对光源而言的。

        

        (相机深度贴图)

(光照贴图,视角很奇怪是因为光源在头顶)

(阴影贴图,相对于相机而言的)

        2.外描边OutlinePass。在UCTS中,外描边的光照模式LightMode和不透明物体的LightMode是相同的,都为ForwardBase,两个Pass之间遵循从上到下的顺序执行(实测两者互换不影响渲染结果,外描边的效果与渲染顺序并没有直接关系)。由于这个角色相对复杂一些,帧分析器的内容不够直观,这里换了个场景截的图。

(渲染结果)

(画完头发的外描边Pass的结果)

        3.前向渲染Pass(Forward Pass),最重要的一个Pass,卡通角色渲染的核心Pass,后面会具体展开研究其实现。

(已经接近最终效果)

         4.后处理部分,包括运动模糊、辉光等效果,具体的实现代码和相关shader可以在Post-Processing Behaviour组件源码中找到。

(加上辉光之后效果明显好多了,后处理同样很重要)

        接下来我们找一个Shader来印证一下渲染顺序,可以从场景中带有Skinned Mesh Renderer组件的任意物体的Material中通过齿轮菜单下的Edit Shader进入其Shader源码。

        首先映入眼帘的是茫茫多的Shader Property,在外面是那么的整洁(感谢UTS2GUI.cs),这些全部忽略,实际上Shader的主体非常短,这里可以摘抄大部分。


Shader "UnityChanToonShader/Toon_DoubleShadeWithFeather" 
{
    Properties
    {
        ...
    }
    SubShader 
    {
        Tags 
        {
            "RenderType"="Opaque"
        }
        Pass {
            Name "Outline"
            Tags 
            {
                "LightMode"="ForwardBase"
            }
            Cull Front

            CGPROGRAM

            // #pragma 
            //アウトライン処理はUTS_Outline.cgincへ.
            #include "UCTS_Outline.cginc"
            ENDCG
        }

        Pass
         {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }

            Cull[_CullMode]
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            //#define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog

            //v.2.0.4
            #pragma multi_compile _IS_CLIPPING_OFF
            #pragma multi_compile _IS_PASS_FWDBASE
            //v.2.0.7
            #pragma multi_compile _EMISSIVE_SIMPLE _EMISSIVE_ANIMATION
            //
            #include "UCTS_DoubleShadeWithFeather.cginc"

            ENDCG
        }
        Pass {
            //处理多个光源
            Name "FORWARD_DELTA"
            Tags {
                "LightMode"="ForwardAdd"
            }

            Blend One One
            Cull[_CullMode]
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            //#define UNITY_PASS_FORWARDADD
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            //for Unity2018.x
            #pragma multi_compile_fwdadd_fullshadows
            #pragma multi_comp
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值