Unity Shader 广告牌闪光特效

原文链接:

点击打开链接

这个可能是有点费,因为不是对一张图片进行uv坐标的位移,然后两张图片合成的方法,而是在shader里面纯计算的方法实现的,可能有点费,性能暂未测试。

下面是shader代码:

Shader "MyShader/Flash" {
    Properties {
        _MainTex ("MainTexture", 2D) = "white" {}
        _MaskTex ("MaskTexture", 2D) = "white" {}     
		_FlashColor ("FlashColor", Color) = (0.5,0.5,0.5,1)
		_FlashAngle("FlashAngle",Range(0,180))=60
		_xLength("xLength",float)=0.25
		_Interval("Interval",float)=5
		_BeginTime("BeginTime",float)=2
		_offsetX("OffsetX",float)=0.15
		_loopTime("loopTime",float)=0.7
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Cull Off
                       
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles 
            #pragma target 3.0
            uniform fixed4 _LightColor0;
            uniform sampler2D _MainTex; uniform fixed4 _MainTex_ST;
            uniform sampler2D _MaskTex; uniform fixed4 _MaskTex_ST;
            uniform fixed4 _FlashColor;

			fixed _FlashAngle;
			fixed _xLength;
			fixed _Interval;
			fixed _BeginTime;
			fixed _offsetX;
			fixed _loopTime;

            struct VertexInput {
                fixed4 vertex : POSITION;
                fixed3 normal : NORMAL;
                fixed2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                fixed4 pos : SV_POSITION;
                fixed2 uv0 : TEXCOORD0;
                fixed4 posWorld : TEXCOORD1;
                fixed3 normalDir : TEXCOORD2;
                LIGHTING_COORDS(3,4)
                UNITY_FOG_COORDS(5)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                fixed3 lightColor = _LightColor0.rgb;
                o.pos = UnityObjectToClipPos( v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }

	    //必须放在使用其的 frag函数之前,否则无法识别。
            //核心:计算函数,角度,uv,光带的x长度,间隔,开始时间,偏移,单次循环时间
            fixed inFlash(fixed angle,fixed2 uv,fixed xLength,int interval,int beginTime, fixed offX, fixed loopTime)
            {
                //亮度值
                fixed brightness =0;
               
                //倾斜角
                fixed angleInRad = 0.0174444 * angle;
               
                //当前时间
                fixed currentTime = _Time.y;
           
                //获取本次光照的起始时间
                int currentTimeInt = _Time.y/interval;
                currentTimeInt *=interval;
               
                //获取本次光照的流逝时间 = 当前时间 - 起始时间
                fixed currentTimePassed = currentTime -currentTimeInt;
                if(currentTimePassed >beginTime)
                {
                    //底部左边界和右边界
                    fixed xBottomLeftBound;
                    fixed xBottomRightBound;

                    //此点边界
                    fixed xPointLeftBound;
                    fixed xPointRightBound;
                   
                    fixed x0 = currentTimePassed-beginTime;
                    x0 /= loopTime;
           
                    //设置右边界
                    xBottomRightBound = x0;
                   
                    //设置左边界
                    xBottomLeftBound = x0 - xLength;

                   
                    //投影至x的长度 = y/ tan(angle)
                    fixed xProjL;
                    xProjL= (uv.y)/tan(angleInRad);

                    //此点的左边界 = 底部左边界 - 投影至x的长度
                    xPointLeftBound = xBottomLeftBound - xProjL;
                    //此点的右边界 = 底部右边界 - 投影至x的长度
                    xPointRightBound = xBottomRightBound - xProjL;
                   
                    //边界加上一个偏移
                    xPointLeftBound += offX;
                    xPointRightBound += offX;
                   
                    //如果该点在区域内
                    if(uv.x > xPointLeftBound && uv.x < xPointRightBound)
                    {
                        //得到发光区域的中心点
                        fixed midness = (xPointLeftBound + xPointRightBound)/2;
                       
                        //趋近中心点的程度,0表示位于边缘,1表示位于中心点
                        fixed rate= (xLength -2*abs(uv.x - midness))/ (xLength);
                        brightness = rate;
                    }
                }
                brightness= max(brightness,0);
               
                //返回颜色 = 纯白色 * 亮度
                fixed4 col = fixed4(1,1,1,1) *brightness;
                return brightness;
            }

            fixed4 frag(VertexOutput i, fixed facing : VFACE) : COLOR {
                fixed isFrontFace = ( facing >= 0 ? 1 : 0 );
                fixed faceSign = ( facing >= 0 ? 1 : -1 );
                i.normalDir = normalize(i.normalDir);
                i.normalDir *= faceSign;
                fixed3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
                fixed3 normalDirection = i.normalDir;
                fixed3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 lightColor = _LightColor0.rgb;
// Lighting:
                fixed attenuation = LIGHT_ATTENUATION(i);
                fixed3 attenColor = attenuation * _LightColor0.xyz;
/// Diffuse:
                fixed NdotL = max(0.0,dot( normalDirection, lightDirection ));
                fixed3 directDiffuse = max( 0.0, NdotL) * attenColor;
                fixed3 indirectDiffuse = fixed3(0,0,0);
                indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light
                fixed4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
                fixed3 diffuseColor = _MainTex_var.rgb;
                fixed3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;
// Emissive:
                fixed4 _MaskTex_var = tex2D(_MaskTex,TRANSFORM_TEX(i.uv0, _MaskTex));

/// Final Color:
                fixed3 finalColor = diffuse ;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);

				//传进i.uv等参数,得到亮度值
                fixed tmpBrightness;
                tmpBrightness =inFlash(_FlashAngle,i.uv0,_xLength,_Interval,_BeginTime,_offsetX,_loopTime);

				 //图像区域,判定设置为 颜色的A > 0.5,输出为材质颜色+光亮值
                if(finalRGBA.w >0.5)
                        finalRGBA  =finalRGBA+_FlashColor*tmpBrightness;
                //空白区域,判定设置为 颜色的A <=0.5,输出空白
                else
                    finalRGBA =fixed4(0,0,0,0);

                return finalRGBA;
            }
            ENDCG
        }
        Pass {
            Name "FORWARD_DELTA"
            Tags {
                "LightMode"="ForwardAdd"
            }
            Blend One One
            Cull Off
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDADD
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdadd_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles 
            #pragma target 3.0
            uniform fixed4 _LightColor0;
            uniform sampler2D _MainTex; uniform fixed4 _MainTex_ST;
            uniform sampler2D _MaskTex; uniform fixed4 _MaskTex_ST;

            struct VertexInput {
                fixed4 vertex : POSITION;
                fixed3 normal : NORMAL;
                fixed2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                fixed4 pos : SV_POSITION;
                fixed2 uv0 : TEXCOORD0;
                fixed4 posWorld : TEXCOORD1;
                fixed3 normalDir : TEXCOORD2;
                LIGHTING_COORDS(3,4)
                UNITY_FOG_COORDS(5)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                fixed3 lightColor = _LightColor0.rgb;
                o.pos = UnityObjectToClipPos( v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            fixed4 frag(VertexOutput i, fixed facing : VFACE) : COLOR {
                fixed isFrontFace = ( facing >= 0 ? 1 : 0 );
                fixed faceSign = ( facing >= 0 ? 1 : -1 );
                i.normalDir = normalize(i.normalDir);
                i.normalDir *= faceSign;
                fixed3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
                fixed3 normalDirection = i.normalDir;
                fixed3 lightDirection = normalize(lerp(_WorldSpaceLightPos0.xyz, _WorldSpaceLightPos0.xyz - i.posWorld.xyz,_WorldSpaceLightPos0.w));
                fixed3 lightColor = _LightColor0.rgb;
// Lighting:
                fixed attenuation = LIGHT_ATTENUATION(i);
                fixed3 attenColor = attenuation * _LightColor0.xyz;
/// Diffuse:
                fixed NdotL = max(0.0,dot( normalDirection, lightDirection ));
                fixed3 directDiffuse = max( 0.0, NdotL) * attenColor;
                fixed4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
                fixed3 diffuseColor = _MainTex_var.rgb;
                fixed3 diffuse = directDiffuse * diffuseColor;
/// Final Color:
                fixed3 finalColor = diffuse;
                fixed4 finalRGBA = fixed4(finalColor * 1,0);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
        Pass {
            Name "ShadowCaster"
            Tags {
                "LightMode"="ShadowCaster"
            }
            Offset 1, 1
            Cull Off
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_SHADOWCASTER
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_shadowcaster
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles 
            #pragma target 3.0
            struct VertexInput {
                fixed4 vertex : POSITION;
            };
            struct VertexOutput {
                V2F_SHADOW_CASTER;
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.pos = UnityObjectToClipPos( v.vertex );
                TRANSFER_SHADOW_CASTER(o)
                return o;
            }
            fixed4 frag(VertexOutput i, fixed facing : VFACE) : COLOR {
                fixed isFrontFace = ( facing >= 0 ? 1 : 0 );
                fixed faceSign = ( facing >= 0 ? 1 : -1 );
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

这个是在mainTex基础上加了一个maskTex,目的是为了让扫光区域外的部分不接受扫光。

整体效果还不错,性能消耗待检验。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值