欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity3D Shader实现流光效果

程序员文章站 2023-02-19 16:10:58
本文实例为大家分享了unity3d shader实现流光效果的具体代码,供大家参考,具体内容如下流光效果图:演示工程:下载地址//功能需求:模拟数据传送效果,高亮色块从模型上方移动到下方//功能分析:...

本文实例为大家分享了unity3d shader实现流光效果的具体代码,供大家参考,具体内容如下

流光效果图:

Unity3D Shader实现流光效果

演示工程:下载地址

//功能需求:模拟数据传送效果,高亮色块从模型上方移动到下方
//功能分析:这里采用uv动画的方式来实现,利用alpha贴图控制流动的形状
//  利用alpha遮罩贴图,控制模型中哪些地方需要进行流动

shader "custom/datafloweffect"
{
 properties
 {
 _maincolor("main color",color) = (1,1,1,1)
 _maintex("main texture",2d) = "white"{}
 _specular("specular",color) = (1,1,1,1)
 _gloss("gloss",range(0,255)) = 20.0
 _flowtex("flow tex (a)",2d) = "black"{}
 _flowcolor("flow color (rgba)",color)=(1,1,1,1)
 _flowidletime("flowinternal",range(0,10))=1.0
 _flowduring("flowduring",range(0,10))=1.0
 _flowmasktex("flowmasking (a)",2d)="white"{}
 _flowdirection("flowdirection",int)= 0
 _flowbegintime("flow begin time",float)=0
 }

 subshader
 {
 tags{"rendertype" = "opaque" "queue"="geometry"}

 pass
 {
  tags{"lightmode"="forwardbase"}
  blend srcalpha oneminussrcalpha

  cgprogram

  #pragma vertex vert
  #pragma fragment frag

  #include "unitycg.cginc"
  #include "lighting.cginc"

  sampler2d _maintex; //颜色贴图
  half4 _maintex_st; //颜色uv 缩放和偏移
  fixed3 _maincolor; //漫反射颜色
  fixed3 _specular; //高光颜色
  fixed _gloss;  //高光度
  sampler2d _flowtex; //数据流图片
  fixed4 _flowcolor; //数据流颜色叠加
  half4 _flowtex_st; //数据流贴图uv的缩放和偏移
  fixed _flowidletime; //流动动画间歇时间
  fixed _flowduring; //流动动画播放时间
  sampler2d _flowmasktex; //流动遮罩
  fixed _flowdirection; //流动方向
  float _flowbegintime; //流动效果开始的时间

  struct a2v
  {
  half4 pos: position;
  half3 normal :normal;
  half4 texcoord : texcoord0;
  };

  struct v2f
  {
  half4 position : sv_position;
  half2 uv : texcoord0;
  half3 worldnormal : texcoord1;
  half3 worldpos : texcoord2;
  half2 flowuv : texcoord3;
  };

  v2f vert(a2v i)
  {
  v2f v;
  v.position = unityobjecttoclippos(i.pos);
  v.uv = i.texcoord * _maintex_st.xy + _maintex_st.zw;
  v.worldnormal = mul(unity_objecttoworld,i.normal);
  v.worldpos = mul(unity_objecttoworld,i.pos);
  v.flowuv = i.texcoord * _flowtex_st.xy + _flowtex_st.zw;
  return v;
  }

  //uv - vert的uv坐标
  //scale - 贴图缩放
  //idletime - 每次循环开始后多长时间,开始流动
  //looptime - 单次流动时间
  fixed4 getflowcolor(half2 uv,int scale,fixed idletime,fixed looptime)
  {
  //当前运行时间
  half flowtime_ = _time.y - _flowbegintime;

  //上一次循环开始,到本次循环开始的时间间隔
  half internal = idletime + looptime;

  //当前循环执行时间
  half curlooptime = fmod(flowtime_,internal);

  //每次开始流动之前,有个停止间隔,检测是否可以流动了
  if(curlooptime > idletime)
  {
   //已经流动时间
   half actiontime = curlooptime - idletime;

   //流动进度百分比
   half actionpercentage = actiontime / looptime;

   half length = 1.0 / scale;

   //从下往上流动
   //计算方式:设:y = ax + b,其中y为下边界值,x为流动进度
   //根据我们要求可以,x=0时y=-length;x=1时y=1;带入解方程
   half bottomborder = actionpercentage * (1+length) - length;
   half topborder = bottomborder + length;

   //从上往下流动
   //求解方法与上面类似
   if(_flowdirection < 0)
   {
   topborder = (-1-length) * actionpercentage + 1 + length;
   bottomborder = topborder - length;
   }

   if(uv.y < topborder && uv.y > bottomborder)
   {
   half y = (uv.y - bottomborder) / length;
   return tex2d(_flowtex,fixed2(uv.x,y)); 
   }
  }

  return fixed4(1,1,1,0);
  }

  fixed4 frag(v2f v):sv_target
  {
  //计算漫反射系数
  fixed3 albedo = tex2d(_maintex,v.uv) * _maincolor;

  //计算环境光
  fixed3 ambient = unity_lightmodel_ambient.xyz * albedo;


  fixed3 worldnormal = normalize(v.worldnormal);    //世界坐标的法线方向
  fixed3 worldlightdir = normalize(unityworldspacelightdir(v.worldpos)); //世界坐标的光照方向
  fixed3 worldviewdir = normalize(unityworldspaceviewdir(v.worldpos)); //世界坐标的视角方向

  //计算漫反射颜色,采用half-lambert模型
  fixed3 lightcolor = _lightcolor0.rgb;
  fixed3 diffuse = lightcolor * albedo * max(0,0.5*dot(worldnormal,worldlightdir)+0.5);

  //计算高光,采用blinn-phone高光模型
  fixed3 halfdir = normalize(worldviewdir + worldlightdir);
  fixed3 speccolor = _specular * lightcolor * pow(max(0,dot(worldnormal,halfdir)),_gloss);

  //叠加流动贴图  
  fixed4 flowcolor = getflowcolor(v.uv,_flowtex_st.y,_flowidletime,_flowduring); 
  fixed4 flowmaskcolor = tex2d(_flowmasktex,v.uv);

  //与遮罩贴图进行混合,只显示遮罩贴图不透明的部分
  flowcolor.a = flowmaskcolor.a * flowcolor.a * _flowcolor.a;

  fixed3 finaldiffuse = lerp(diffuse,_flowcolor,flowcolor.a);

  return fixed4(ambient + finaldiffuse+speccolor,1);
  }

  endcg
 }
 }
 fallback "diffuse"
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。