1
$\begingroup$

Whenever talking about gamma correction the answer for the gamma value is always 2.2 or 2.3. I did some tests using standard view transform: Emission shader: 0.5 Render result with sRGB view transform: 0.7354 -> Gamma: 2.25530545664

Is my calculation correct and does somebody know why Blender uses such an arbitrary number?

$\endgroup$
6
  • 3
    $\begingroup$ When you have conflicting answers, what good is another answer? Blender does not use a straight power operation to convert between linear and sRGB color. The function appears to be srgb_to_linearrgb(), in github.com/blender/blender/blob/… . That code is as exact and concise a description of the algorithm used as you can get. Beware of texture filtering in tests to confirm. $\endgroup$
    – Nathan
    May 22, 2022 at 17:38
  • $\begingroup$ UNfortunately I actually don't have a coding background at all, so the source code really is only of limited use for me... But thanks anyways! Is there some kind of overview of where what part of the source code is or do you have everything memorized? $\endgroup$ May 23, 2022 at 15:37
  • $\begingroup$ Honestly, this is the first time I've searched Blender code. I know github has excellent search capabilities, so I just found the repository on Google, then searched for "srgb" and it only gave me a few options. Some coding knowledge helps for knowing which of those options is likely to be right, but you can just look in all of them. Most people learn to code just by reading code. The language here is C or C++ and the confusing part here is the ternary operator (confusing even for some experienced coders, source of arguments lol) but that name should be enough to find references. $\endgroup$
    – Nathan
    May 23, 2022 at 15:49
  • $\begingroup$ How do I actually find out whether a file is in C or C++? $\endgroup$ May 23, 2022 at 15:56
  • $\begingroup$ Huh, I don't know, but for reading, it doesn't usually matter :) $\endgroup$
    – Nathan
    May 23, 2022 at 16:11

1 Answer 1

3
$\begingroup$

As Nathan points out in the comments, using a Gamma node with the magic "2.2" value is only approximate because sRGB<->Linear conversions involve a power function.

As I needed a more exact conversion for my specific use case (I'm encoding bitmasks as colours into my vertexes as an optimisation for my game), I have taken the blender source that was linked (https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/blenlib/intern/math_color.c) and converted it to blender nodes for your convenience.

Converting sRGB to Linear

Blender's implementation in C

float srgb_to_linearrgb(float c)
{
  if (c < 0.04045f) {
    return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
  }

  return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
}

Material node equivalent

blender_srgb_to_linear_nodes

Converting Linear to sRGB

Blender's implementation in C

float linearrgb_to_srgb(float c)
{
  if (c < 0.0031308f) {
    return (c < 0.0f) ? 0.0f : c * 12.92f;
  }

  return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
}

Material node equivalent

blender_linear_to_srgb_nodes

I've implemented both of these as node groups in my project. Here's a minimal use case of it in action, which will read my vertex colour's red channel and convert it to the range 0-255, which matches my setup in Unreal Engine: trivial_use_case

Note that some of the numbers in the screenshots have been truncated in blender, if implementing again yourself, you may have to manually punch in 1/12.92/or whatever to get closer to my implementation's results.

Also note that I haven't tested these blender nodes extensively -- I am no expert with this software, but figured this would be a helpful starting point for artists to interpret the C equivalent for conversions.

$\endgroup$
2
  • $\begingroup$ "As I needed a more exact conversion for my specific use case (I'm encoding bitmasks as colours into my vertexes as an optimisation for my game)" might be an XY problem... You can easily convert to linear by choosing the right setting in the Image Texture node. You can easily convert from linear by choosing the right setting in the output settings. Why calculate it in the shader? $\endgroup$ Feb 11 at 9:41
  • $\begingroup$ While the Image Texture node does provide easy transforms for the colour space, not using one. I'm sampling from the vertex colour via a "Color Attribute" node. I'm using "Face Corner/Byte Color" because that's the format Unreal Engine wants, but the result is different in Blender (3.6) so I believe I need this manual step. If there's a way of sampling the vertex colour without a transformation, please let me know. $\endgroup$
    – Salami
    Feb 11 at 13:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .