Hi Jan,
I have been using ProMotion Lately to generate pixelart textures for a palette lookup shader. ProMotion Does not have any Linear/SRGB display switches and actually editing linear values in the upper brighntess levels is kinda hard because the perceived brightness levels are so close together.
So I wanted to edit the textures using a reagular generated HSL or RGB gradient (which are the same value wise for greyscale gradients) and then use a Gamma 2.2 to linear conversion in the shader to get the colors ready for a texture lookup in my gradient texture. This way I would have nice editing in PM and correct values in the shader.
However: I noticed that the greyscale values PM generates when using the linear gradient option diverge somewhat from the actual conversion values the would be generated by the usual linear to Gamma transfer method [Power(input, 1.0/2.2)] Would you be willing to disclose how the gradient values are generated in PM so that I can reverse the colors to linear in my shader?
I’ve attached a image to show the differences (noticable the most in dark areas)
Hi @visionvortex,
the ramping in PM is generally a linear transition from color A to color B by scaling the color components (RGB, HSB, HSL…) with even steps.
For the ease of calculation, lets scale from 255 to 0 on every RGB channel in 10 steps.
Having color A being full white, there are 9 steps left to scale to full black.That means, a single step is 255 / 9 = 28.3 values darker than the one before. Every second/third step, it’s 29, due to rounding up the broken value.
There is no gamma correction as this is typically done by the displays.
-Jan
Thank you for the answer. I think the way you perform the calculation is different to how it usually is done.
As shown in the image the to gradient is a true linear gradient over 10 swatches from black to white
#FF #F2 #E4 #D5 #C4 #B1 #9C #81 #5D #00
Transforming this linear gradient into the preceptually linear brightness based gradient that is ususally used is done with a gamma function ( pow 2.2 ). So linear pow(linearRGB, 2.2) is the same result as sRGB.
If you just take brightness steps you run into very subtle differences. Visually that doesn’t make much difference but If I may I’ll elaborate on the usecase. In our project we are using a palette swapping shader. The shader reads the greyscale value from an input texture and, based on the brightness, looks into a color table to find the corrrect color index. This way you can do explosions etc. in greyscale and have a large number of properly palette shaded variations for very cheap at runtime.
I tried using PMs output greysacel gradient as base for the lookup. But the value differences through the rounding prevent certain indices from being “looked up”. That does not happen with the true linear gradient or any brightness based sRGB greysacle gradient, which I can transform back to linear by pow 1/2.2
If you are interested I can elaborate on this more. It would be nice however if PM could generate a true sRGB gradient in greyscale. For now I’m using a custom palette to get around the issue. And I understand it’s really a rather technical useCase XD
Thanks for all the details. Very interesting. So, what PM is doing is just a simple linear interpolation between source and target value. Linear means, between each color slot the difference is the same (except for some slight mismatch like one value because of rounding). That’s the basic, mathematical definition of “linear”. It would create a straight line if you placed the values into a 2d diagram where x is the number of the color slot and y one of the RGB channel values.
Yes, applying gamma correction as you described is typically used to map “technical” RGB values from the full RGB space to those values that can actually be perceived by human eye. Gamma correction translates them into the values actually used on the display device. This results in non-linear values, because human eye can not differ good enough in very bright or very dark ranges etc. . Pow 1/2.2 does a basic correction that stretches or squeezes values in the range.
Anyway, that basically what you described 
PM always works with “technical” RGB values. So, a linear scale is a linear scale as described, not matter what the user can perceive, because the user has a display device (and software) that doe gamma correction (and other corrections) so that technical RGB can be seen as it is meant to be seen.
When I create a 256 color ramp from white to black and fill a large image, then I can see an (almost) perfect linear scale, where I can see the difference between any two neighbor values when zooming in. This is because my display and software corrects the physical RGB values to what I’m able to see.
What I think should be done with your mapper, is:
take the RGB values from PM, apply pow(rgb, 1/2.2) and use this to find the color in your table.
Also, there is a layer effect in PM that does something similar. It allows you to draw pixels with palette indices 16-31 (for example) being 16 gray values and then let it map to other color ranges of 16 colors in the palette.
See Documentation | cosmigo and the effect “Re-apply color palette”. It comes with a sample project. But it’s maybe not want you want if you want to use arbitrary target colors. The effect would be limited to the 256 colors being there in the project/frame/layer palette.
I hope, we are not talking past each other 