Unity Shader 图片流光效果实现(纯计算方式)
shader源码如下
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "Custom/StreamerLight" { Properties{ _MainTex("Texture", 2D) = "white" { } _Angle("Angle", Float) = 45 //光带的倾斜角度 _Width("Width",Float)=0.65 //光带的宽度 _Interval("Interval",Float)=3 //间隔时间 _BeginTime("BeginTime",Float)=0 //开始时间 _OffestX("OffestX",Float)=0.6 //光带边界的偏移量 _LoopTime("LoopTime",Float)=0.7 //单次的循环时间 } SubShader { Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"} Blend SrcAlpha OneMinusSrcAlpha AlphaTest Greater 0.1 pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" half _Angle; half _Width; half _Interval; half _BeginTime; half _OffestX; half _LoopTime; sampler2D _MainTex; float4 _MainTex_ST; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; //顶点函数没什么特别的,和常规一样 v2f vert(appdata_base v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord,_MainTex); return o; } //必须放在使用其的 frag函数之前,否则无法识别。 //核心:计算函数,角度,uv,光带的x长度,间隔,开始时间,偏移,单次循环时间 float inFlash(float angle,float2 uv,float xLength,int interval,int beginTime, float offX, float loopTime) { //亮度值 float brightness = 0; //倾斜角 float angleInRad = 0.0174444 * angle; //当前时间 float currentTime = _Time.y; //获取本次光照的起始时间 int currentTimeInt = _Time.y / interval; currentTimeInt *= interval; //获取本次光照的流逝时间 = 当前时间 - 起始时间 float currentTimePassed = currentTime - currentTimeInt; if (currentTimePassed > beginTime) { //底部左边界和右边界 float xBottomLeftBound; float xBottomRightBound; //此点边界 float xPointLeftBound; float xPointRightBound; float x0 = currentTimePassed - beginTime; x0 /= loopTime; //设置右边界 xBottomRightBound = x0; //设置左边界 xBottomLeftBound = x0 - xLength; //投影至x的长度 = y/ tan(angle) float 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) { //得到发光区域的中心点 float midness = (xPointLeftBound + xPointRightBound) / 2; //趋近中心点的程度,0表示位于边缘,1表示位于中心点 float rate = (xLength - 2 * abs(uv.x - midness)) / (xLength); brightness = rate; } } brightness = max(brightness,0); brightness = min(brightness, 0.75); //返回颜色 = 纯白色 * 亮度 float4 col = float4(1,1,1,1) *brightness; return brightness; } float4 frag(v2f i) : COLOR { float4 outp; //根据uv取得纹理颜色,和常规一样 float4 texCol = tex2D(_MainTex,i.uv); //传进i.uv等参数,得到亮度值 float tmpBrightness; tmpBrightness = inFlash(_Angle,i.uv,_Width,_Interval,_BeginTime,_OffestX,_LoopTime); //图像区域,判定设置为 颜色的A > 0.5,输出为材质颜色+光亮值 if (texCol.w > 0.5) outp = texCol + float4(1,1,1,1)*tmpBrightness; //空白区域,判定设置为 颜色的A <=0.5,输出空白 else outp = float4(0,0,0,0); return outp; } ENDCG } }}