Skip to content

Commit

Permalink
WIP HSV lerp
Browse files Browse the repository at this point in the history
  • Loading branch information
PeenScreeker committed Dec 1, 2023
1 parent a87aff3 commit ba64b0b
Showing 1 changed file with 80 additions and 2 deletions.
82 changes: 80 additions & 2 deletions scripts/util/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,88 @@ function rgbaTupleLerp(colorA: RgbaTuple, colorB: RgbaTuple, alpha: number): Rgb
* Blends two colors linearly (not HSV lerp).
* RGB inputs are converted to RGBA with A value of 1.
*/
function rgbaStringLerp(colorA: string, colorB: string, alpha: number): string {
function rgbaStringLerp(colorA: string, colorB: string, alpha: number, useHsv: boolean = false): string {
const arrayA = rgbaStringToTuple(colorA);
const arrayB = rgbaStringToTuple(colorB);
return tupleToRgbaString(rgbaTupleLerp(arrayA, arrayB, alpha));
if (!useHsv) return tupleToRgbaString(rgbaTupleLerp(arrayA, arrayB, alpha));

const FromHSV: RgbaTuple = LinearRGBToHSV(arrayA) as RgbaTuple;
const ToHSV: RgbaTuple = LinearRGBToHSV(arrayB) as RgbaTuple;

// Take the shortest path to the new hue
if (Math.abs(FromHSV[0] - ToHSV[0]) > 180) {
if (ToHSV[0] > FromHSV[0]) {
FromHSV[0] += 360;
} else {
ToHSV[0] += 360;
}
}
const newHsv = rgbaTupleLerp(FromHSV, ToHSV, alpha);

newHsv[0] = newHsv[0] % 360;
if (newHsv[0] < 0) {
newHsv[0] += 360;
}

const newRgb: RgbaTuple = HSVToLinearRGB(newHsv) as RgbaTuple;

return tupleToRgbaString(newHsv);
}
/** Converts an HSV color to a linear space RGB color */
function HSVToLinearRGB([h, s, v, a]: RgbaTuple): number[] {
// In this color, R = H, G = S, B = V
const Hue = h;
const Saturation = s;
const Value = v;

const HDiv60 = Hue / 60;
const HDiv60_Floor = Math.floor(HDiv60);

Check warning on line 97 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Floor' is not in camel case
const HDiv60_Fraction = HDiv60 - HDiv60_Floor;

Check warning on line 98 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Fraction' is not in camel case

Check warning on line 98 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Floor' is not in camel case

const RGBValues: RgbaTuple = [
Value,
Value * (1 - Saturation),
Value * (1 - HDiv60_Fraction * Saturation),

Check warning on line 103 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Fraction' is not in camel case
Value * (1 - (1 - HDiv60_Fraction) * Saturation)

Check warning on line 104 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Fraction' is not in camel case
];
const RGBSwizzle = [
[0, 3, 1],
[2, 0, 1],
[1, 0, 3],
[1, 2, 0],
[3, 1, 0],
[0, 1, 2]
];
const SwizzleIndex = HDiv60_Floor % 6;

Check warning on line 114 in scripts/util/colors.ts

View workflow job for this annotation

GitHub Actions / build

Identifier 'HDiv60_Floor' is not in camel case

return [
RGBValues[RGBSwizzle[SwizzleIndex][0]] * 255,
RGBValues[RGBSwizzle[SwizzleIndex][1]] * 255,
RGBValues[RGBSwizzle[SwizzleIndex][2]] * 255,
a
];
}

function LinearRGBToHSV([r, g, b, a]: RgbaTuple): number[] {
const RGBMin = Math.min(r, g, b);
const RGBMax = Math.max(r, g, b);
const RGBRange = RGBMax - RGBMin;

const Hue =
RGBMax === RGBMin
? 0
: RGBMax === r
? (((g - b) / RGBRange) * 60 + 360) % 360
: RGBMax === g
? ((b - r) / RGBRange) * 60 + 120
: RGBMax === b
? ((r - g) / RGBRange) * 60 + 240
: 0;

const Saturation = RGBMax === 0 ? 0 : RGBRange / RGBMax;
const Value = RGBMax / 255;

return [Hue, Saturation, Value, a];
}

/**
Expand Down

0 comments on commit ba64b0b

Please sign in to comment.