Unity引擎制作闪电护盾效果
大家好,我是阿赵。
这期做一个闪电护盾的效果。
一、效果说明
可以改变闪电的颜色
可以改变范围
改变贴图的平铺次数,也可以做出各种不同感觉的护盾。
二、原理
这个效果看着很复杂,其实只是用了一张Noise贴图
把贴图贴在一个球上,得到这样的效果
常规操作,先乘再power,得到一个可以控制亮度和范围的效果。
这里我想这个效果是流动起来的。所以可以选择用UV动画来做。我这里做一个稍微复杂一点的UV动画,叫做Flow效果:
float3 Flow(sampler2D tex, float2 uv, float2 dir, float2 strength, float speed)
{
float2 dirx = dir + 0.5f;
float timeSpeed = _Time.y*speed;
float2 uv1 = uv + (dirx*strength*frac(timeSpeed));
float2 uv2 = uv + (dirx*strength*(frac(timeSpeed + 0.5f)));
float3 result = lerp(UnpackNormal(tex2D(tex, uv1)), UnpackNormal(tex2D(tex, uv2)), (abs((frac(timeSpeed) - 0.5)) / 0.5));
return result;
}
通过传入贴图、uv、流动方向、流动强度和速度,得到一个流动的动画效果。
对上面的效果继续做power和取反(被1减)的操作,得到这样的一个效果,我们拿到的是刚才那个噪声图的边缘。
接下来我们再做一次Flow,但这次传入的dir是不同的。然后把两次的结果相乘,得到这么一个随机变化的遮罩。
给rgb乘以一个颜色,就得到了这个护盾的基础颜色了
然后把遮罩给到alpha通道,就看到了这样的效果了。
如果想闪电有一定的闪烁效果,那么简单的用Time作为x,0作为y,组成UV采样一下给噪声图。就能得到一个闪烁的过程,这个值乘以原来的Alpah通道。
三、代码
Shader "azhao/azhaoShield1"
{
Properties
{
_Size("Size", Range(0 , 10)) = 1
_colorPow("colorPow", Float) = 1
_colorMul("colorMul", Float) = 1
_mainColor("mainColor", Color) = (1,1,1,0)
_Noise1Tex("Noise1Tex", 2D) = "white" {}
_dir1("dir1", Vector) = (0,0,0,0)
_dir2("dir2", Vector) = (1,1,0,0)
_alphaSpeed("alphaSpeed", Float) = 1
_colorAdd("colorAdd", Float) = 1
_flowSpeed("flowSpeed", Float) = 1
_flowStrength("flowStrength", Vector) = (1,1,0,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
Blend SrcAlpha OneMinusSrcAlpha, SrcAlpha OneMinusSrcAlpha
ZWrite Off
LOD 100
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;
};
uniform float4 _mainColor;
uniform sampler2D _Noise1Tex;
uniform float4 _Noise1Tex_ST;
uniform float _Size;
uniform float3 _dir1;
uniform float2 _flowStrength;
uniform float _flowSpeed;
uniform float _colorMul;
uniform float _colorPow;
uniform float3 _dir2;
uniform float _colorAdd;
uniform float _alphaSpeed;
float3 Flow(sampler2D tex, float2 uv, float2 dir, float2 strength, float speed)
{
float2 dirx = dir + 0.5f;
float timeSpeed = _Time.y*speed;
float2 uv1 = uv + (dirx*strength*frac(timeSpeed));
float2 uv2 = uv + (dirx*strength*(frac(timeSpeed + 0.5f)));
float3 result = lerp(UnpackNormal(tex2D(tex, uv1)), UnpackNormal(tex2D(tex, uv2)), (abs((frac(timeSpeed) - 0.5)) / 0.5));
return result;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _Noise1Tex)/+_Size;
return o;
}
half4 frag (v2f i) : SV_Target
{
float3 col1 = Flow(_Noise1Tex,i.uv,_dir1,_flowStrength,_flowSpeed);
float3 col2 = Flow(_Noise1Tex, i.uv, _dir2, _flowStrength, _flowSpeed);
float val1 = 1.0 - saturate( pow(col1.r*_colorMul, _colorPow));
float val2 = 1.0 - saturate(pow(col2.r*_colorMul, _colorPow));
float4 noiseCol = tex2D(_Noise1Tex, float2(frac(_Time.y*_alphaSpeed), 0));
float alpha = val1*val2*noiseCol.r*noiseCol.r;
float3 rgb = _mainColor.rgb*val1*val2*_colorAdd;
return half4(rgb,alpha);
}
ENDCG
}
}
}