VisualShader: Add LinearToSRGB and SRGBToLinear to ColorFunc node
Implements and closes https://github.com/godotengine/godot-proposals/issues/10818.
Adds LinearToSRGB and SRGBToLinear conversions to the visual shader node ColorFunc.
Implementation: This node automatically switches it's conversion function depending on which renderer is used.
The RenderingDevice (Forward+ and Mobile Renderer) conversion functions: https://github.com/godotengine/godot/blob/4254946de93bab0cc1fb36a7b9039c9ec43be924/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl#L121-L130
The Compatibility renderer uses slightly different functions: https://github.com/godotengine/godot/blob/4254946de93bab0cc1fb36a7b9039c9ec43be924/drivers/gles3/shaders/tonemap_inc.glsl#L13-L26
If https://github.com/godotengine/godot/pull/90187 is merged, and the change in that PR is also made to the GLSL version of the linear_to_srgb and srgb_to_linear functions, then this visual shader node will need to be updated.
All else being equal, the visual shader node should be accurate to whatever computation is used in the current renderer (or, if it must make assumptions, favor the Forward+ and Mobile renderers). But if the Compatibility approximation is both much faster and still very accurate, then it makes sense to use it for visual shdaer nodes, where you might be converting between color spaces repeatedly (if a node is there, it will be used!).
The computation now depends on the renderer, exactly matching whichever computation is used internally.
Thanks!
I have been working on the HDR output PR, which requires the use of HDR buffers. This PR is useful because it allows simulation of traditional blending with nonlinear sRGB-encoded values, while still using HDR buffers. This approach involves performing a linear to sRGB conversion, applying blending or other shader operations, and then converting back to linear.
Especially when using HDR output it is important that all HDR values are maintained (values above 1.0). This PR clamps these values so that colour information is lost if it is above 1.0, but only in the Mobile and Forward+ rendering methods that most need this colour information.
I understand that "this is the way it was previously done in many shader files in Godot", but in these previous cases it wouldn't have an impact because the colour value was immediately written to a buffer that clamps to [0, 1]. The use case for this node is different: it is expected that the user may be converting to and from nonlinear-sRGB encoding to achieve different effects. If they want to clamp, they can do so with the Clamp visual node.
Is there a reason that the clamp function was included in this node for Mobile and Forward+?