Skip to content

Commit

Permalink
Do not optimize ray trace method for far away colors
Browse files Browse the repository at this point in the history
It turns out, when testing far away _and_ near colors, that optimizing
with the smallest angle from origin (achromatic) can yield better
results for far color, but worse results for near colors. This is
just due to how the perceptual spaces curve through the linear RGB
space. But by leaving things as they were previously (tracing from
achromatic to the sample and using 4 iterations instead of 3) results
are more consistent near to far. Colors nearer to the gamut are often
more accurate, but far colors are still below ∆h of 2. It is better to
have more accurate near and far colors than gain some speed to converge
far colors faster.
  • Loading branch information
facelessuser committed Mar 29, 2024
1 parent 085a3bc commit 98e3404
Showing 1 changed file with 13 additions and 12 deletions.
25 changes: 13 additions & 12 deletions apps/gamut-mapping/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,24 +199,25 @@ const methods = {
return methods.raytrace.trace(mapColor);
},
trace: (mapColor) => {
let achroma = mapColor.set("c", 0).to("p3-linear").coords;
let gamutColor = mapColor.set("c", 1e-8).to("p3-linear");
let [light, chroma, hue] = mapColor.coords;
mapColor.c = 0;
let achroma = mapColor.to("p3-linear").coords;
mapColor.c = chroma;
mapColor = mapColor.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 < 3; i++) {
for (let i = 0; i < 4; i++) {
if (i) {
const oklch = gamutColor.oklch;
const oklch = mapColor.oklch;
oklch.l = light;
oklch.h = hue;
}
const intersection = raytrace(achroma, gamutColor.coords);
const intersection = raytrace(achroma, mapColor.coords);
if (intersection.length) {
gamutColor.setAll(gamutColor.space, intersection);
mapColor.setAll(mapColor.space, intersection);
continue;
}

Expand All @@ -225,17 +226,17 @@ const methods = {
}

// Remove noise from floating point math by clipping
let coords = gamutColor.coords;
gamutColor.setAll(
gamutColor.space,
let coords = mapColor.coords;
mapColor.setAll(
mapColor.space,
[
util.clamp(0.0, coords[0], 1.0),
util.clamp(0.0, coords[1], 1.0),
util.clamp(0.0, coords[2], 1.0),
],
);

return gamutColor.to("p3");
return mapColor.to("p3");
},
raytrace_box: (start, end, bmin = [0, 0, 0], bmax = [1, 1, 1]) => {
// Use slab method to detect intersection of ray and box and return intersect.
Expand Down

0 comments on commit 98e3404

Please sign in to comment.