Did I correctly implement the math for converting from CIE L*a*b* to sRGB (or other RGB colorspaces) in this shader?

I think it might actually be the same, now that I’m looking closer at it. (L+16)/116 is used both as the term to cube, and is the definition for fy - and on top of that, L/κ is equivalent to (116*fy - 16)/κ since you’d literally just be doing (116*(L + 16)/116 - 16)/κ, causing the two 116s to cancel out, then you’re just adding 16 immediately before subtracting 16.

The fact this wasn’t obvious to me before just shows I’m not really good at reading other people’s equations sometimes. It’s easy for me to get confused with those equations, which is why I didn’t mention Bruce’s website in my original post.

I redid the computation on my own 1 month ago, I did not find the same result. Maybe an error on my side, but still… If it’s the same, write it the same, no need to obfuscate the equations. I served my time at the university, I have had my share of sneaky teachers playing this dumb game, I’m too old for this nonsense.

Agreed, especially since I’m doing GLSL, where batching operations into vectors and matrices gives free performance benefits (as there’s dedicated hardware for those operations and the compiler can work faster; GLSL is compiled when it’s run, so fast compile times actually can matter).

Having a slightly more complex route for one of them than is strictly necessary, but as a result ensuring all of them can run simultaneously, can end up being better in the long run. At least in my case.

I’m still probably doing way more work than even doing it that way though, since I’m:

  1. Applying the offset to just L* (making the equivalent of fy)
  2. Calculating the equivalent to fx and fz
  3. Removing the offset from all 3 of them (even though it was only indirectly applied to fx and fz)
  4. Adding the offset back on, sorta, inside toLinear()

But since I’m getting at least 13 digits of accuracy when comparing to Colour-Science’s output (and I’ve since tested with sRGB values of [0.0001, 0.0001, 0.0001] to check against L* values below 0.008, and confirmed accuracy is kept in that case), I’m assuming that my code applies and removes that offset correctly in the end.