TBH both look wrong to me. If I squint, neither dithering patterns match the original gradient... but the non-linearized one looks the most similar.
What could be causing this?
TBH both look wrong to me. If I squint, neither dithering patterns match the original gradient... but the non-linearized one looks the most similar.
What could be causing this?
edit:
Reading back, viewing the gradients also not at 100% zoom level could also itself cause the mismatch, because browsers just suck at image scaling.
I remember I had quite a bit of discussion with madshi when MadVR tried implementing it. You can do something that comes close by modifying the colour space into something that is gamma light in the integer part and linear light in the fractional part.
If the value of a pixel is x you then get something like floor(x) + (l - ginv(x)) / (l - u) with l and u the the two shades corresponding to floor(x) and ceil(x) in linear light.
Though technically error diffusion will still be incorrect, but it does handle constant shades correctly and most alternatives are worse somehow.
Edit: Oh and I see you suffer from the patterned runs of pixels that plagued madshi ;-) It's one of the reasons I prefer simple patterned dithers
See: Dithering should happen in sRGB https://www.shadertoy.com/view/NssBRX
It gets much worse if you uncomment the SHOW_CORRECT define since the data is then being transformed back to SRGB before being quantised, which quite heavily skews the probability of which code point will be selected in favour of the lighter colour.
Increasing the number of bits hides the effect somewhat by making more code points available. But because they're distributed in gamma-encoded rather than linear-encoded space, it's still not correct to assume that a 50/50 pixel mix of two adjacent code points will appear the same as the colour numerically halfway between them, unless you're making that judgement in linear space.
The mistake the shadertoy is making is transforming the data to sRGB before quantising. Both dithering and quantising should be done in linear space (which is non-trivial since in linear space the codepoints aren't linearly distributed any more) - otherwise the dither function's triangular distribution is skewed by the sRGB transform.
They have a different default gamma and they may show a different gray level.
(It bite me a long time ago. I made a gif that has the same RGB bacground than a webpage. In my pc it was fine, but in a mac they the border was very visible and the result horrible. My solution was to change the backgroung of the webpage from a RGB number to a 1 pixel gif with repetition or scale to fill the page.)
But in this case I think it's just wrong. The entire first 40% of the bar is black, and I don't think it should be.
Hypercorrection, in this care over-linearisation.