Unity Shader 效果(1) :图片流光效果
很多游戏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
}
}
}
需要注意的点:
- 时间间隔问题
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,才能实现时间间隔控制
- 色彩融合
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) :图片流光效果的更多相关文章
- Unity shader学习之屏幕后期处理效果之高斯模糊
高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...
- Flash 用FLASH遮罩效果做图片切换效果
本教程是关于FLASH应用遮罩效果制作好看的图片切换效果.该教程选用FLASH遮罩中最简单的一种作为例子,当然你可以用自己的想象力来做出更多更好的图片动画.希望本教程能带你带来帮助. 让我们先看看效果 ...
- Unity shader学习之屏幕后期效果之调整屏幕亮度,饱和度,对比度
Unity的屏幕后期处理效果,使用MonoBehaviour.OnRenderImage来实现. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7228063 ...
- Unity shader学习之屏幕后期处理效果之运动模糊
运动模糊,代码如下: using UnityEngine; public class MotionBlurRenderer : PostEffectRenderer { [Range(0.1f, 0. ...
- Unity shader学习之屏幕后期处理效果之Bloom效果
Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...
- Unity shader学习之屏幕后期处理效果之均值模糊
均值模糊,也使用卷积来实现,之不过卷积中每个值均相等,且相加等于1. 代码如下, 子类: using UnityEngine; public class MeanBlurRenderer : Post ...
- Unity shader学习之屏幕后期处理效果之边缘检测
边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7232707.html 例如: 代码如下: usin ...
- Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法2
这里使用一种更高效地从深度纹理中重建世界坐标的方法. 首先计算摄像机的视锥体的四条射线向量进行线性插值,插值后的值便是该像素在世界空间坐标下到摄像机的方向. 然后通过与深度值相乘即可得到摄像机位置到该 ...
- Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础
来源作者:candycat http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达 ...
随机推荐
- python - unittest 单元测试学习
单元测试 单元测试是用来对一个模块.一个函数或者一个类进行正确性检验的测试工作 比如对Python中的abs 的测试 输入正数: 比如 1, 2, 3, 返回值不变 输入负数: 比如 -1, -2, ...
- 45.work_struct和delayed_work的工作队列使用
介绍 在中断处理中,经常用到工作队列,这样便能缩短中断处理时的时间 中断中通过调用schedule_work(work)来通知内核线程,然后中断结束后,再去继续执行work对应的func函数 示例 当 ...
- HDU1255(KB7-O)
覆盖的面积 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- 微信wx.request
官方 wx.request 代码,Post 没成功过,使用Get 方式成功了. wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' ...
- C#DataTable添加列、C#指定位置添加列
DataSet ds = SQlHelper.GetDataTable(Con, sb.ToString()); ds.Tables[].Columns.Add("Check", ...
- js 返回小数点后几位
function fmoney(s, n) //s:传入的float数字 ,n:希望返回小数点几位 { n = n > 0 && n <= 20 ? n : 2; s = ...
- swipper的一个小坑
今天闲着没事用swipper写轮播图时,发现swipper的控制不起作用,当时就很难受, 后来经过自己的仔细排查发现,用了swipper4的语法,结果引入的CSS和JS都是Swipper3版本的. 特 ...
- [新特性]PeopleTools8.54+:PeopleSoft Application Engine新特性
PeopleTools 8.54 的Application Engine 已经被更新,特别是在AE跟踪设置中有了更多的选项,本文将帮助您了解8.54的新AE特性以及如何使用这些特性. AE trace ...
- Bitmap压缩图片
代码实现: public class MainActivity extends AppCompatActivity { private ImageView img; @Override prot ...
- Java synchronized解析
多线程三大特性: 可见性.原子性.有序性 synchronize的特性: 1.同一时刻只有一个线程访问临界资源 2.其它未获取到锁执行权的线程必须排队等待 3.保证共享资源的原子性.可见性和有序性 4 ...
