我们不使用Fog,通过Sprite 使用定制的shader 来实现上面的效果。
这个Shader主要做的事情:
在Sprite的底部叠加天空的颜色,看起来像渐渐消失。叠加的颜色强度依赖于距离相机的距离,离相机越远,则越强。
Shader如下:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/2DFogSpriteShader"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_SkyColor ("Sky Color", Color) = (1,1,1,1)
_MaxCamDist("Max Camera distance", float) = 100
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}
SubShader
{
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile DUMMY PIXELSNAP_ON
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
float4 worldPos : TEXCOORD1;
};
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color;
OUT.worldPos = mul(unity_ObjectToWorld, IN.vertex);
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif
return OUT;
}
sampler2D _MainTex;
fixed4 _SkyColor;
float _MaxCamDist;
fixed4 frag(v2f IN) : COLOR
{
float dist = distance(IN.worldPos, _WorldSpaceCameraPos);
half4 texcol = tex2D (_MainTex, IN.texcoord) * IN.color;
float distFactor = saturate(dist/_MaxCamDist);
half4 intercol = lerp(texcol, _SkyColor, distFactor);
float gradientFactor = distFactor / 3;
half4 finalCol = lerp(_SkyColor, intercol, (IN.texcoord.y - gradientFactor)/ (1 - gradientFactor)) * step(gradientFactor, IN.texcoord.y);
if (IN.texcoord.y < gradientFactor) finalCol = _SkyColor;
finalCol.a = texcol.a;
return finalCol;
}
ENDCG
}
}
Fallback "Sprites/Default"
}
场景中创建若干个Sprite,并将上面的shader创建Material 赋给这些Sprite.
创建 SkyColorManager.cs ,把脚本挂在Camera上。将Camera设置为Solid Color ,通过脚本来设置Camera 背景颜色。
- 通过Gradient 设置颜色渐变,
- 通过 fogMat.SetColor("_SkyColor", Camera.main.backgroundColor); 将背景颜色传给上面的Shader.
- 通过gradient.Evaluate(Mathf.PingPong(timeCounter, 1)); 使背景颜色动态变化。
public class SkyColorManager : MonoBehaviour {
private Color skyColor;
private Material fogMat;
public Gradient gradient;
public GameObject boxSprite;
private float timeCounter = 0;
void Start()
{
fogMat = boxSprite.GetComponent<Renderer>().sharedMaterial;
}
void Update ()
{
// timeCounter += Time.deltaTime*0.1f;
timeCounter += Time.deltaTime*0.5f;
Camera.main.backgroundColor = gradient.Evaluate(Mathf.PingPong(timeCounter, 1));
fogMat.SetColor("_SkyColor", Camera.main.backgroundColor);
}
}
最后给这些Sprite添加一些上下移动效果,创建SpriteAnim.cs , 并讲他挂到创建的Sprite 上。
public class SpriteAnim : MonoBehaviour
{
private float maxPosY;
private Vector3 mInitPos;
private float mTimeCounter = 0;
// Use this for initialization
void Start ()
{
mInitPos = this.transform.position;
maxPosY = Random.Range(1, 2.0f);
}
// Update is called once per frame
void Update ()
{
// mTimeCounter += Time.deltaTime * 0.5f;
mTimeCounter += Time.deltaTime * 1.0f;
this.transform.position = mInitPos + Vector3.up * (Mathf.PingPong(mTimeCounter,maxPosY)-maxPosY/2.0f);
}
}
最终效果如下。
Unity完整工程源码:请搜索微信公众号UnityAsk,或者 加QQ群:891920228 获取