应用噪声函数制作火焰特效

1.白噪声

gridCount = 5,生成的白噪声纹理是 5行5列的：类似 frac(5x)的结果。

float WhiteNoise(int seed, int i, int j)
{
//return (51237 * sin((i * 15367 + j * 66374 + seed * 36275) % 425767) + (seed * 12352 + 24556)) % 1.0f;
//float r = sin((float(i) * 157.024f + sin(float(j) * 66.525f) * 214.0f + 214.126f * float(seed)) * 21.25f);
float r = frac(sin(dot(float2(i, cos(j)), float2(float(seed) + 12.9898, float(seed) + 78.233))) * 43758.5453);
return r;
}


2.柏林噪声

float HashGrid(int seed, int i, int j)
{
//	白噪声的结果
float r = WhiteNoise(seed, i, j);
r = r * 2.0f - 1.0f;
return r;
}
float2 ComputeGradient(int seed, int gridX, int gridY)
{
float2 gradient = float2(HashGrid(seed * 123 + 345, gridX, gridY), HashGrid(seed * 456 + 234, gridX, gridY));
}

//柏林噪声
float PerlinNoise(int seed, float2 p, float gridSize)
{
p /= gridSize;
int gridX = floor(p.x);// / gridSize);
int gridY = floor(p.y);// / gridSize);

float2 v00 = float2(gridX, gridY);// * gridSize;
float2 v01 = float2(gridX, gridY + 1);// * gridSize;
float2 v10 = float2(gridX + 1, gridY);// * gridSize;
float2 v11 = float2(gridX + 1, gridY + 1);// * gridSize;

float dp00 = dot((p - v00), gradient00);
float dp01 = dot((p - v01), gradient01);
float dp10 = dot((p - v10), gradient10);
float dp11 = dot((p - v11), gradient11);

// bilinear interpolation
float tx = (p.x - v00.x);// / gridSize;
float ty = (p.y - v00.y);// / gridSize;
float res = SmoothLerp(SmoothLerp(dp00, dp10, tx), SmoothLerp(dp01, dp11, tx), ty);
// float res = lerp(lerp(dp00, dp10, tx), lerp(dp01, dp11, tx), ty);

return res;
}


3.分形布朗运动

4.柏林噪声+分型布朗运动

5.应用噪声，做一个动态的火焰：

Shader "Unlit/nosie"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
{
Tags { "RenderType"="Opaque" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog

#include "UnityCG.cginc"

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

struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};

float WhiteNoise(int seed, int i, int j)
{
//return (51237 * sin((i * 15367 + j * 66374 + seed * 36275) % 425767) + (seed * 12352 + 24556)) % 1.0f;
//float r = sin((float(i) * 157.024f + sin(float(j) * 66.525f) * 214.0f + 214.126f * float(seed)) * 21.25f);
float r = frac(sin(dot(float2(i, cos(j)), float2(float(seed) + 12.9898, float(seed) + 78.233))) * 43758.5453);
return r;
}
// smooth interpolation for perlin noise
float SmoothLerp(float min, float max, float t)
{
t = t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
return min + t * (max - min);
}

float HashGrid(int seed, int i, int j)
{
float r = WhiteNoise(seed, i, j);
r = r * 2.0f - 1.0f;
return r;
}

float2 ComputeGradient(int seed, int gridX, int gridY)
{
float2 gradient = float2(HashGrid(seed * 123 + 345, gridX, gridY), HashGrid(seed * 456 + 234, gridX, gridY));
}

float PerlinNoiseTiling(int seed, float2 p, float gridSize, int tilingSize)
{
// tilingSize = 8;
p /= gridSize;
int gridX = floor(p.x);// / gridSize);
int gridY = floor(p.y);// / gridSize);
int gridXP1 = (gridX + 1);
int gridYP1 = (gridY + 1);

float2 v00 = float2(gridX, gridY);// * gridSize;
float2 v01 = float2(gridX, gridYP1);// * gridSize;
float2 v10 = float2(gridXP1, gridY);// * gridSize;
float2 v11 = float2(gridXP1, gridYP1);// * gridSize;

float dp00 = dot((p - v00), gradient00);
float dp01 = dot((p - v01), gradient01);
float dp10 = dot((p - v10), gradient10);
float dp11 = dot((p - v11), gradient11);

// bilinear interpolation
float tx = (p.x - v00.x);// / gridSize;
float ty = (p.y - v00.y);// / gridSize;
float res = SmoothLerp(SmoothLerp(dp00, dp10, tx), SmoothLerp(dp01, dp11, tx), ty);
// float res = lerp(lerp(dp00, dp10, tx), lerp(dp01, dp11, tx), ty);

return res;
}
// perlin noise with Fractal Brownian Motion (add some self-similarity?)
float PerlinNoiseTilingFBM6(int seed, float2 p, float gridSize)
{
// const float aspect = 2.0f;
// p.x *= aspect;
// fBM : https://www.iquilezles.org/www/articles/fbm/fbm.htm
//Vector4 deltaVec = new Vector4(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f), 0.0f, 0.0f); ;// new Vector4(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f), 0.0f, 0.0f);
float2x2 mat = { //some rotation matrix
0.8f, 0.6f,
-0.6f, 0.8f
};

float f = 0.0f;
int numFbmSteps = 6;
float multiplier[6] = { 2.02f, 2.03f, 2.01f, 2.04f, 2.01f, 2.02f };
// float multiplier[6] = { 1.02f, 2.03f, 3.01f, 2.04f, 3.01f, 3.02f };
float amp = 1.0f;
for (int i = 0; i < numFbmSteps; ++i)
{
f += amp * PerlinNoiseTiling(seed, p, gridSize, 10);
p = mul(mat, p) * multiplier[i];//(2.0f + Random.Range(0.0f, 0.05f));//brownian motion applied to sample coord
// p *= multiplier[i];
amp *= 0.5f;
}
return f / 0.96875f;
}
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}

fixed4 frag (v2f i) : SV_Target
{
// 生成遮罩
// float mask = 1.0f - i.uv.y;
// mask -= abs(2 * (i.uv.x -0.5f));

float fireheight = 0.5f;
mask -= 3 * pow((abs(2 * (i.uv.x-0.5))),2);

float noise = PerlinNoiseTilingFBM6(96,(i.uv + float2(0,-_Time.y)),0.12f);
mask += saturate(i.uv.y + 0.3f) * noise;

float3 res = saturate(albedo) * saturate(mask * 5);
return fixed4(res,1);
}
ENDCG
}
}
}



01-03 127

08-27 2140
01-30 175
03-15 621
03-15
12-02 1728
01-09 74
06-06
03-30