Unity3D Shader实现流光效果

所属分类: 软件编程 / C#教程 阅读数: 135
收藏 0 赞 0 分享

本文实例为大家分享了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"
}

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

更多精彩内容其他人还在看

c#开发word批量转pdf源码分享

已经安装有Office环境,借助一些简单的代码即可实现批量Word转PDF,看下面的实例源码吧
收藏 0 赞 0 分享

c# xml API操作的小例子

这篇文章主要介绍了c# xml API操作的小例子,有需要的朋友可以参考一下
收藏 0 赞 0 分享

c#唯一值渲染实例代码

这篇文章主要介绍了c#唯一值渲染实例代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

淘宝IP地址库采集器c#代码

这篇文章主要介绍了淘宝IP地址库采集器c#代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C#在后台运行操作(BackgroundWorker用法)示例分享

BackgroundWorker类允许在单独的专用线程上运行操作。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题,下面看示例
收藏 0 赞 0 分享

c#文本加密程序代码示例

这是一个加密软件,但只限于文本加密,加了窗口控件的滑动效果,详细看下面的代码
收藏 0 赞 0 分享

c#生成站点地图(SiteMapPath)文件示例程序

这篇文章主要介绍了c#生成站点地图(SiteMapPath)文件的示例,大家参考使用
收藏 0 赞 0 分享

C# 键盘Enter键取代Tab键实现代码

这篇文章主要介绍了C# 键盘Enter键取代Tab键实现代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C# WinForm导出Excel方法介绍

在.NET应用中,导出Excel是很常见的需求,导出Excel报表大致有以下三种方式:Office PIA,文件流和NPOI开源库,本文只介绍前两种方式
收藏 0 赞 0 分享

C#串口通信程序实例详解

在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports,创建C#串口通信程序的具体实现是如何的呢?让我们开始吧
收藏 0 赞 0 分享
查看更多