Unity Shader Graph 源码学习

Noise | Random

RandomRangeNode

1
2
3
4
5
6
7
8
9
10
float Random(float seed)
{
return frac(sin(dot(Seed, float2(12.9898, 78.233)))*43758.5453);
}

float RandomRange(float seed, float min, float max)
{
float randomno = frac(sin(dot(Seed, float2(12.9898, 78.233)))*43758.5453);
return lerp(Min, Max, randomno);
}

Unity_SimpleNoise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
inline float Unity_SimpleNoise_RandomValue_float (float2 uv)
{
float angle = dot(uv, float2(12.9898, 78.233));
#if defined(SHADER_API_MOBILE) && (defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) || defined(SHADER_API_VULKAN))
// 'sin()' has bad precision on Mali GPUs for inputs > 10000
angle = fmod(angle, TWO_PI); // Avoid large inputs to sin()
#endif
return frac(sin(angle)*43758.5453);
}

inline float Unity_SimpleNnoise_Interpolate_float (float a, float b, float t)
{
return (1.0-t)*a + (t*b);
}

inline float Unity_SimpleNoise_ValueNoise_float (float2 uv)
{
float2 i = floor(uv);
float2 f = frac(uv);
f = f * f * (3.0 - 2.0 * f);

uv = abs(frac(uv) - 0.5);
float2 c0 = i + float2(0.0, 0.0);
float2 c1 = i + float2(1.0, 0.0);
float2 c2 = i + float2(0.0, 1.0);
float2 c3 = i + float2(1.0, 1.0);
float r0 = Unity_SimpleNoise_RandomValue_float(c0);
float r1 = Unity_SimpleNoise_RandomValue_float(c1);
float r2 = Unity_SimpleNoise_RandomValue_float(c2);
float r3 = Unity_SimpleNoise_RandomValue_float(c3);

float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
return t;
}

float Unity_SimpleNoise(float2 UV, float Scale)
{
float t = 0.0;

float freq = pow(2.0, float(0));
float amp = pow(0.5, float(3-0));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;

freq = pow(2.0, float(1));
amp = pow(0.5, float(3-1));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;

freq = pow(2.0, float(2));
amp = pow(0.5, float(3-2));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;

return t;
}

GradientNoiseNode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
float2 Unity_GradientNoise_Dir_float(float2 p)
{
// Permutation and hashing used in webgl-nosie goo.gl/pX7HtC
p = p % 289;
// need full precision, otherwise half overflows when p > 1
float x = float(34 * p.x + 1) * p.x % 289 + p.y;
x = (34 * x + 1) * x % 289;
x = frac(x / 41) * 2 - 1;
return normalize(float2(x - floor(x + 0.5), abs(x) - 0.5));
}

float Unity_GradientNoise(float2 UV, float Scale)
{
float2 p = UV * Scale;
float2 ip = floor(p);
float2 fp = frac(p);
float d00 = dot(Unity_GradientNoise_Dir_float(ip), fp);
float d01 = dot(Unity_GradientNoise_Dir_float(ip + float2(0, 1)), fp - float2(0, 1));
float d10 = dot(Unity_GradientNoise_Dir_float(ip + float2(1, 0)), fp - float2(1, 0));
float d11 = dot(Unity_GradientNoise_Dir_float(ip + float2(1, 1)), fp - float2(1, 1));
fp = fp * fp * fp * (fp * (fp * 6 - 15) + 10);
Out = lerp(lerp(d00, d01, fp.y), lerp(d10, d11, fp.y), fp.x) + 0.5;
}

VoronoiNode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
inline float2 Unity_Voronoi_RandomVector_float (float2 UV, float offset)
{
float2x2 m = float2x2(15.27, 47.63, 99.41, 89.98);
UV = frac(sin(mul(UV, m)));
return float2(sin(UV.y*+offset)*0.5+0.5, cos(UV.x*offset)*0.5+0.5);
}

float Unity_Voronoi(float2 UV, float AngleOffset, float CellDensity)
{
float2 g = floor(UV * CellDensity);
float2 f = frac(UV * CellDensity);
float t = 8.0;
float3 res = float3(8.0, 0.0, 0.0);

for(int y=-1; y<=1; y++)
{
for(int x=-1; x<=1; x++)
{
float2 lattice = float2(x,y);
float2 offset = Unity_Voronoi_RandomVector_float(lattice + g, AngleOffset);
float d = distance(lattice + offset, f);

if(d < res.x)
{
res = float3(d, offset.x, offset.y);
Out = res.x;
Cells = res.y;
}
}
}
}

NoiseSineWaveNode

1
2
3
4
5
6
7
8
float NoiseSineWave(float In, float2 MinMax)
{
float sinIn = sin(In);
float sinInOffset = sin(In + 1.0);
float randomno = frac(sin((sinIn - sinInOffset) * (12.9898 + 78.233))*43758.5453);
float noise = lerp(MinMax.x, MinMax.y, randomno);
return sinIn + noise;
}

DitherNode

1
2
3
4
5
6
7
8
9
10
11
12
13
float Unity_Dither(float In, float2 ScreenPosition)
{
float2 uv = ScreenPosition.xy * _ScreenParams.xy;
float DITHER_THRESHOLDS[16] =
{
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
};
uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
return In - DITHER_THRESHOLDS[index];
}

Math

Remap

1
2
3
4
float Remap(float In, float2 InMinMax, float2 OutMinMax)
{
Out = OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x);
}

NormalFromHeight

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
float3 Unity_NormalFromHeight(float In, float Strength, float3 Position, float3x3 TangentMatrix)
{
float3 worldDerivativeX = ddx(Position);
float3 worldDerivativeY = ddy(Position);

float3 crossX = cross(TangentMatrix[2].xyz, worldDerivativeX);
float3 crossY = cross(worldDerivativeY, TangentMatrix[2].xyz);
float d = dot(worldDerivativeX, crossY);
float sgn = d < 0.0 ? (-1.0f) : 1.0f;
float surface = sgn / max(0.000000000000001192093f, abs(d));

float dHdx = ddx(In);
float dHdy = ddy(In);
float3 surfGrad = surface * (dHdx*crossY + dHdy*crossX);
float3 Out = SafeNormalize(TangentMatrix[2].xyz - (Strength * surfGrad));

// if (outputSpace == OutputSpace.Tangent)
// Out = TransformWorldToTangent(Out, TangentMatrix);

return Out;
}

Unity Shader Graph 源码学习
https://automask.github.io/wild/2022/06/26/lab/S_Unity_ShaderGraph/
作者
Kyle Zhou
发布于
2022年6月26日
许可协议