Skip to content

Commit

Permalink
Faster ray trace GMA
Browse files Browse the repository at this point in the history
Ensure the initial ray cast is done with the smallest angle. This is
done by passing the origin (color with no chroma) and passing the ray
through a second color with (almost no chroma) to guide the direction.
This is done instead of casting through the origin and the current color
which often yields the greatest angle of deviation. This will actually
cause the GMA to converge on an optimal value in less iterations,
allowing us to only require 3 passes instead of 4 while still
maintaining a ∆h somewhere in the ~2 range.
  • Loading branch information
facelessuser committed Mar 19, 2024
1 parent d4d27af commit add75a1
Showing 1 changed file with 7 additions and 2 deletions.
9 changes: 7 additions & 2 deletions apps/gamut-mapping/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ const methods = {
return methods.raytrace.trace(mapColor);
},
trace: (mapColor) => {
let gamutColor = mapColor.to("p3-linear");
let achroma = mapColor.set("c", 0).to("p3-linear").coords;
let gamutColor = mapColor.set("c", 1e-8).to("p3-linear");
let raytrace = methods.raytrace.raytrace_box;

// Cast a ray from the zero chroma color to the target color.
// Trace the line to the RGB cube edge and find where it intersects.
// Correct L and h within the perceptual OkLCh after each attempt.
let light = mapColor.coords[0];
let hue = mapColor.coords[2];
for (let i = 0; i < 4; i++) {
for (let i = 0; i < 3; i++) {
if (i) {
const oklch = gamutColor.oklch;
oklch.l = light;
Expand Down Expand Up @@ -150,6 +150,11 @@ const methods = {
tnear = tfar;
}

// Result should be finite
if (!isFinite(tnear)) {
return [];
}

// Calculate nearest intersection via interpolation
return [
start[0] + direction[0] * tnear,
Expand Down

0 comments on commit add75a1

Please sign in to comment.