2021-01-16 22:02:25 +00:00
|
|
|
//
|
|
|
|
// File: blumen_patterns.h
|
|
|
|
// Author: Peter Slattery
|
|
|
|
// Creation Date: 2021-01-15
|
|
|
|
//
|
|
|
|
#ifndef BLUMEN_PATTERNS_H
|
|
|
|
|
2021-01-31 00:24:36 +00:00
|
|
|
#define FLOWER_COLORS_COUNT 12
|
2021-01-31 03:33:44 +00:00
|
|
|
|
2021-03-20 22:15:35 +00:00
|
|
|
internal r32
|
|
|
|
Smoothstep(r32 T)
|
|
|
|
{
|
|
|
|
r32 Result = (T * T * (3 - (2 * T)));
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
internal r32
|
|
|
|
Smoothstep(r32 T, r32 A, r32 B)
|
|
|
|
{
|
|
|
|
return LerpR32(Smoothstep(T), A, B);
|
|
|
|
}
|
2021-03-23 02:09:30 +00:00
|
|
|
internal v3
|
|
|
|
Smoothstep(v3 P)
|
|
|
|
{
|
|
|
|
v3 R = {};
|
|
|
|
R.x = Smoothstep(P.x);
|
|
|
|
R.y = Smoothstep(P.y);
|
|
|
|
R.z = Smoothstep(P.z);
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v3
|
|
|
|
AbsV3(v3 P)
|
|
|
|
{
|
|
|
|
v3 Result = {};
|
|
|
|
Result.x = Abs(P.x);
|
|
|
|
Result.y = Abs(P.y);
|
|
|
|
Result.z = Abs(P.z);
|
|
|
|
return Result;
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
|
|
|
|
internal v2
|
|
|
|
FloorV2(v2 P)
|
|
|
|
{
|
|
|
|
v2 Result = {};
|
|
|
|
Result.x = FloorR32(P.x);
|
|
|
|
Result.y = FloorR32(P.y);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
internal v3
|
|
|
|
FloorV3(v3 P)
|
|
|
|
{
|
|
|
|
v3 Result = {};
|
|
|
|
Result.x = FloorR32(P.x);
|
|
|
|
Result.y = FloorR32(P.y);
|
|
|
|
Result.z = FloorR32(P.z);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v2
|
|
|
|
FractV2(v2 P)
|
|
|
|
{
|
|
|
|
v2 Result = {};
|
|
|
|
Result.x = FractR32(P.x);
|
|
|
|
Result.y = FractR32(P.y);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
internal v3
|
|
|
|
FractV3(v3 P)
|
|
|
|
{
|
|
|
|
v3 Result = {};
|
|
|
|
Result.x = FractR32(P.x);
|
|
|
|
Result.y = FractR32(P.y);
|
|
|
|
Result.z = FractR32(P.z);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v2
|
|
|
|
SinV2(v2 P)
|
|
|
|
{
|
|
|
|
v2 Result = {};
|
|
|
|
Result.x = SinR32(P.x);
|
|
|
|
Result.y = SinR32(P.y);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
internal v3
|
|
|
|
SinV3(v3 P)
|
|
|
|
{
|
|
|
|
v3 Result = {};
|
|
|
|
Result.x = SinR32(P.x);
|
|
|
|
Result.y = SinR32(P.y);
|
|
|
|
Result.y = SinR32(P.z);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Hash1(v2 P)
|
|
|
|
{
|
|
|
|
v2 Result = FractV2( P * 0.3183099f ) * 50.f;
|
|
|
|
return FractR32(P.x * P.y * (P.x + P.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Hash1(r32 N)
|
|
|
|
{
|
|
|
|
return FractR32(N * 17.0f * FractR32(N * 0.3183099f));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v2
|
|
|
|
Hash2(r32 N)
|
|
|
|
{
|
|
|
|
v2 P = V2MultiplyPairwise(SinV2(v2{N,N+1.0f}), v2{43758.5453123f,22578.1459123f});
|
|
|
|
return FractV2(P);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v2
|
|
|
|
Hash2(v2 P)
|
|
|
|
{
|
|
|
|
v2 K = v2{ 0.3183099f, 0.3678794f };
|
|
|
|
v2 Kp = v2{K.y, K.x};
|
|
|
|
v2 R = V2MultiplyPairwise(P, K) + Kp;
|
|
|
|
return FractV2( K * 16.0f * FractR32( P.x * P.y * (P.x + P.y)));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v3
|
|
|
|
Hash3(v2 P)
|
|
|
|
{
|
|
|
|
v3 Q = v3{};
|
|
|
|
Q.x = V2Dot(P, v2{127.1f, 311.7f});
|
|
|
|
Q.y = V2Dot(P, v2{267.5f, 183.3f});
|
|
|
|
Q.z = V2Dot(P, v2{419.2f, 371.9f});
|
|
|
|
return FractV3(SinV3(Q) * 43758.5453f);
|
|
|
|
}
|
|
|
|
|
2021-03-23 02:09:30 +00:00
|
|
|
internal r32
|
|
|
|
HashV3ToR32(v3 P)
|
|
|
|
{
|
|
|
|
v3 Pp = FractV3(P * 0.3183099f + v3{0.1f, 0.1f, 0.1f});
|
|
|
|
Pp *= 17.0f;
|
|
|
|
r32 Result = FractR32(Pp.x * Pp.y * Pp.z * (Pp.x + Pp.y + Pp.z));
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-03-20 22:15:35 +00:00
|
|
|
internal r32
|
|
|
|
Random(v2 N)
|
|
|
|
{
|
|
|
|
v2 V = v2{12.9898f, 4.1414f};
|
|
|
|
return FractR32(SinR32(V2Dot(N, V)) * 43758.5453);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Noise2D(v2 P)
|
|
|
|
{
|
|
|
|
v2 IP = FloorV2(P);
|
|
|
|
v2 U = FractV2(P);
|
|
|
|
U = V2MultiplyPairwise(U, U);
|
|
|
|
U = V2MultiplyPairwise(U, ((U * 2.0f) + v2{-3, -3}));
|
|
|
|
|
|
|
|
r32 A = LerpR32(U.x, Random(IP), Random(IP + v2{1.0f, 0}));
|
|
|
|
r32 B = LerpR32(U.x, Random(IP + v2{0, 1}), Random(IP + v2{1, 1}));
|
|
|
|
r32 Res = LerpR32(U.y, A, B);
|
|
|
|
|
|
|
|
return Res * Res;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
2021-03-23 02:09:30 +00:00
|
|
|
Noise3D(v3 P)
|
|
|
|
{
|
|
|
|
P = AbsV3(P);
|
|
|
|
v3 PFloor = FloorV3(P);
|
|
|
|
v3 PFract = FractV3(P);
|
|
|
|
v3 F = Smoothstep(PFract);
|
|
|
|
|
|
|
|
r32 Result = LerpR32(F.z,
|
|
|
|
LerpR32(F.y,
|
|
|
|
LerpR32(F.x,
|
|
|
|
HashV3ToR32(PFloor + v3{0, 0, 0}),
|
|
|
|
HashV3ToR32(PFloor + v3{1, 0, 0})),
|
|
|
|
LerpR32(F.x,
|
|
|
|
HashV3ToR32(PFloor + v3{0, 1, 0}),
|
|
|
|
HashV3ToR32(PFloor + v3{1, 1, 0}))),
|
|
|
|
LerpR32(F.y,
|
|
|
|
LerpR32(F.x,
|
|
|
|
HashV3ToR32(PFloor + v3{0, 0, 1}),
|
|
|
|
HashV3ToR32(PFloor + v3{1, 0, 1})),
|
|
|
|
LerpR32(F.x,
|
|
|
|
HashV3ToR32(PFloor + v3{0, 1, 1}),
|
|
|
|
HashV3ToR32(PFloor + v3{1, 1, 1}))));
|
|
|
|
|
|
|
|
Assert(Result >= 0 && Result <= 1);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Noise3D_(v3 Pp)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
|
|
|
v3 P = FloorV3(Pp);
|
|
|
|
v3 W = FractV3(Pp);
|
|
|
|
|
|
|
|
//v3 U = W * W * W * (W * (W * 6.0f - 15.0f) + 10.0f);
|
|
|
|
v3 U = V3MultiplyPairwise(W, W * 6.0f - v3{15, 15, 15});
|
|
|
|
U = U + v3{10, 10, 10};
|
|
|
|
U = V3MultiplyPairwise(U, W);
|
|
|
|
U = V3MultiplyPairwise(U, W);
|
|
|
|
U = V3MultiplyPairwise(U, W);
|
|
|
|
|
|
|
|
r32 N = P.x + 317.0f * P.y + 157.0f * P.z;
|
|
|
|
|
|
|
|
r32 A = Hash1(N + 0.0f);
|
|
|
|
r32 B = Hash1(N + 1.0f);
|
|
|
|
r32 C = Hash1(N + 317.0f);
|
|
|
|
r32 D = Hash1(N + 317.0f);
|
|
|
|
r32 E = Hash1(N + 157.0f);
|
|
|
|
r32 F = Hash1(N + 158.0f);
|
|
|
|
r32 G = Hash1(N + 474.0f);
|
|
|
|
r32 H = Hash1(N + 475.0f);
|
|
|
|
|
|
|
|
r32 K0 = A;
|
|
|
|
r32 K1 = B - A;
|
|
|
|
r32 K2 = C - A;
|
|
|
|
r32 K3 = E - A;
|
|
|
|
r32 K4 = A - B - C + D;
|
|
|
|
r32 K5 = A - C - E + G;
|
|
|
|
r32 K6 = A - B - E + F;
|
|
|
|
r32 K7 = A + B + C - D + E - F - G + H;
|
|
|
|
|
|
|
|
return -1.0f + 2.0f * (K0 +
|
|
|
|
K1 * U.x +
|
|
|
|
K2 * U.y +
|
|
|
|
K3 * U.z +
|
|
|
|
K4 * U.x * U.y +
|
|
|
|
K5 * U.y + U.z +
|
|
|
|
K6 * U.z * U.x +
|
|
|
|
K7 * U.x * U.y * U.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Fbm2D(v2 P)
|
|
|
|
{
|
|
|
|
r32 R = 0;
|
|
|
|
r32 Amp = 1.0;
|
|
|
|
r32 Freq = 1.0;
|
|
|
|
for (u32 i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
R += Amp * Noise2D(P * Freq);
|
|
|
|
Amp *= 0.5f;
|
|
|
|
Freq *= 1.0f / 0.5f;
|
|
|
|
}
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
|
|
|
global m44 M3 = m44{
|
|
|
|
0.00f, 0.80f, 0.60f, 0,
|
|
|
|
-0.80f, 0.36f, -0.48f, 0,
|
|
|
|
-0.60f, -0.48f, 0.64f, 0,
|
|
|
|
0, 0, 0, 1
|
|
|
|
};
|
|
|
|
|
|
|
|
internal r32
|
|
|
|
Fbm3D(v3 P)
|
|
|
|
{
|
|
|
|
v3 X = P;
|
|
|
|
r32 F = 2.0f;
|
|
|
|
r32 S = 0.5f;
|
|
|
|
r32 A = 0.0f;
|
|
|
|
r32 B = 0.5f;
|
|
|
|
for (u32 i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
r32 N = Noise3D(X);
|
|
|
|
A += B * N;
|
|
|
|
B *= S;
|
|
|
|
v4 Xp = M3 * ToV4Point(X);
|
|
|
|
X = Xp.xyz * F;
|
|
|
|
}
|
|
|
|
|
|
|
|
return A;
|
|
|
|
}
|
|
|
|
|
2021-03-23 02:09:30 +00:00
|
|
|
internal r32
|
|
|
|
Fbm3D(v3 P, r32 T)
|
|
|
|
{
|
|
|
|
v3 Tt = v3{T, T, T};
|
|
|
|
r32 SinT = SinR32(T);
|
|
|
|
v3 Tv = v3{SinT, SinT, SinT};
|
|
|
|
v3 Pp = P;
|
|
|
|
r32 F = 0.0;
|
|
|
|
|
|
|
|
F += 0.500000f * Noise3D(Pp + Tt); Pp = Pp * 2.02;
|
|
|
|
F += 0.031250f * Noise3D(Pp); Pp = Pp * 2.01;
|
2021-03-31 02:55:54 +00:00
|
|
|
F += 0.250000f * Noise3D(Pp - Tt); Pp = Pp * 2.03;
|
2021-03-23 02:09:30 +00:00
|
|
|
F += 0.125000f * Noise3D(Pp); Pp = Pp * 2.01;
|
2021-03-31 02:55:54 +00:00
|
|
|
F += 0.062500f * Noise3D(Pp + Tt); Pp = Pp * 2.04;
|
2021-03-23 02:09:30 +00:00
|
|
|
F += 0.015625f * Noise3D(Pp + Tv);
|
|
|
|
|
|
|
|
F = F / 0.984375f;
|
|
|
|
return F;
|
|
|
|
}
|
|
|
|
|
2021-03-20 22:15:35 +00:00
|
|
|
internal r32
|
|
|
|
Voronoise(v2 P, r32 U, r32 V)
|
|
|
|
{
|
|
|
|
r32 K = 1.0f + 63.0f + PowR32(1.0f - V, 6.0f);
|
|
|
|
|
|
|
|
v2 I = FloorV2(P);
|
|
|
|
v2 F = FractV2(P);
|
|
|
|
|
|
|
|
v2 A = v2{0, 0};
|
|
|
|
for (s32 y = -2; y <= 2; y++)
|
|
|
|
{
|
|
|
|
for (s32 x = -2; x <= 2; x++)
|
|
|
|
{
|
|
|
|
v2 G = v2{(r32)x, (r32)y};
|
|
|
|
v3 O = V3MultiplyPairwise(Hash3(I + G), v3{U, U, 1.0f});
|
|
|
|
v2 D = G - F + O.xy;
|
|
|
|
r32 W = PowR32(1.0f - Smoothstep(V2Mag(D), 0.0f, 1.414f), K);
|
|
|
|
A += v2{O.z * W, W};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return A.x / A.y;
|
|
|
|
}
|
|
|
|
|
2021-03-21 02:10:12 +00:00
|
|
|
internal pixel
|
|
|
|
V4ToRGBPixel(v4 C)
|
|
|
|
{
|
|
|
|
pixel Result = {};
|
|
|
|
Result.R = (u8)(C.x * 255);
|
|
|
|
Result.G = (u8)(C.y * 255);
|
|
|
|
Result.B = (u8)(C.z * 255);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-01-31 00:24:36 +00:00
|
|
|
internal pixel
|
|
|
|
PixelMix(r32 T, pixel A, pixel B)
|
|
|
|
{
|
|
|
|
pixel Result = {
|
|
|
|
LerpU8(T, A.R, B.R),
|
|
|
|
LerpU8(T, A.G, B.G),
|
|
|
|
LerpU8(T, A.B, B.B),
|
|
|
|
};
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal pixel
|
2021-03-21 02:10:12 +00:00
|
|
|
PixelMix(r32 T, v4 A, v4 B)
|
|
|
|
{
|
|
|
|
v4 Result = V4Lerp(T, A, B);
|
|
|
|
pixel P = V4ToRGBPixel(Result);
|
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal v4
|
|
|
|
GetColor(v4* Colors, u32 ColorsCount, r32 Percent)
|
2021-01-31 00:24:36 +00:00
|
|
|
{
|
|
|
|
Percent = Clamp01(Percent);
|
|
|
|
|
|
|
|
u32 LowerIndex = Percent * ColorsCount;
|
|
|
|
|
|
|
|
u32 HigherIndex = LowerIndex + 1;
|
|
|
|
if (HigherIndex >= ColorsCount) HigherIndex = 0;
|
|
|
|
|
|
|
|
r32 LowerPercent = (r32)LowerIndex / (r32)ColorsCount;
|
|
|
|
r32 StepPercent = 1.f / (r32)ColorsCount;
|
|
|
|
r32 PercentLower = (Percent - LowerPercent) / StepPercent;
|
|
|
|
|
2021-03-21 02:10:12 +00:00
|
|
|
v4 Result = V4Lerp(PercentLower, Colors[LowerIndex], Colors[HigherIndex]);
|
2021-01-31 00:24:36 +00:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-01-31 03:33:44 +00:00
|
|
|
v4 RGBToHSV(v4 In)
|
|
|
|
{
|
|
|
|
v4 Result = {};
|
|
|
|
|
|
|
|
r32 Min = Min(In.r, Min(In.g, In.b));
|
|
|
|
r32 Max = Max(In.r, Max(In.g, In.b));
|
|
|
|
|
|
|
|
r32 V = Max;
|
|
|
|
r32 Delta = Max - Min;
|
|
|
|
r32 S = 0;
|
|
|
|
r32 H = 0;
|
|
|
|
if( Max != 0 )
|
|
|
|
{
|
|
|
|
S = Delta / Max;
|
|
|
|
|
|
|
|
if( In.r == Max )
|
|
|
|
{
|
|
|
|
H = ( In.g - In.b ) / Delta; // between yellow & magenta
|
|
|
|
}
|
|
|
|
else if( In.g == Max )
|
|
|
|
{
|
|
|
|
H = 2 + ( In.b - In.r ) / Delta; // between cyan & yellow
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
H = 4 + ( In.r - In.g ) / Delta; // between magenta & cyan
|
|
|
|
}
|
|
|
|
H *= 60; // degrees
|
|
|
|
if( H < 0 )
|
|
|
|
H += 360;
|
|
|
|
Result = v4{H, S, V, 1};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// r = g = b = 0
|
|
|
|
// s = 0, v is undefined
|
|
|
|
S = 0;
|
|
|
|
H = -1;
|
|
|
|
Result = v4{H, S, 1, 1};
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-01-16 22:02:25 +00:00
|
|
|
v4 HSVToRGB (v4 In)
|
|
|
|
{
|
|
|
|
float Hue = In.x;
|
|
|
|
/*
|
|
|
|
while (Hue > 360.0f) { Hue -= 360.0f; }
|
|
|
|
while (Hue < 0.0f) { Hue += 360.0f; }
|
|
|
|
*/
|
|
|
|
Hue = ModR32(Hue, 360.0f);
|
|
|
|
if (Hue < 0) { Hue += 360.0f; }
|
|
|
|
if (Hue == MinR32) { Hue = 0; }
|
|
|
|
if (Hue == MaxR32) { Hue = 360; }
|
|
|
|
Assert(Hue >= 0 && Hue < 360);
|
|
|
|
|
|
|
|
float Sat = In.y;
|
|
|
|
float Value = In.z;
|
|
|
|
|
|
|
|
float hh, p, q, t, ff;
|
|
|
|
long i;
|
|
|
|
v4 Result = {};
|
|
|
|
Result.a = In.a;
|
|
|
|
|
|
|
|
if(Sat <= 0.0f) { // < is bogus, just shuts up warnings
|
|
|
|
Result.r = Value;
|
|
|
|
Result.g = Value;
|
|
|
|
Result.b = Value;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
hh = Hue;
|
|
|
|
if(hh >= 360.0f) hh = 0.0f;
|
|
|
|
hh /= 60.0f;
|
|
|
|
i = (long)hh;
|
|
|
|
ff = hh - i;
|
|
|
|
p = Value * (1.0f - Sat);
|
|
|
|
q = Value * (1.0f - (Sat * ff));
|
|
|
|
t = Value * (1.0f - (Sat * (1.0f - ff)));
|
|
|
|
|
|
|
|
switch(i) {
|
|
|
|
case 0:
|
|
|
|
{Result.r = Value;
|
|
|
|
Result.g = t;
|
|
|
|
Result.b = p;
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
Result.r = q;
|
|
|
|
Result.g = Value;
|
|
|
|
Result.b = p;
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
Result.r = p;
|
|
|
|
Result.g = Value;
|
|
|
|
Result.b = t;
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
Result.r = p;
|
|
|
|
Result.g = q;
|
|
|
|
Result.b = Value;
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
Result.r = t;
|
|
|
|
Result.g = p;
|
|
|
|
Result.b = Value;
|
|
|
|
}break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
Result.r = Value;
|
|
|
|
Result.g = p;
|
|
|
|
Result.b = q;
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
internal void
|
|
|
|
Pattern_AltBloomMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
|
|
|
{
|
|
|
|
v3 SphereCenter = Assembly.Center - v3{0, -150, 0};
|
|
|
|
r32 SphereRadius = Time;
|
|
|
|
r32 SphereBrightness = 1;
|
|
|
|
|
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
|
|
|
{
|
|
|
|
v3 P = Leds->Positions[LedIndex].xyz;
|
|
|
|
r32 Sphere = SDF_SphereNormalized(P, SphereCenter, SphereRadius);
|
|
|
|
Sphere = Clamp01(-Sphere);
|
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(WhiteV4 * Sphere);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 22:02:25 +00:00
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_HueShift(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
r32 Height = SinR32(Time) * 25;
|
|
|
|
|
|
|
|
r32 CycleLength = 5.0f;
|
|
|
|
r32 CycleProgress = FractR32(Time / CycleLength);
|
|
|
|
r32 CycleBlend = (SinR32(Time) * .5f) + .5f;
|
|
|
|
|
2021-02-06 22:09:17 +00:00
|
|
|
v4 HSV = { CycleProgress * 360, 1, 1, 1 };
|
|
|
|
v4 RGB = HSVToRGB(HSV);
|
|
|
|
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
v4 Pos = Leds->Positions[LedIndex];
|
|
|
|
r32 Dist = Pos.y - Height;
|
|
|
|
|
2021-02-06 22:09:17 +00:00
|
|
|
//v4 HSV = { (ModR32(Dist, 25) / 25) * 360, 1, 1, 1 };
|
|
|
|
//v4 RGB = HSVToRGB(HSV);
|
2021-01-16 22:02:25 +00:00
|
|
|
|
|
|
|
u8 R = (u8)(RGB.x * 255);
|
|
|
|
u8 G = (u8)(RGB.y * 255);
|
|
|
|
u8 B = (u8)(RGB.z * 255);
|
|
|
|
|
|
|
|
Leds->Colors[LedIndex].R = R;
|
|
|
|
Leds->Colors[LedIndex].G = G;
|
|
|
|
Leds->Colors[LedIndex].B = B;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2021-03-31 02:55:54 +00:00
|
|
|
Pattern_Rainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
r32 HueBase = ModR32(Time * 50, 360);
|
|
|
|
|
|
|
|
r32 CycleLength = 5.0f;
|
|
|
|
r32 CycleProgress = FractR32(Time / CycleLength);
|
|
|
|
r32 CycleBlend = (SinR32(Time) * .5f) + .5f;
|
|
|
|
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
v4 Pos = Leds->Positions[LedIndex];
|
|
|
|
r32 Hue = HueBase + Pos.y + Pos.x;
|
|
|
|
v4 HSV = { Hue, 1, 1, 1 };
|
|
|
|
v4 RGB = HSVToRGB(HSV);
|
|
|
|
|
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2021-03-31 02:55:54 +00:00
|
|
|
Pattern_RadialRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) });
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-01-16 22:02:25 +00:00
|
|
|
{
|
|
|
|
v2 Vector = v2{
|
|
|
|
Leds->Positions[LedIndex].x,
|
|
|
|
Leds->Positions[LedIndex].z
|
|
|
|
};
|
|
|
|
Vector = V2Normalize(Vector);
|
|
|
|
|
|
|
|
r32 Angle = V2Dot(RefVector, Vector);
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 HSV = { (Angle * 30) + (Time * 10), 1, 1, 1 };
|
2021-01-16 22:02:25 +00:00
|
|
|
v4 RGB = HSVToRGB(HSV);
|
|
|
|
|
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(RGB);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-31 03:33:44 +00:00
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_BasicFlowers(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-01-31 03:33:44 +00:00
|
|
|
{
|
2021-03-27 23:00:06 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
|
|
|
phrase_hue Hue = BLState->AssemblyColors[Assembly.AssemblyIndex % 3];
|
|
|
|
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
|
|
|
|
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
|
|
|
|
v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1});
|
|
|
|
|
2021-01-31 03:33:44 +00:00
|
|
|
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
|
|
|
|
{
|
|
|
|
v2_strip Strip = Assembly.Strips[StripIndex];
|
|
|
|
r32 CycleT = ModR32(Time, 10) * 20;
|
|
|
|
|
|
|
|
for (u32 i = 0; i < Strip.LedCount; i++)
|
|
|
|
{
|
|
|
|
u32 LedIndex = Strip.LedLUT[i];
|
|
|
|
v4 P = Leds->Positions[LedIndex];
|
|
|
|
|
|
|
|
r32 T = ModR32(P.y + CycleT, 200) / 200.f;
|
|
|
|
T = Clamp01(T);
|
|
|
|
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 Color = {};
|
|
|
|
if (T < 0.5f)
|
|
|
|
{
|
|
|
|
Color = V4Lerp(T * 2, C0, C1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Color = V4Lerp((T - 0.5f) * 2, C1, C2);
|
|
|
|
}
|
2021-03-21 02:10:12 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(Color);
|
2021-01-31 03:33:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
|
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_Wavy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
2021-03-23 03:58:52 +00:00
|
|
|
DEBUG_TRACK_FUNCTION;
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-27 23:00:06 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
2021-03-31 02:55:54 +00:00
|
|
|
phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
|
|
|
|
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1});
|
|
|
|
|
|
|
|
r32 Top = 120 + (SinR32(Time) * 10);
|
|
|
|
r32 Mid = 70 + (CosR32(Time * 2.13) * 20);
|
|
|
|
r32 Bot = 0;
|
|
|
|
|
|
|
|
r32 TopD = Top - Mid;
|
|
|
|
r32 BotD = Mid - Bot;
|
|
|
|
r32 MidD = Min(TopD, BotD);
|
2021-03-27 23:00:06 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
//r32 MaxFadeDistance = 10;
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
2021-03-31 02:55:54 +00:00
|
|
|
v3 P = Leds->Positions[LedIndex].xyz;
|
|
|
|
|
|
|
|
r32 PercentTop = Clamp01(1.0f - ((Top - P.y) / TopD));
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 PercentMid = Clamp01(1.0f - Abs(P.y - Mid) / MidD);
|
|
|
|
r32 N = Noise3D((P / 17) + v3{Time, -Time, 0});
|
|
|
|
N = Clamp01(N) * 2;
|
|
|
|
N = Smoothstep(N);
|
|
|
|
N *= N;
|
|
|
|
N = Smoothstep(N);
|
|
|
|
N *= 1.0f - PowR32(1.0f - PercentMid, 4);
|
|
|
|
PercentMid = Clamp01(PercentMid + N);
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 PercentBot = Clamp01(1.0f - ((P.y - Bot) / BotD));
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 TopC = (C0 * PercentTop);
|
|
|
|
v4 MidC = (C1 * PercentMid);
|
|
|
|
v4 BotC = (C2 * PercentBot);
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C = {};
|
|
|
|
if (PercentTop > PercentMid && PercentTop > PercentBot)
|
|
|
|
{
|
|
|
|
C = C0;
|
|
|
|
}
|
|
|
|
else if (PercentMid > PercentBot)
|
|
|
|
{
|
|
|
|
C = C1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
C = C2;
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 ScaleFactor = PercentTop + PercentMid + PercentBot;
|
|
|
|
C = (TopC + MidC + BotC) / ScaleFactor;
|
2021-03-21 02:10:12 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
2021-03-23 03:58:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
|
|
|
{
|
|
|
|
DEBUG_TRACK_FUNCTION;
|
|
|
|
|
2021-03-27 23:00:06 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
2021-03-31 02:55:54 +00:00
|
|
|
phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
|
|
|
|
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
|
|
|
|
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-03-23 02:09:30 +00:00
|
|
|
{
|
|
|
|
v4 P = Leds->Positions[LedIndex];
|
|
|
|
r32 LedRange = 300.0f;
|
|
|
|
r32 ScaleFactor = 1.0f / LedRange;
|
|
|
|
v3 Pp = P.xyz + v3{150, 100, 0};
|
|
|
|
|
|
|
|
r32 NoiseA = Noise3D((Pp / 38) + v3{0, 0, Time});
|
|
|
|
NoiseA = PowR32(NoiseA, 3);
|
|
|
|
NoiseA = Smoothstep(NoiseA);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 CA = C0 * NoiseA;
|
2021-03-23 02:09:30 +00:00
|
|
|
|
|
|
|
r32 NoiseB = Noise3D((Pp / 75) + v3{Time * 0.5f, 0, 0});
|
|
|
|
NoiseB = PowR32(NoiseB, 3);
|
|
|
|
NoiseB = Smoothstep(NoiseB);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 CB = C1 * NoiseB;
|
2021-03-23 02:09:30 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C = (C0 * NoiseA) + (C1 * NoiseB);
|
|
|
|
C /= (NoiseA + NoiseB);
|
2021-03-23 02:09:30 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
internal r32
|
|
|
|
Leafy_BandSDF(v3 P, gs_random_series* Random, r32 Time)
|
|
|
|
{
|
|
|
|
r32 MinBandThickness = 5;
|
|
|
|
r32 MaxBandThickness = 10;
|
|
|
|
r32 MaxTransitionPeriod = 120.0f;
|
|
|
|
|
|
|
|
r32 BandTransitionPeriod = NextRandomUnilateral(Random) * MaxTransitionPeriod;
|
|
|
|
r32 BandTransitionBias = (1 - Clamp(0, (Time / (MaxTransitionPeriod / 2)), 0.7f)); // approaches 0.5 over time
|
|
|
|
BandTransitionPeriod *= BandTransitionBias;
|
|
|
|
|
|
|
|
r32 BandPercent = ModR32(Time, BandTransitionPeriod) / BandTransitionPeriod;
|
|
|
|
BandPercent = Smoothstep(BandPercent);
|
|
|
|
r32 BandY = -150 + (BandPercent * 290);
|
|
|
|
|
|
|
|
r32 ThickRand = NextRandomUnilateral(Random);
|
|
|
|
// 1 - 4((ThickRand - .5)^2) - distribution curve
|
|
|
|
ThickRand = 1.0f - ((4 * PowR32(ThickRand, 2)) - (4 * ThickRand) + 1);
|
|
|
|
r32 BandThickness = MinBandThickness + (ThickRand * (MaxBandThickness - MinBandThickness));
|
|
|
|
|
|
|
|
// BandBrightness = 1 - ((2x - 1) ^ 8) where x is BandPercent
|
|
|
|
r32 BandBrightness = 1.0f - PowR32((2 * BandPercent) - 1, 8);
|
|
|
|
BandBrightness *= RemapR32(NextRandomUnilateral(Random), 0, 1, .25f, 1);
|
|
|
|
r32 Result = 1 - Clamp01(Abs(P.y - BandY) / BandThickness);
|
|
|
|
Result *= BandBrightness;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2021-03-20 22:15:35 +00:00
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_Leafy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
2021-03-23 03:58:52 +00:00
|
|
|
DEBUG_TRACK_FUNCTION;
|
|
|
|
|
2021-03-27 23:00:06 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
2021-03-31 02:55:54 +00:00
|
|
|
phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
|
|
|
|
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1});
|
2021-03-21 04:49:02 +00:00
|
|
|
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
|
|
|
v4 P = Leds->Positions[LedIndex];
|
2021-03-21 04:49:02 +00:00
|
|
|
|
2021-03-21 02:10:12 +00:00
|
|
|
v4 C = {};
|
2021-03-20 22:15:35 +00:00
|
|
|
r32 B = 0;
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
// NOTE(PS): initializing the Random seed inside the Led Loop
|
|
|
|
// so that the bands are consistently calculated for each led
|
|
|
|
// ie. each time you calculate a band, the random numbers requested
|
|
|
|
// will always be the same
|
|
|
|
gs_random_series Random = InitRandomSeries(24601);
|
|
|
|
u32 BandCount = 25;
|
2021-03-20 22:15:35 +00:00
|
|
|
for (u32 Band = 0; Band < BandCount; Band++)
|
|
|
|
{
|
2021-03-31 02:55:54 +00:00
|
|
|
B += Leafy_BandSDF(P.xyz, &Random, Time);
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
2021-03-31 02:55:54 +00:00
|
|
|
B = Clamp01(B);
|
2021-03-20 22:15:35 +00:00
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
C = WhiteV4 * B;
|
2021-03-21 02:10:12 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_LeafyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
2021-03-23 03:58:52 +00:00
|
|
|
DEBUG_TRACK_FUNCTION;
|
2021-03-27 23:00:06 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
2021-03-31 02:55:54 +00:00
|
|
|
|
|
|
|
phrase_hue Hue = BlumenLumen_GetCurrentHue(BLState, Assembly);
|
2021-03-27 23:00:06 +00:00
|
|
|
v4 C0 = HSVToRGB({Hue.Hue0, 1, 1, 1});
|
|
|
|
v4 C1 = HSVToRGB({Hue.Hue1, 1, 1, 1});
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C2 = HSVToRGB({Hue.Hue2, 1, 1, 1});
|
|
|
|
|
2021-03-23 03:58:52 +00:00
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
|
|
|
{
|
|
|
|
v4 P = Leds->Positions[LedIndex];
|
|
|
|
v3 Pp = P.xyz + v3{150, 100, 0};
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 NoiseA = Fbm3D((Pp / 18), Time * 0.25f);
|
2021-03-23 03:58:52 +00:00
|
|
|
NoiseA = Smoothstep(NoiseA);
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 0.5f});
|
2021-03-23 03:58:52 +00:00
|
|
|
NoiseB = PowR32(NoiseB, 3);
|
|
|
|
NoiseB = Smoothstep(NoiseB);
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
r32 NoiseC = Noise3D((Pp / 25) + v3{0, 0, Time * 4});
|
|
|
|
r32 CPresence = SinR32((P.y / 50) - Time) + (0.8f * SinR32((P.y / 25) - (Time * 5.0f)));
|
|
|
|
CPresence = RemapR32(CPresence, -1.8, 1.8, 0, 1);
|
|
|
|
CPresence = PowR32(CPresence, 4);
|
|
|
|
NoiseC *= CPresence;
|
|
|
|
|
|
|
|
v4 C = (C0 * NoiseA * 0.5f) + (C1 * NoiseB) + (C2 * NoiseC);
|
|
|
|
C *= 1.0f / (NoiseA + NoiseB + NoiseC);
|
2021-03-23 03:58:52 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2021-03-23 03:58:52 +00:00
|
|
|
Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-03-31 02:55:54 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
Pattern_VerticalLines(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
2021-03-20 22:15:35 +00:00
|
|
|
{
|
2021-03-23 03:58:52 +00:00
|
|
|
DEBUG_TRACK_FUNCTION;
|
2021-03-25 02:45:11 +00:00
|
|
|
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData;
|
2021-03-23 05:36:33 +00:00
|
|
|
gs_random_series Random = InitRandomSeries(24601);
|
|
|
|
|
|
|
|
r32 LightSpeedMin = 1;
|
|
|
|
r32 LightSpeedMax = 5;
|
|
|
|
|
|
|
|
s32 LightTailLength = 10;
|
|
|
|
for (u32 StripIndex = 0; StripIndex < Assembly.StripCount; StripIndex++)
|
|
|
|
{
|
|
|
|
v2_strip Strip = Assembly.Strips[StripIndex];
|
|
|
|
|
|
|
|
r32 LightStartHeight = NextRandomUnilateral(&Random);
|
|
|
|
r32 LightSpeed = LerpR32(NextRandomUnilateral(&Random),
|
|
|
|
LightSpeedMin,
|
|
|
|
LightSpeedMax);
|
|
|
|
r32 LightCurrentHeight = LightStartHeight + (LightSpeed * Time * 0.1f);
|
|
|
|
s32 StartIndex = (s32)(LightCurrentHeight * (r32)Strip.LedCount) % Strip.LedCount;
|
|
|
|
|
|
|
|
for (s32 i = 0; i < LightTailLength; i++)
|
|
|
|
{
|
|
|
|
s32 StripLedIndex = StartIndex + i;
|
|
|
|
if (StripLedIndex >= (s32)Strip.LedCount) continue;
|
|
|
|
|
|
|
|
u32 LedIndex = Strip.LedLUT[StripLedIndex];
|
|
|
|
r32 PctTail = ((r32)i / (r32)LightTailLength);
|
2021-03-31 02:55:54 +00:00
|
|
|
v4 C = WhiteV4 * PctTail;
|
2021-03-23 05:36:33 +00:00
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 22:15:35 +00:00
|
|
|
}
|
|
|
|
|
2021-03-31 02:55:54 +00:00
|
|
|
internal void
|
|
|
|
Pattern_Rotary(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
|
|
|
{
|
|
|
|
gs_random_series Random = InitRandomSeries(24601);
|
|
|
|
|
|
|
|
#define SphereCount 32
|
|
|
|
v3 SphereCenter[SphereCount];
|
|
|
|
|
|
|
|
r32 MaxHeightOffset = 150;
|
|
|
|
r32 MaxSpeed = 10;
|
|
|
|
r32 SphereRadius = 2.0f;
|
|
|
|
for (u32 i = 0; i < SphereCount; i++)
|
|
|
|
{
|
|
|
|
r32 SphereSeedA = NextRandomBilateral(&Random);
|
|
|
|
r32 SphereSeedB = NextRandomBilateral(&Random);
|
|
|
|
r32 SphereSpeed = NextRandomUnilateral(&Random) * MaxSpeed;
|
|
|
|
|
|
|
|
r32 SphereTime = Time + SphereSpeed;
|
|
|
|
r32 HeightOffset = SphereTime + (SphereSeedA * MaxHeightOffset);
|
|
|
|
r32 RotationOffset = SphereTime + SphereSeedB * TauR32;
|
|
|
|
r32 SphereRotationDir = NextRandomBilateral(&Random) < 0 ? -1 : 1;
|
|
|
|
v3 SpherePosOffset = v3{
|
|
|
|
SinR32(RotationOffset * SphereRotationDir) * (SphereRadius * 2),
|
|
|
|
HeightOffset,
|
|
|
|
CosR32(RotationOffset * SphereRotationDir) * (SphereRadius * 2)
|
|
|
|
};
|
|
|
|
SphereCenter[i] = Assembly.Center + SpherePosOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
|
|
|
{
|
|
|
|
v3 P = Leds->Positions[LedIndex].xyz;
|
|
|
|
|
|
|
|
r32 Dist = 10000000;
|
|
|
|
for (u32 i = 0; i < SphereCount; i++)
|
|
|
|
{
|
|
|
|
r32 SphereSDF = Abs(SDF_Sphere(P, SphereCenter[i], SphereRadius));
|
|
|
|
SphereSDF = SphereSDF / SphereRadius;
|
|
|
|
Dist = Min(Dist, SphereSDF);
|
|
|
|
}
|
|
|
|
|
|
|
|
v4 C = BlackV4;
|
|
|
|
if (Dist <= 1)
|
|
|
|
{
|
|
|
|
r32 Brightness = Clamp01(SphereRadius - Dist);
|
|
|
|
C = WhiteV4 * Brightness;
|
|
|
|
}
|
|
|
|
|
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
Pattern_AllOnMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
|
|
|
{
|
|
|
|
pixel White = V4ToRGBPixel(WhiteV4);
|
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
|
|
|
{
|
|
|
|
v3 P = Leds->Positions[LedIndex].xyz;
|
|
|
|
Leds->Colors[LedIndex] = White;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
Pattern_BulbMask(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
|
|
|
|
{
|
|
|
|
r32 Top = 141;
|
|
|
|
r32 BulbRange = 50;
|
|
|
|
|
|
|
|
pixel White = V4ToRGBPixel(WhiteV4);
|
|
|
|
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
|
|
|
|
{
|
|
|
|
v3 P = Leds->Positions[LedIndex].xyz;
|
|
|
|
|
|
|
|
r32 BulbSDF = 1 - Clamp01(((Top - P.y) - BulbRange) / BulbRange);
|
|
|
|
r32 N = Noise3D((P / 17) + v3{Time, -Time, 0});
|
|
|
|
N = Clamp01(N) * 2;
|
|
|
|
N = Smoothstep(N);
|
|
|
|
N *= N;
|
|
|
|
N = Smoothstep(N);
|
|
|
|
N *= 1.0f - PowR32(1.0f - BulbSDF, 4);
|
|
|
|
BulbSDF += N;
|
|
|
|
BulbSDF = Clamp01(BulbSDF);
|
|
|
|
v4 C = WhiteV4 * BulbSDF;
|
|
|
|
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 22:02:25 +00:00
|
|
|
#define BLUMEN_PATTERNS_H
|
|
|
|
#endif // BLUMEN_PATTERNS_H
|