您现在的位置是:首页 >学无止境 >2D火焰特效网站首页学无止境

2D火焰特效

阿赵3D 2023-07-17 12:00:02
简介2D火焰特效

Unity面片实现火焰效果

一、效果说明

大家好,我是阿赵。这是一个火焰的效,不过它不是粒子做的,是用一个面片做的,可以理解成是2D的特效。这个例子很简单,但可以拓展一下思路,原来除了用序列帧和粒子做动画,还可以用Shader来实现。
在这里插入图片描述
在这里插入图片描述

二、分步制作原理

1、颜色部分

这里主要是使用了一张噪声图作为火焰的模拟

通过控制UV坐标,让噪声图有一个从下到上滚动的效果
在这里插入图片描述

float2 noiseUV = i.uv*_NoiseTex_ST.xy + _NoiseTex_ST.zw +_Time.y*_Speed;
half4 noiseCol = tex2D(_NoiseTex, noiseUV);

接下来用一张渐变图实现火焰上下过渡的效果:
在这里插入图片描述
在这里插入图片描述

可以看到,通过噪声图和渐变图,面片上已经有一点火焰的感觉了。但现在的火焰是黑白的,我们还要乘以一个颜色。
在这里插入图片描述
在这里插入图片描述

float2 noiseUV = i.uv*_NoiseTex_ST.xy + _NoiseTex_ST.zw +_Time.y*_Speed;
half4 noiseCol = tex2D(_NoiseTex, noiseUV);
half noiseVal = noiseCol.r;

half4 genCol = tex2D(_GenTex, i.uv);
float genVal = genCol.r;

float finalG = (1 - genVal)*_EndVal*noiseVal*_ColChange + _Color.g;
finalG = clamp(finalG, 0, 1);

half3 finalRGB = half3(_Color.r, finalG, _Color.b);
finalRGB = finalRGB * _Bright;

注意到代码里面有一个finalG的变量,用于最终输出颜色的G通道,然后RB通道都是直接使用了一个指定的颜色_Color。其实这里也可以整个_Color和渐变色、噪声图颜色一起做乘法的,效果会是这样
half3 finalRGB = _Color.rgb* genVal*noiseVal;
在这里插入图片描述

感觉没有单独用G通道去计算的效果好。

2、透明度部分

这里使用一张黑白的遮罩图,对上面得到的颜色结果进行裁剪,得到只有在遮罩范围内才显示:
在这里插入图片描述
在这里插入图片描述

现在的形状过于整齐,火焰燃烧时应该是有一定的抖动效果,所以在计算这个遮罩的时候,把噪声图和渐变图也加入进去,让火焰的边缘产生不规则的抖动:
在这里插入图片描述

三、完整Shader

Shader "azhao/panelFire"
{
    Properties
    {
		_NoiseTex("NoiseTex", 2D) = "white" {} 
		_Speed("Speed", Vector) = (0,0,0,0)
		_Color("_Color", Color) = (1,0.7981879,0,0)
		_GenTex("GenTex", 2D) = "white" {}
		_EndVal("EndVal", Float) = 1
		_ColChange("ColChange", Float) = 0
		_Bright("Bright", Float) = 1
		_MaskOffset("MaskOffset", Float) = 1
		_MaskTex("MaskTex", 2D) = "white" {}
		_NoiseLen("NoiseLen", Float) = 0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" }
        LOD 100
		ZWrite off
		Cull off
		Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
			
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            { 
                float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
            };
			sampler2D _NoiseTex;
			float4 _NoiseTex_ST;
			float2 _Speed;
			float4 _Color;
			sampler2D _GenTex;
			float _EndVal;
			float _ColChange;
			float _Bright;
			float _MaskOffset;
			sampler2D _MaskTex;
			float _NoiseLen;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                // sample the texture
				float2 noiseUV = i.uv*_NoiseTex_ST.xy + _NoiseTex_ST.zw +_Time.y*_Speed;
                half4 noiseCol = tex2D(_NoiseTex, noiseUV);
				half noiseVal = noiseCol.r;

				half4 genCol = tex2D(_GenTex, i.uv);
				float genVal = genCol.r;

				float finalG = (1 - genVal)*_EndVal*noiseVal*_ColChange + _Color.g;
				finalG = clamp(finalG, 0, 1);

				half3 finalRGB = half3(_Color.r, finalG, _Color.b);
				finalRGB = finalRGB * _Bright;
				float2 maskUV = i.uv;
				maskUV.x = (noiseVal * 2 - 1)*noiseVal*0.1*_MaskOffset + i.uv.x;
				half4 maskCol = tex2D(_MaskTex, maskUV);
				half alpha = smoothstep(noiseVal - _NoiseLen, noiseVal, genVal)*genVal*maskCol.r;
                return half4(finalRGB,alpha);
            }
            ENDCG
        }
    }
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。