> ## Content Index
> Fetch the complete content index at: https://blog.febucci.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Unity Fire Shader Tutorial: Procedural Flames
- URL: https://blog.febucci.com/2019/05/fire-shader/
- Published: 2019-05-01T13:00:00.000Z
- Updated: 2026-04-06T07:25:40.000Z
- Description: Create a procedural fire shader in Unity using scrolling noise, color gradients, and shape masking. Full HLSL code and Amplify Shader graph included.
- Author: Federico Bellucci
- Tags: Tutorials, Unity

Build a procedural fire shader in Unity using just two textures: a scrolling noise and a gradient for the flame shape. The whole effect is a handful of math operations per pixel, making it super cheap to run. Full HLSL code below, plus an Amplify Shader graph version if you prefer nodes.

## How do I create a fire shader in Unity?

Here's how to create a Fire Shader. The effect works by scrolling a noise texture over time and using it to mask a gradient texture, giving the illusion of flickering flames. As always, you can also find below the HLSL Shader and, if you're supporting me on Patreon, the download link for the Unity Package. If you're new to writing shaders, start with my [intro to HLSL shaders in Unity](https://blog.febucci.com/2019/11/how-to-write-shaders-in-unity/) first.

0:00 

/0:01 

1× 

## How it works

The shader samples 2 textures: a noise texture (scrolled upward by subtracting `_Time.x` from the UV's Y) and a gradient texture (static). Three `step()` calls compare the noise value against the gradient value at offsets of 0, -0.2, and -0.4\. Those 3 thresholds define 3 "layers" of fire (L1, L2, L3 in the shader). The outer layer controls alpha, and the 2 inner layers control the color blend between the brighter and darker fire colors. No [vertex distortion](https://blog.febucci.com/2018/10/vertex-shader/) is used, which keeps the shader very cheap - just 2 texture samples and a handful of math ops per pixel. The step-based masking technique here is similar to what happens in a [dissolve shader](https://blog.febucci.com/2018/09/dissolve-shader/), just applied differently.

## HLSL

The shader is transparent, so the SubShader uses `Blend SrcAlpha OneMinusSrcAlpha`. It requires 2 textures as inputs: a tileable noise and a gradient that shapes the fire outline. The scroll speed is controlled by `_Time.x` (which is `_Time.y / 20`), so you can speed it up by multiplying it.

1. Sample the noise texture with scrolling UVs: `IN.uv - float2(0, _Time.x)`.
2. Sample the gradient texture with the original UVs.
3. Run 3 step calls at offsets 0, -0.2, and -0.4 to get 3 fire layer masks.
4. Set alpha to `step1` (the outermost layer).
5. Lerp between `_BrighterCol` and `_DarkerCol` using `step1 - step2`, then blend in `_MiddleCol` using `step2 - step3`.

```hlsl
//@febucci, https://www.febucci.com/tutorials/
//Support my work here: https://www.patreon.com/febucci

Shader "Fire"
{
	Properties
	{
		_NoiseTex("Noise Texture", 2D) = "white" {}
		_GradientTex("Gradient Texture", 2D) = "white" {}

		_BrighterCol("Brighter Color", Color) = (1,1,1,1)
		_MiddleCol("Middle Color", Color) = (.7,.7,.7,1)
		_DarkerCol("Darker Color", Color) = (.4,.4,.4,1)
	}

	SubShader
	{
		//The shader is transparent
		Tags
		{
			"RenderType" = "Transparent"
		}

		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			#include "UnityShaderVariables.cginc" //to use _Time

			sampler2D _NoiseTex;
			sampler2D _GradientTex;

			float4 _BrighterCol;
			float4 _MiddleCol;
			float4 _DarkerCol;

			//Input for the vertex
			struct appdata {
				float4 vertex : POSITION;
				float4 texcoord : TEXCOORD0;
			};

			//Output for the fragment
			struct v2f {
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			v2f vert(appdata v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord.xy;

				return o;
			}

			float4 frag(v2f IN) : SV_Target {

				float noiseValue = tex2D(_NoiseTex, IN.uv - float2(0, _Time.x)).x; //fire with scrolling
				float gradientValue = tex2D(_GradientTex, IN.uv).x;

				float step1 = step(noiseValue, gradientValue);
				float step2 = step(noiseValue, gradientValue-0.2);
				float step3 = step(noiseValue, gradientValue-0.4);

				//The entire fire color
				float4 c = float4
					(
						//Calculates where to place the darker color instead of the brighter one
						lerp
						(
							_BrighterCol.rgb,
							_DarkerCol.rgb,
							step1 - step2 //Corresponds to "L1" in my GIF
						),

					step1 //This is the alpha of our fire, which is the "outer" color, i.e. the step1
					);

				c.rgb = lerp //Calculates where to place the middle color
					(
						c.rgb,
						_MiddleCol.rgb,
						step2 - step3 //Corresponds to "L2" in my GIF
					);

				return c;
			}
			ENDCG
		}

	}
}

```

---

## Amplify Shader

![](https://storage.ghost.io/c/38/36/383676a1-e894-4116-9a98-bb5a9336da39/content/images/2024/09/febucci_fire_shader_graph_ase.jpg)

## Frequently asked questions

### What textures do I need?

You need 2: a tileable noise texture (any grayscale noise works) and a gradient texture that shapes the fire's silhouette, typically brighter at the base and darker at the top.

### How do I change the scroll speed?

Multiply `_Time.x` by a value greater than 1 to speed it up, or less than 1 to slow it down. You can expose it as a shader property if you want to control it at runtime.

### Can I add a fourth color layer?

Yes, add another step call at an additional offset (e.g., -0.6) and blend in a fourth color the same way step3 handles the middle color.

### Does this work in the Universal Render Pipeline?

The HLSL version uses Unity's built-in CG includes, so it only works in the Built-in Render Pipeline. For URP you'll need to rewrite it as an HLSL shader or recreate it in Shader Graph.