drwhut / tabletop-club

An open-source platform for playing tabletop games in a physics-based 3D environment for Windows, macOS, and Linux! Made with the Godot Engine.
MIT License
1.24k stars 49 forks source link

Replace the default SpatialShader with one that allows additive albedo blending. #298

Open pie75 opened 12 months ago

pie75 commented 12 months ago

Is your feature request related to a problem? Please describe. Multiplicative albedo blending is cool and all but it's not very flexible. Many textures work better when the white areas are preserved -- and this can be important when you're making lots of variants of the same piece.

Describe the solution you'd like At the moment, the default spatial shader just does ALBEDO = albedo.rgb * albedo_tex.rgb, and it needs to do ALBEDO = albedo.rgb + albedo_text.rgb

Somewhere in the piece creation stage, pieces should be assigned a different spatial material, which implements a copy of the default spatial material, with a flag that indicates whether it should multiply or add its albedo color to its albedo texture.

In the config.cfg, there should be a property called color_mode. color_blendmode, blendmode, or add_color set by default to color_mode= "multiply"/add_color = false, which can be set to color_mode = "add"/add_color = true

Describe alternatives you've considered Seeing as tabletop club already runs on a custom version of Godot, an alternative solution could be to actually replace the default spatial shader.

I suspect that the odd 'if else' in a fragment shader can be a little weird and wasteful -- one could just assign a shader that does the additive blending based on the config flag. But I think that having a custom default shader is the more extensible option, as wasteful as it is.

Currently, the "alternative" is to make tons of textures and duplicate .gltf files. It's quite cumbersome.

Additional context I've spent the past few weeks making assets, and it just keeps getting to me that I have to make everything so dark. Red dice with black pips are a pet peeve of mine, too.

drwhut commented 12 months ago

Thank you for the suggestion! I agree, this would help a lot when importing duplicate objects that only vary by colour - not only would it reduce the storage space needed for the pack, but it could also potentially improve the quality of the assets at the same time (like with black pips on red dice), so this seems like a no-brainer to me.

I had a look at Godot's own GitHub to see if anyone else had this idea, and surprisingly nothing came up... so I had a quick look at the material.cpp file which contains the definitions for the SpatialMaterial class, and lo and behold, the multiplying menace has been caught red-handed:

code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n";

It looks like for each SpatialMaterial, the engine manually writes all of the shader code given all of the flags from that given instance. At first glance, it looks actually kinda easy (I might regret saying that) to add an extra flag that switches an if statement from multiplying to adding, which would mean there shouldn't be any performance hit in the fragment shader, since it would bake in the addition operator to the shader rather than having an if branch in a "generic" shader. This could also potentially open the door to multiple different operations down the line as well!