很多游戏Logo中可以看到这种流光效果,一般的实现方案就是对带有光条的图片uv根据时间进行移动,然后和原图就行叠加实现,不过实现过程中稍稍有点需要注意的地方。之前考虑过风宇冲的实现方式,但是考虑到shader中太多的计算,还是放弃了。

基础版本

Shader "UICustom/ImageFlashEffect2"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {} _LightTex ("Light Texture", 2D) = "white" {} _LightColor("Light Color",Color) = (1,1,1,1) _LightPower("Light Power",Range(0,5)) = 1 //每次持续时间,受Angle和Scale影响
_LightDuration("Light Duration",Range(0,10)) = 1
//时间间隔,受Angle和Scale影响
_LightInterval("Light Interval",Range(0,20)) = 3
} SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
} Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
Offset -1, -1
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest Greater 0.1 Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float2 lightuv : TEXCOORD1;
}; sampler2D _MainTex;
float4 _MainTex_ST; sampler2D _LightTex ;
float4 _LightTex_ST; half _LightInterval ;
half _LightDuration ; half4 _LightColor ;
half _LightPower ; half _LightOffSetX ;
half _LightOffSetY ; v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
fixed currentTimePassed = fmod(_Time.y,_LightInterval);
//uv offset, Sprite wrap mode need "Clamp"
fixed offsetX = currentTimePassed / _LightDuration;
fixed offsetY = currentTimePassed / _LightDuration;
fixed2 offset ;
offset.x = offsetX - 0.5f;
offset.y = offsetY - 0.5f; o.lightuv = v.uv + offset ; o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.lightuv = TRANSFORM_TEX(o.lightuv, _LightTex);
return o;
} fixed4 frag (v2f i) : SV_Target
{
fixed4 mainCol = tex2D(_MainTex, i.uv);
fixed4 lightCol = tex2D(_LightTex, i.lightuv);
lightCol *= _LightColor ; //need blend
//lightCol.rgb *= mainCol.rgb ;
fixed4 fininalCol ;
fininalCol.rgb = mainCol.rgb + lightCol.rgb * _LightPower;
fininalCol.a = mainCol.a * lightCol.a ;
return fininalCol ;
}
ENDCG
}
}
}

需要注意的点:

  1. 时间间隔问题
fixed currentTimePassed = fmod(_Time.y,_LightInterval);
//uv offset, Sprite wrap mode need "Clamp"
fixed offsetX = currentTimePassed / _LightDuration;
fixed offsetY = currentTimePassed / _LightDuration;

offsetX 、offsetY其实是0~_LightInterval的数值,需要设置图片为光线图片的Wrap模式为Clamp,才能实现时间间隔控制

  1. 色彩融合

    Pixel着色器中frag()函数是通过原始颜色和光线颜色叠加的方式实现的,也有将光线颜色和原图混合后再叠加的做法,这个我觉得看实际应用。注意alpha的控制

优化

1. 增加角度和大小控制

基本版本的实现中光线只能根据流光图片中亮线的宽度和方向决定实际的滚动方向和大小。有时候如果需要经常调节方向和大小,可以考虑加入相关因素。流光的Uv是通过原图当前Uv加上时间轴参数获得,可以考虑通过修改流光uv的计算方式来实现。如下面代码。不过这种方式增加了一定计算量,不需要的话则直接跳过。还有一点就是流光贴图必须是垂直或者水平。

float2 base = v.uv ;
base.x -= _LightOffSetX ;
base.y -= _LightOffSetX ;
base = base / _LightScale ; float2 base2 = v.uv;
base2.x = base.x * cosInRad - base.y * sinInRad ;
base2.y = base.y * cosInRad + base.x * sinInRad ; o.lightuv = base2 + offset ;
材质复用

只是想不同的图片都是使用相同的材质,应该保证每个图片的效果都可以独立进行修改保存,可以考虑每张图片都创建一份材质,然后修改其参数。

   void UpdateParam()
{
if (Material == null)
{
Debug.LogWarning("Metarial is miss");
return;
} if (mGraphic == null)
{
mGraphic = GetComponent<MaskableGraphic>();
} if (mGraphic is Text)
{
Debug.LogError("FlashEffec need component type of Image、RawImage");
return;
} if (mDynaMaterial == null)
{
mDynaMaterial = new Material(Material);
mDynaMaterial.name = mDynaMaterial.name + "(Copy)";
mDynaMaterial.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
} if (mDynaMaterial == null)
{
return;
} mDynaMaterial.mainTexture = null;
if (OverrideTexture != null)
{
mDynaMaterial.mainTexture = OverrideTexture; if (mGraphic is RawImage)
{
RawImage img = mGraphic as RawImage;
img.texture = null;
}
else if (mGraphic is Image)
{
Image img = mGraphic as Image;
img.sprite = null;
}
}
else
{
mDynaMaterial.mainTexture = mGraphic.mainTexture;
} if (Duration > Interval)
{
Debug.LogWarning("ImageFlashEffect.UpdateParam:Duration need less Interval");
Interval = Duration + 0.5f;
} mDynaMaterial.SetColor("_LightColor", Color);
mDynaMaterial.SetFloat("_LightPower", Power);
mDynaMaterial.SetFloat("_LightScale", Scale);
mDynaMaterial.SetFloat("_LightAngle", Angle);
mDynaMaterial.SetFloat("_LightDuration", Duration);
mDynaMaterial.SetFloat("_LightInterval", Interval);
mDynaMaterial.SetFloat("_LightOffSetX", OffSet);
mGraphic.material = mDynaMaterial;
mGraphic.SetMaterialDirty();
}

