Skip to content

Use weighted harmonic mean for temperature interpolation#43

Draft
aeraglyx wants to merge 2 commits intopsi4j:mainfrom
aeraglyx:temperature-interpolation
Draft

Use weighted harmonic mean for temperature interpolation#43
aeraglyx wants to merge 2 commits intopsi4j:mainfrom
aeraglyx:temperature-interpolation

Conversation

@aeraglyx
Copy link
Contributor

@aeraglyx aeraglyx commented Jan 5, 2026

Interpolating color temperatures in the "inverse space" to make transitions perceptually uniform. More info in #44.

This modifies the original utility function interpolate_u32.

Just not sure about the naming. I chose interpolate_inverse_u32 to signify it's not just a simple lerp, but maybe interpolate_temp_u32 could also work?

@psi4j
Copy link
Owner

psi4j commented Jan 9, 2026

Testing this new interpolation method removes the broadened low end of the Kelvin color spectrum (deliberately), making the default update interval (60 sec) too long and the color jump from one update to the next too large. This creates visual discontinuity when using our default settings with non-extreme latitudes. Try running some simulations using something like this for your geo coordinates (or using manual times) and compare the transition smoothness to the current binary from main:

sunsetr --simulate "2026-01-08 15:44:27" "2026-01-08 16:46:51" 720

By making the spectrum more uniform, we've effectively compressed the relevant portion of the Kelvin spectrum that our settings have been fine-tuned for. In order to implement this new method properly, we will need to make changes to the update interval, and or adjust the Bezier curve and potentially other parameters.

While I do like the idea of making the interpolation of the full color spectrum perceptually uniform, I would like to note that using the bluer end of the spectrum (beyond 6500) defeats the purpose of the application as a blue-light filter, so I would prefer to prioritize for transition smoothness. I recognize some individuals might like their day temperature adjusted higher to something like 7000K, so I did make the day temperature configurable. I would like to see if we can fine-tune this change to avoid visual discontiuity.

What would you suggest for making the transition updates less jarring for a 25-45 minute transition duration while using the Mired method you've implemented? I'm open to discussing an optimal solution for this.

@aeraglyx
Copy link
Contributor Author

aeraglyx commented Jan 10, 2026

Thanks for the comment. I tried a few sped-up simulations with no curve and also plotting the gradients in Blender, here are some thoughts. In general, yes I think it would make sense to adjust the Bezier points, probably to something more symmetric (or even switch to a simpler smoothstep function).

I guess the sRGB normalization might be a bit problematic. By dividing everything by the max component, it creates a discontinuity around "white" where the luminance drops off quickly on both sides. And by compressing the mid/high temp portion with this PR, it gets more visible during the transition. I wonder if there's a way to smooth that out (perhaps with some clever tone-mapping). So (ignoring Bezier), while it makes the temperature changes more perceptually uniform, luminance changes after normalization get harsher...

Anyway, here are a few images that plot 1000-12000K using the two interpolations (and no Bezier on top). I used Blenders native Blackbody node instead of imitating the exact code, hopefully it's close enough.

Original vs PR (without normalization, scaled to avoid clipping):

original_no_norm
new_no_norm

Original vs PR (with normalization):

original_with_norm
new_with_norm

For reference, the PR versions have 1846K in the "middle" (instead of 6500K for the originals). Here's a less drastic 2500-6500K transition (with normalization):

original_with_norm_v2
new_with_norm_v2

There's still a small issue with the update interval that the jumps are dependent on transition duration and mired difference (technically also the gamma diff..). Maybe a more robust solution could be to have an adaptive update interval that would check how quickly is the output color multiplier changing in some perceptually uniform color space like oklab, but I haven't really thought that through...

the bluer end of the spectrum (beyond 6500) defeats the purpose of the application as a blue-light filter

Personally I also don't see a reason to use anything beyond 6500K, I just like the idea that it could work consistently for any range.

@aeraglyx aeraglyx force-pushed the temperature-interpolation branch from 33a7b60 to 0d69549 Compare January 10, 2026 18:02
@psi4j
Copy link
Owner

psi4j commented Jan 11, 2026

I guess the sRGB normalization might be a bit problematic. By dividing everything by the max component, it creates a discontinuity around "white" where the luminance drops off quickly on both sides. And by compressing the mid/high temp portion with this PR, it gets more visible during the transition.

I see what you're saying. Thank you for rendering the transition gradients in Blender. This makes things much more concrete via juxtaposition. I do think that using the Mired interpolation is the better way to do things, so I'll be looking into creating an adaptive interval that takes advantage of Oklab to try to smooth out the noticeable jumps (thanks for sharing Oklab). What I'm thinking is possibly making a new update_interval setting available as:

update_interval = "adaptive"
# OR
update_interval = 60 # constant

If this works well enough and fairly ubiquitously across devices, maybe we could just remove the update_interval altogether like you said.

Is there a way we could chat real-time or maybe still asynchronously so we don't pollute the PRs?

@aeraglyx
Copy link
Contributor Author

Sure, maybe Discord or Signal?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants