【Unity技巧】LOGO闪光效果-----妈妈说女孩子要自立自强

写在前面


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


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



代码


[plain]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. Shader "Custom/LogoFlash" {  
  2.     Properties {  
  3.         _MainTex ("Base (RGB)", 2D) = "white" {}  
  4.         _FlashColor ("Flash Color", Color) = (1,1,1,1)  
  5.         _Angle ("Flash Angle", Range(0, 180)) = 45  
  6.         _Width ("Flash Width", Range(0, 1)) = 0.2  
  7.         _LoopTime ("Loop Time", Float) = 1  
  8.         _Interval ("Time Interval", Float) = 3  
  9. //        _BeginTime ("Begin Time", Float) = 2  
  10.     }  
  11.     SubShader  
  12.     {  
  13.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }  
  14.       
  15.         CGPROGRAM  
  16.         #pragma surface surf Lambert alpha exclude_path:prepass noforwardadd  
  17. //      #pragma target 3.0  
  18.   
  19.         sampler2D _MainTex;  
  20.         float4 _FlashColor;  
  21.         float _Angle;  
  22.         float _Width;  
  23.         float _LoopTime;  
  24.         float _Interval;  
  25. //        float _BeginTime;  
  26.               
  27.         struct Input   
  28.     {  
  29.         half2 uv_MainTex;  
  30.     };  
  31.              
  32.         float inFlash(half2 uv)  
  33.         {     
  34.             float brightness = 0;  
  35.               
  36.             float angleInRad = 0.0174444 * _Angle;  
  37.             float tanInverseInRad = 1.0 / tan(angleInRad);  
  38.               
  39. //            float currentTime = _Time.y - _BeginTime;  
  40.         float currentTime = _Time.y;  
  41.         float totalTime = _Interval + _LoopTime;  
  42.             float currentTurnStartTime = (int)((currentTime / totalTime)) * totalTime;  
  43.             float currentTurnTimePassed = currentTime - currentTurnStartTime - _Interval;  
  44.               
  45.             bool onLeft = (tanInverseInRad > 0);  
  46.         float xBottomFarLeft = onLeft? 0.0 : tanInverseInRad;  
  47.         float xBottomFarRight = onLeft? (1.0 + tanInverseInRad) : 1.0;  
  48.               
  49.         float percent = currentTurnTimePassed / _LoopTime;  
  50.             float xBottomRightBound = xBottomFarLeft + percent * (xBottomFarRight - xBottomFarLeft);  
  51.             float xBottomLeftBound = xBottomRightBound - _Width;  
  52.               
  53.             float xProj = uv.x + uv.y * tanInverseInRad;  
  54.               
  55.             if(xProj > xBottomLeftBound && xProj < xBottomRightBound)  
  56.             {  
  57.                 brightness = 1.0 - abs(2.0 * xProj - (xBottomLeftBound + xBottomRightBound)) / _Width;  
  58.             }  
  59.   
  60.             return brightness;  
  61.         }  
  62.           
  63.         void surf (Input IN, inout SurfaceOutput o)  
  64.         {                  
  65.             half4 texCol = tex2D(_MainTex, IN.uv_MainTex);  
  66.             float brightness = inFlash(IN.uv_MainTex);  
  67.           
  68.             o.Albedo = texCol.rgb + _FlashColor.rgb * brightness;  
  69.             o.Alpha = texCol.a;  
  70.         }  
  71.           
  72.         ENDCG       
  73.     }  
  74.       
  75.     FallBack "Unlit/Transparent"  
  76. }  


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


各变量意义如下:

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


效果






更新


颜色偏暗的问题


下面留言说,上述得到的效果LOGO颜色会偏暗,我原来还真没发现这个问题。。。其实这个问题很好解决,只需要在surf函数里计算颜色值的时候多乘一点参数就可以了,比如像下面这样:
[plain]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. o.Albedo = texCol.rgb * 1.2 + _FlashColor.rgb * brightness;  

这个原理也很简单,就是让颜色更亮而已,这个方法也经常被用于Diffuse等Shader的渲染中。

更新后的效果如下:




移动平台优化的问题


上述的Shader用了非常多的计算,乘法除法之类的,这对于移动平台其实是非常消耗资源的,经常会报寄存器不够的错误。为了优化,我一开始对于乘法和除法做了好久的优化。。。包括少使用临时变量,尽量少使用除法等等。最后结果是刚刚够用。。。但是,如果在上述计算颜色时多乘一个参数,就又超过了。。。所幸的是,前几天学了Shader对手机优化的内容,可参见 这篇博文,在优化了 #pragma后,又重新得以运行。。。

当然,如果你面对的是PC平台,这些问题就不是问题了。只需要把下面这句话的注释去掉就可以了:
[plain]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //      #pragma target 3.0  

这句话表明我们可以使用更多的寄存器了。具体可见 官网解释



写在最后


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

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值