找回密码
 立即注册
查看: 453|回复: 0

Unity——Shader学习13——From庄懂(特效篇):AC、AB ...

[复制链接]
发表于 2021-12-17 17:26 | 显示全部楼层 |阅读模式
第十三课(特效篇)

<hr/>本课任务:


  • 特效大纲
  • AC(AlphaCutout)
  • AB(AlphaBlend)
  • AD(Addtive)
  • 混合模式
  • 美术自定义混合面板
<hr/>一、特效大纲

1.特效·透

  • AlphaCutOut(AC)
  • AlphaBlend(AB)
  • Additive(AD)
  • 其他混合效果



2.特效·动

  • 参数动画:面板上的参数做动画,(标量、位置、颜色、向量...)
  • UV动画:
    UV流动:一般拿UV的Offset做流动动画
    UV扰动:UV做扰动+映射
    序列帧动画:拿UV走序列,如1张图是3x3的九宫格,拿UV去走每一格
  • 顶点动画
    顶点位置动画:下面视频中的食物动画就是用顶点位置动画实现的,不是骨骼实现的
    顶点颜色动画:通常和粒子相关,粒子颜色、显示、消失等


https://www.zhihu.com/video/1433564662336389120
序列帧动画:


https://www.zhihu.com/video/1433564838043324416
序列帧动画案例:案例来源:v_xchen_v

3.特效·映射

  • 极坐标:可以制作圆形的法阵,做一些极坐标的动画
  • 屏幕坐标UV:(之前讲过)拿屏幕坐标UV采样贴图,配合UV扰动可以做出下面透明扭曲的效果
  • 透明扭曲


https://www.zhihu.com/video/1433565046320885760
<hr/>二、透明剪切·AlphaCutout(AC)(或者AlphaTest)

介绍:只有完全透明和不完全透明2种情况,无中间半透明情况,其本质是舍弃了某些片元
用途:

  • 常用于复杂轮廓,边缘明确的物体表现,如:镂空金属,裙摆边缘,特定风格的头发,树叶等。(像丝袜的网孔,写实的头发,其边缘就表达不能确了)
  • 卡通渲染表现,一般配上抗锯齿后处理+Bloom(辉光)
优点:

  • 无排序问题
缺点:

  • 边缘效果太实
  • 移动端性能较差
  • 有很强的锯齿



AC:右;AB:左

Shader代码


