2D flame effects

Unity patch realizes flame effect

1. Effect Description

Hello everyone, I am Zhao. This is a flame effect, but it is not made of particles, it is made of a patch, which can be understood as a 2D special effect. This example is very simple, but you can expand your thinking. It turns out that in addition to using sequence frames and particles for animation, you can also use Shader to achieve it.
insert image description here
insert image description here

Second, the principle of step-by-step production

1. Color part

Here we mainly use a noise map as a simulation of the flame

By controlling the UV coordinates, the noise map has a scrolling effect from bottom to top
insert image description here

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

Next, use a gradient map to achieve the effect of the flame's up and down transition:
insert image description here
insert image description here

It can be seen that through the noise map and the gradient map, there is already a little flame on the patch. But now the flame is black and white, we have to multiply it by a color.
insert image description here
insert image description here

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;

Note that there is a finalG variable in the code, which is used for the G channel of the final output color, and then the RB channel directly uses a specified color _Color. In fact, the entire _Color can also be multiplied with the gradient color and noise map color, and the effect will be like this
half3 finalRGB = _Color.rgb* genVal*noiseVal;
insert image description here

I feel that the calculation effect is not as good as using the G channel alone.

2. Transparency

Here, a black and white mask image is used to crop the color result obtained above, so that it is displayed only within the mask range:
insert image description here
insert image description here

The current shape is too neat, and there should be a certain jitter effect when the flame burns, so when calculating this mask, the noise map and gradient map are also added to make the edge of the flame jitter irregularly:
insert image description here

3. Complete 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
        }
    }
}

Guess you like

Origin blog.csdn.net/liweizhao/article/details/130497427