I’ve come across an inconsistency in Godot 3, which is not a big issue for me right now, but I’m curious to find out where it comes from.
I have a Viewport rendering a UI with the background colour #1d186b, and writing to a ViewportTexture which I then pass into a SpatialMaterial as both the albedo and emission texture. Albedo colour is white, emission colour is black, emission mode is additive.
When I make another SpatialMaterial with identical parameters, except without the texture, and with albedo and emission colour set to #1d186b, the resulting colour is noticeably different.
Godot renders 3D scenes in the linear color space before converting the generated texture to sRGB for display. When you then take that sRGB texture and use it in a 3D scene again, that texture is treated as if it were in the linear color space even though it’s actually in sRGB, resulting in brighter and washed-out colors. In other words, your colors are getting converted from linear to sRGB twice.
There’s a setting on the Viewport called keep_3d_linear that lets you ignore the conversion of the 3D scene from linear to sRGB, but this will not work in your case because you’re rendering a 2D UI, which is always in sRGB.[1]
Instead, you’ll have enable the SpatialMaterial’s flags_albedo_tex_force_srgb value to true. This will convert the ViewportTexture, which is in sRGB, back to linear space:
As you can see, the color is still incorrect, but that’s because the flag only corrects the color space of the albedo texture; the emission texture is still in sRGB. If you remove the emission texture and set the emission color to #1d186b, then you get exactly the same colors:
In order to fully fix your problem in Godot 3, I think you’ll have to add a script to convert the ViewportTexture into linear space before using it as the emission texture in the SpatialMaterial. Your other option is to upgrade to Godot 4, where the issue has apparently been addressed (not sure when), and the colors match exactly when using a ViewportTexture that is rendering a UI as your albedo and emission textures:
Unless I end up switching to Godot 4, I think I’ll use flags_albedo_tex_force_srgb combined with flags_unshaded on the SpatialMaterial, since it’s quite simple, and I probably don’t need specular etc. on the ingame LCD panels.