概述
冰火围城里的过场动画,犹如一团火焰,把地图烧毁,气势磅礴。效果如下图:
原理
首先我们需要给当前游戏画面截个屏,作为背景图。通过gradientmain(以下简称gmain)这张图控制燃烧进程。白色部分就是未燃烧到的截屏图,黑色部分是已经烧掉的部分,中间的渐变就是正在燃烧的部分。
仔细的同学已经注意到了,gradientfire(以下简称gfire)这张图和gmain有点相似。gfire的颜色部分,正好对应的是gmain的渐变部分,它们用同一套uv采样,所以火焰的颜色,是由gfire这张图控制的。火焰的形状则由firemap这张图控制。
那么怎么控制火焰从右下角烧到左上角呢?我们需要一个平面网格,然后刷顶点渐变色。左下角Color(0.5)->右上角Color(1),渐变过渡,如下图:
实现
接下去来看看具体的代码实现。
mScreenshot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
mScreenshot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
mScreenshot.Apply();
mat.SetTexture("_ScreenCapture", mScreenshot);
这是C#代码,给屏幕截图,并且把图片传入shader。
struct appdata_transition
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
fixed4 color : COLOR;
};
顶点结构定义里加入顶点色。
v2f vert(appdata_transition v)
{
v2f o = (v2f)0;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy * _FireMap_ST.xy + _FireMap_ST.zw;
o.uv += frac(_Time.y * float2(_FireMapSpeedX, _FireMapSpeedY));
o.screenUV = (o.pos.xy / o.pos.w) * 0.5 + 0.5;
o.color = v.color;
return o;
}
vertex shader里,计算firemap的uv坐标,并加入uv动画。计算屏幕坐标,作为截屏图片的uv坐标。把顶点色赋值给v2f结构。
fixed4 frag(v2f i) : Color
{
fixed4 c = tex2D(_ScreenCapture, i.screenUV);
fixed firemap = tex2D(_FireMap, i.uv).r + i.color.r + _DissolveAmount;
fixed mainDissolve = tex2D(_GradientMainDissolve, fixed2(firemap, 0)).r;
fixed4 fireDissolve = tex2D(_GradientFireDissolve, fixed2(firemap, 0));
c *= mainDissolve;
c.rgb += fireDissolve.rgb;
return c;
}
fragment shader里,首先用屏幕坐标采样截屏图片。
fixed firemap = tex2D(_FireMap, i.uv).r + i.color.r + _DissolveAmount;
_DissolveAmount这个变量是由应用程序传入的,范围在[-1, 0]之间的值。这个值会逐渐递减,使得firemap这个值也随之逐渐递减。得到的值用来作为uv坐标,采样gmian和gfire。右下角的顶点,因为颜色值较小,会最先燃烧。
c *= mainDissolve;
gmain的信息控制动画进程,黑色的直接不显示。
c.rgb += fireDissolve.rgb;
叠加上gfire图,得到火焰的效果。
代码和资源
图片和完整源代码,有需要可以自行去下载