1.Properties  声明:
_MainTex  : 要带透明度的贴图
_Cutoff  : 透明剪切阈值
2.SubShader Tags
Tags {
         "Queue" = "AlphaTest"               //渲染队列2450
         "IgnoreProjector" = "True"          //shader不会受到投影器(Projectors)的影响
         "ForceNoShadowCasting" = "True"     //关闭阴影投射
         "RenderType" = "TransparentCutout"  //把Shader归入到提前定义的组(这里是TransparentCutout组)
                                              //以指明该Shader使用了透明度测试
                                              //RenderType标签通常被用于着色器替换功能3.用clip函数对采样纹理进行透明度剪切
clip(var_MainTex.a - _Cutoff);  //如果clip里面的值小于0,则剔除该片元这里我在Pass里面 使用了渲染设置 Cull Off关闭背面剔除
具体代码:
Shader "AP1/L13/AlphaCutout" {
        Properties{
        _MainTex ("RGB:颜色 ; A:透贴" , 2D) = "white"{}
        _Cutoff  ("Cutoff" , Range(0.0 , 1.0)) = 0.5
        }
        SubShader{
                Tags {
                        "Queue" = "AlphaTest"               //渲染队列2450
            "IgnoreProjector" = "True"          //shader不会受到投影器(Projectors)的影响
            "ForceNoShadowCasting" = "True"     //关闭阴影投射
            "RenderType" = "TransparentCutout"  //把Shader归入到提前定义的组(这里是TransparentCutout组)
                                                 //以指明该Shader使用了透明度测试
                                                 //RenderType标签通常被用于着色器替换功能
                }
                Pass {
                        Name "FORWARD"
                        Tags {
                                "LightMode" = "ForwardBase"
                        }

            Cull Off        //关闭背面剔除
                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #include "UnityCG.cginc"
                        #pragma multi_compile_fwdbase_fullshadows
                        #pragma target 3.0

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform fixed      _Cutoff;

                        struct VertexInput {
                                float4 vertex : POSITION;
                float2 uv0    : TEXCOORD0;
                        };
                        struct VertexOutput {
                                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                        };
                        VertexOutput vert(VertexInput v) {
                                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
                                return o;
                        }

                        fixed4 frag(VertexOutput i) : SV_TARGET {

                fixed4 var_MainTex = tex2D(_MainTex , i.uv0);
                clip(var_MainTex.a - _Cutoff);                //如果clip里面的值小于0,则剔除该片元
                               
                                return fixed4(var_MainTex.rgb ,1.0);       
                        }
                                ENDCG
                }
        }
                FallBack "Diffuse"                                               
}<hr/>三、透明混合·AlphaBlend(AB)

介绍:有半透明效果,将源颜色(该片元颜色)目标颜色(颜色缓冲区颜色)进行混合
用途:

  • 用于复杂轮廓,无明确边缘的物体表现
  • 半透明物体的表现
  • 一般的特效表现,打底用
优点:

  • 移动端性能较好
  • 边缘效果好,有过渡
缺点:

  • 有排序问题,需要关闭深度写入



AC:右;AB:左

Shader代码


Queue : 控制渲染队列,使Unity能够先渲染不透明物体,再渲染带透明度的物体
Blend : 混合方式,源颜色和目标颜色的混合算法的一部分
(这里是 Blend One OneMinusSrcAlpha,是因为所用贴图的rgb已经预乘过了alpha通道了,如果没有预乘过则应写成 Blend SrcAlpha OneMinusSrcAlpha)(具体解释看十五课)
注意:AB涉及到了透明度混合,因此想要渲染双面显示,不能直接简单地写 Cull Off ,应该用2个Pass来分别渲染前后面

具体代码:
Shader "AP1/L13/AlphaBlend" {
        Properties{
        _MainTex ("RGB:颜色 ; A:透贴" , 2D) = "white"{}
        }
        SubShader{
                Tags {
                        "Queue" = "Transparent"              //渲染队列3000
            "RenderType" = "Transparent"         //把Shader归入到提前定义的组(这里是Transparent组)
                                                 //以指明该Shader使用了透明度测试
                                                 //RenderType标签通常被用于着色器替换功能
            "IgnoreProjector" = "True"           //shader不会受到投影器(Projectors)的影响
            "ForceNoShadowCasting" = "True"      //关闭阴影投射

                }
                Pass {
                        Name "FORWARD"
                        Tags {
                                "LightMode" = "ForwardBase"
                        }
                        ZWrite Off                                                        //关闭深度写入
            Blend One OneMinusSrcAlpha          //修改混合方式


                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #include "UnityCG.cginc"
                        #pragma multi_compile_fwdbase_fullshadows
                        #pragma target 3.0

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;

                        struct VertexInput {
                                float4 vertex : POSITION;
                float2 uv0    : TEXCOORD0;
                        };
                        struct VertexOutput {
                                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                        };
                        VertexOutput vert(VertexInput v) {
                                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
                                return o;
                        }

                        fixed4 frag(VertexOutput i) : SV_TARGET {

                fixed4 var_MainTex = tex2D(_MainTex , i.uv0);                               
                                return fixed4(var_MainTex);                //最终输出
                        }
                                ENDCG
                }
        }
                FallBack "Diffuse"                                               
}<hr/>四、透明度叠加·Additive(AD)

用途:

  • 常用于发光体,辉光
  • 一般用于特效提亮
问题:

  • 有排序问题,需要关闭深度写入
  • 叠加多层后 容易爆性能(OverDraw),一个像素会算多次叠加
  • 辉光效果,通常可以用后处理Bloom替代


Shader代码:


只是在AB的基础上修改混合模式为 Blend One One 即可,达到提亮的效果
(注意:这里前面的One 是用了预乘后的贴图,如果没有预乘,则要在Shader里面预乘)
为什么最后输出alpha通道可以设置为1.0:因为AD的混合因子为 One One ,与透明度无关,因此最终输出的RGB不会受到alpha值的影响,你将其设置为0.0也不会有任何改变
具体代码:
Shader "AP1/L13/Addtive" {
        Properties{
        _MainTex ("RGB:颜色 ; A:透贴" , 2D) = "white"{}
        }
        SubShader{
                Tags {
                        "Queue" = "Transparent"              //渲染队列3000
            "RenderType" = "Transparent"         //把Shader归入到提前定义的组(这里是Transparent组)
                                                 //以指明该Shader使用了透明度测试
                                                 //RenderType标签通常被用于着色器替换功能
            "IgnoreProjector" = "True"           //shader不会受到投影器(Projectors)的影响
            "ForceNoShadowCasting" = "True"      //关闭阴影投射

                }
                Pass {
                        Name "FORWARD"
                        Tags {
                                "LightMode" = "ForwardBase"
                        }
                        ZWrite Off                           //关闭深度写入
            Blend One One          //修改混合方式

                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #include "UnityCG.cginc"
                        #pragma multi_compile_fwdbase_fullshadows
                        #pragma target 3.0

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;

                        struct VertexInput {
                                float4 vertex : POSITION;
                float2 uv0    : TEXCOORD0;
                        };
                        struct VertexOutput {
                                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                        };
                        VertexOutput vert(VertexInput v) {
                                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
                                return o;
                        }

                        fixed4 frag(VertexOutput i) : SV_TARGET {

                fixed4 var_MainTex = tex2D(_MainTex , i.uv0);                               
                                return fixed4(var_MainTex.rgb , 1.0);                //最终输出,因为Blend One One 最终输出RGB与透明度无关,所以alpha可以设置为常数
                        }
                                ENDCG
                }
        }
                FallBack "Diffuse"                                               
}


AC、AB、AD对比

五、混合模式

各种混合模式,就是一个个函数,参数是混合因子和运算符,变量是源颜色和目标颜色
(拿PS类比:PS的上图层——源颜色,下图层——目标颜色)
关于混合计算方式可以参考我的另一篇文章:TecrayC:《UnityShader入门精要》学习笔记——第八章——透明效果  中的混合命令






<hr/>六、美术自定义混合面板




左边:一般给美术调试效果; 右边:进行相应封装(需要C#)

代码实现:


[Enum(UnityEngine.Rendering.BlendMode)]   //[枚举Enum(枚举类型)]
_BlendSrc("混合源乘子" , int) = 0           //_BlendSrc , int型Enum是枚举的意思,后面小括号内是枚举类型
BlendOp [_BlendOp]                      //可自定义混合算符
Blend   [_BlendSrc]  [_BlendDst]        //可自定义混合模式在定义变量时BlendOp(混合算符)Blend(混合模式) 的参数填写 面板参数
具体代码:
Shader "AP1/L13/BlendMode" {
        Properties{
        _MainTex ("RGB:颜色 ; A:透贴" , 2D) = "white"{}

        [Enum(UnityEngine.Rendering.BlendMode)]   //[枚举Enum(枚举类型)]
        _BlendSrc("混合源乘子" , int) = 0          //_BlendSrc , int型
        [Enum(UnityEngine.Rendering.BlendMode)]
        _BlendDst("混合目标乘子" , int) = 0        //_BlendDst
        [Enum(UnityEngine.Rendering.BlendOp)]
        _BlendOp("混合算符" , int) = 0             //_BlendOp
        }
        SubShader{
                Tags {
                        "Queue" = "Transparent"              //渲染队列3000
            "RenderType" = "Transparent"         //把Shader归入到提前定义的组(这里是Transparent组)
                                                 //以指明该Shader使用了透明度测试
                                                 //RenderType标签通常被用于着色器替换功能
            "IgnoreProjector" = "True"           //shader不会受到投影器(Projectors)的影响
            "ForceNoShadowCasting" = "True"      //关闭阴影投射

                }
                Pass {
                        Name "FORWARD"
                        Tags {
                                "LightMode" = "ForwardBase"
                        }
                        ZWrite Off                                                        //关闭深度写入
            BlendOp [_BlendOp]                      //可自定义混合算符
            Blend   [_BlendSrc]  [_BlendDst]        //可自定义混合模式


                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #include "UnityCG.cginc"
                        #pragma multi_compile_fwdbase_fullshadows
                        #pragma target 3.0

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;

                        struct VertexInput {
                                float4 vertex : POSITION;
                float2 uv0    : TEXCOORD0;
                        };
                        struct VertexOutput {
                                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                        };
                        VertexOutput vert(VertexInput v) {
                                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv0 = v.uv0 * _MainTex_ST.xy + _MainTex_ST.zw;
                                return o;
                        }

                        fixed4 frag(VertexOutput i) : SV_TARGET {

                fixed4 var_MainTex = tex2D(_MainTex , i.uv0);                               
                                return fixed4(var_MainTex);               
                        }
                                ENDCG
                }
        }
                FallBack "Diffuse"                                               
}

https://www.zhihu.com/video/1433565970187497472
<hr/>第十三课总结:


  • 特效有透明,动画,映射等
  • AC(AlphaCutout)是直接去掉透明度超过某一阈值的片元
  • AB(AlphaBlend)和AD(Addtive)都是应用了透明度混合,用到了混合模式
  • 混合模式有很多种,其本质上是一种关于源颜色、目标颜色、源混合因子、目标混合因子的算法,可以自己设定面板参数进行枚举调节

参考资料:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-23 01:22 , Processed in 0.090167 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表