下载:https://github.com/carlosCn/Unity_Image_Flash_Effect

参考

http://blog.csdn.net/qq992817263/article/details/51200424

http://qkxue.net/info/169189/Unity-Simple-Shaderlab-uGui-shader-1

Unity Shader 效果(1) :图片流光效果的更多相关文章

  1. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  2. Flash 用FLASH遮罩效果做图片切换效果

    本教程是关于FLASH应用遮罩效果制作好看的图片切换效果.该教程选用FLASH遮罩中最简单的一种作为例子,当然你可以用自己的想象力来做出更多更好的图片动画.希望本教程能带你带来帮助. 让我们先看看效果 ...

  3. Unity shader学习之屏幕后期效果之调整屏幕亮度,饱和度,对比度

    Unity的屏幕后期处理效果,使用MonoBehaviour.OnRenderImage来实现. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7228063 ...

  4. Unity shader学习之屏幕后期处理效果之运动模糊

    运动模糊,代码如下: using UnityEngine; public class MotionBlurRenderer : PostEffectRenderer { [Range(0.1f, 0. ...

  5. Unity shader学习之屏幕后期处理效果之Bloom效果

    Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...

  6. Unity shader学习之屏幕后期处理效果之均值模糊

    均值模糊,也使用卷积来实现,之不过卷积中每个值均相等,且相加等于1. 代码如下, 子类: using UnityEngine; public class MeanBlurRenderer : Post ...

  7. Unity shader学习之屏幕后期处理效果之边缘检测

    边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7232707.html 例如: 代码如下: usin ...

  8. Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法2

    这里使用一种更高效地从深度纹理中重建世界坐标的方法. 首先计算摄像机的视锥体的四条射线向量进行线性插值,插值后的值便是该像素在世界空间坐标下到摄像机的方向. 然后通过与深度值相乘即可得到摄像机位置到该 ...

  9. Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

    来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达 ...

随机推荐

  1. 在C#中使用ZBar识别条形码

    目录: 一.识别库 二.从一张图片中提取多个条形码 三.注意事项 从博客园学了很多,本着分享的目的,希望后来者遇到类似问题时,不必重复造轮子,早点下班回家^-^. 一.识别库 目前主流的识别库主要有Z ...

  2. RNN入门(一)识别MNIST数据集

    RNN介绍   在读本文之前,读者应该对全连接神经网络(Fully Connected Neural Network, FCNN)和卷积神经网络( Convolutional Neural Netwo ...

  3. Python进阶笔记

    列表生成式 函数的参数类型 lambda函数 map, reduce, filter, sorted函数 eval, exec, join, zip函数 itertools中的函数 copy与deep ...

  4. IEnumerable,ICollection,IList接口问题

    最近有一个疑问:IList已经继承了ICollection<T>,而ICollection<T>继承了 IEnumerable<T>, IEnumerable,那为 ...

  5. EChart中使用地图方式总结(转载)

    EChart中使用地图方式总结 2018年02月06日 22:18:57 来源:https://blog.csdn.net/shaxiaozilove/article/details/79274772 ...

  6. 推荐 3 篇关于 java8 Lambda表达式的文章

    State of the Lambda 这篇主要讲 Labmbda 的背景和用法 译文:深入理解Java 8 Lambda(语言篇--lambda,方法引用,目标类型和默认方法) State of t ...

  7. 2015 Multi-University Training Contest 6 solutions BY ZJU(部分解题报告)

    官方解题报告:http://bestcoder.hdu.edu.cn/blog/2015-multi-university-training-contest-6-solutions-by-zju/ 表 ...

  8. SpringBoot的Autowierd失败

    通常是以下几种可能: 1.没有加@Service注解,或者是这个bean没有放在标注了@Configuration这个注解的类下. 2.SpringBoot启动类没有开启扫描 @ComponentSc ...

  9. Java中的深克隆和浅克隆

    为什么要克隆 首先思考一个问题, 为什么需要克隆对象? 直接new一个对象不行吗? 克隆的对象可能包含一些已经修改过的属性, 而new出来的对象的属性都还是初始化时候的值, 所以当需要一个新的对象来保 ...

  10. Https协议报错:com.sun.net.ssl.internal.www.protocol.https.HttpsURLConnectionOldImpl解决方法

    旭日Follow_24 的CSDN 博客 ,全文地址请点击: https://blog.csdn.net/xuri24/article/details/82220333 所用应用服务器:JBoss服务 ...