godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.56k stars 21.27k forks source link

Rendering discrepancies between forward_plus and gl_compatibility #88214

Open Calandiel opened 9 months ago

Calandiel commented 9 months ago

Tested versions

System information

Godot v4.2.1.stable.mono - Fedora Linux 38 (Workstation Edition) - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3060 Laptop GPU () - 11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz (12 Threads)

Issue description

ShaderMaterials are drawn differently on the gl_compatibility render backend compared to the forward_plus backend. Forward+ colors are desaturated and washed out - this does not happen with the StandardMaterial3D. The scene, the shader and the environment settings are kept simple to minimize the odds of it being a side effect of a feature unsupported on gl_compatibility.

The shader in question:

shader_type spatial;

uniform sampler2D main_texture;

void fragment() {
    ALBEDO = texture(main_texture, UV).rgb;
}

It happens regardless of the render_mode (I also checked unshaded and diffuse_toon). The degree of "error" is also different between version 4.2.1 and 4.3dev3

Steps to reproduce

Minimal reproduction project (MRP)

mrp.zip

AThousandShips commented 9 months ago

This sounds related to sRGB, can you test with:

uniform sampler2D main_texture : source_color;
Calandiel commented 9 months ago

Hmmm, indeed, that does it.

Although, without it, the behavior is different between 4.2.1 and 4.3dev3 (the color is "washed out" differently). Is that intentional?

Calinou commented 9 months ago

Different colors are expected between Forward+, Mobile and Compatibility due to how lighting is rendering in each method. This is especially the case in 3D rendering as lighting differences are the most pronounced there. Most notably, the Compatibility rendering method performs lighting in sRGB space, which is faster but less accurate. Lights with shadows enabled are also rendered additively, which is even less accurate but is a necessary compromise to offer acceptable performance on low-end devices.

To make renderers look closer to each other, you can check the current rendering method being used and modify light parameters using a script. This requires https://github.com/godotengine/godot/pull/85430 to be merged so that the actual rendering method (including fallbacks performed by the engine) can be read from a project. These tweaks aren't something we can automatically do on our end as the exact parameters will vary depending on the scene – only tweaking by eye is a viable solution here.

This is also why it's strongly recommended to stick to a single rendering method throughout a project's development. Offering fallbacks is nice to cover more devices, but it quickly gets very expensive in terms of development and QA.

brcontainer commented 9 months ago

@Calandiel This is not a problem with the shader, here is a 3D Minimal reproduction project (MRP):

colorbug.zip


Results:

forward+ and mobile (Godot 4.2.1): fowardplus (Godot 4.2.1)

gl_compatibility (Godot 4.2.1): gl_compatibility (Godot 4.2.1)

forward+ and mobile (Godot 4.3-dev3): fowardplus (4 3)

gl_compatibility (Godot 4.3-dev3): gl_compatibility (4 3)

Godot 3.5 GLSE2/3

Results:

Godot 3.5 GLSE2/3

In Godot3 the result is also satisfactory, of course everyone has different results, but it is very little, while in Godot4 with gl_compatibility it changes a lot.

cc @Calinou

Calandiel commented 9 months ago

@Calinou wrt your last reply, I understand now where this behavior is coming from but I'd like to bring attention to the second point I raised in this issue (in retrospection maybe it should have been two issues :slightly_smiling_face: ).

That is, the behavior is different between 4.2.1 and 4.3dev3 (the color is "washed out" differently). Is that expected behavior too?