首页 > 代码库 > 【Unity技巧】LOGO闪光效果

【Unity技巧】LOGO闪光效果


写在前面


本文参考了风宇冲的博文,在按照这篇博文实现LOGO闪光时,发现了一些问题。最严重的就是背景无法透明,看上去背景始终是黑色的;其次就是各个变量的意义不是非常明确,调节起来不方便;而且在闪光条的角度处理上考虑不全,在角度为钝角时会有Bug。


这篇文章针对上面的问题修改了该Shader,并将各个变量作为Shader面板中的可调节变量,可视化编辑闪光效果。



代码


Shader "Custom/LogoFlash" {
	Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _FlashColor ("Flash Color", Color) = (1,1,1,1)
        _Angle ("Flash Angle", Range(0, 180)) = 45
        _Width ("Flash Width", Range(0, 1)) = 0.2
        _LoopTime ("Loop Time", Float) = 1
        _Interval ("Time Interval", Float) = 3
//        _BeginTime ("Begin Time", Float) = 2
    }
    SubShader
    {
    	Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    
        CGPROGRAM
        #pragma surface surf Lambert alpha
//		#pragma target 3.0

        sampler2D _MainTex;
        float4 _FlashColor;
        float _Angle;
        float _Width;
        float _LoopTime;
        float _Interval;
//        float _BeginTime;
            
        struct Input 
	{
		half2 uv_MainTex;
	};
           
        float inFlash(half2 uv)
        {	
            float brightness = 0;
            
            float angleInRad = 0.0174444 * _Angle;
            float tanInverseInRad = 1.0 / tan(angleInRad);
            
//            float currentTime = _Time.y - _BeginTime;
	    float currentTime = _Time.y;
	    float totalTime = _Interval + _LoopTime;
            float currentTurnStartTime = (int)((currentTime / totalTime)) * totalTime;
            float currentTurnTimePassed = currentTime - currentTurnStartTime - _Interval;
            
            bool onLeft = (tanInverseInRad > 0);
	    float xBottomFarLeft = onLeft? 0.0 : tanInverseInRad;
	    float xBottomFarRight = onLeft? (1.0 + tanInverseInRad) : 1.0;
			
	    float percent = currentTurnTimePassed / _LoopTime;
            float xBottomRightBound = xBottomFarLeft + percent * (xBottomFarRight - xBottomFarLeft);
            float xBottomLeftBound = xBottomRightBound - _Width;
            
            float xProj = uv.x + uv.y * tanInverseInRad;
            
            if(xProj > xBottomLeftBound && xProj < xBottomRightBound)
            {
              	brightness = 1.0 - abs(2.0 * xProj - (xBottomLeftBound + xBottomRightBound)) / _Width;
            }

            return brightness;
        }
        
        void surf (Input IN, inout SurfaceOutput o)
        {                
            half4 texCol = tex2D(_MainTex, IN.uv_MainTex);
            float brightness = inFlash(IN.uv_MainTex);
        
            o.Albedo = texCol.rgb + _FlashColor.rgb * brightness;
            o.Alpha = texCol.a;
        }
        
        ENDCG     
    }
    
    FallBack "Unlit/Transparent"
}


编译成功后,材质面板如图所示:


各变量意义如下:

  • Base (RGB):LOGO的png图片
  • Flash Color:闪光条的光颜色
  • Flash Angle:闪光条的角度,范围是0到180°
  • Flash Width:闪光条宽度,范围是0到1.0
  • Loop Time:闪光条滚动一次的时间
  • Time Interval:两次相邻的闪光条滚动的时间间隔


效果






写在最后


代码中有一个变量的相关代码被注释掉了,即_BeginTime,这个是用来控制第一次闪光的时间。

由于移动端对指令和寄存器的数码要求较高,如果添加_BeginTime及其相关操作就会超过限制,需要指明Shader Mode 3.0。

实际上,用Shader实现LOGO闪光效果比脚本实现(用一张闪光图,在脚本中控制UV坐标来实现)的资源消耗要大很多,因此实际中不建议这样使用。