godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.05k stars 65 forks source link

Implement `#overlay "path"` #9624

Open RadiantUwU opened 2 weeks ago

RadiantUwU commented 2 weeks ago

Describe the project you are working on

Sci-fi game where i want to overlay multiple shaders

Describe the problem or limitation you are having in your project

Being unable to combine shaders.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

This would allow to overlay multiple shaders on top of one another with ease.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This is the syntax for the overlay preprocessor instruction.

#overlay [blend_mix|blend_add|blend_sub|blend_mul] [alpha] "path"

All it does is combine what's done inside vertex, fragment, light with the given alpha. It allows you to easily overlay multiple shaders on top of one another with ease. Notably, defines before the #overlay preprocessor are passed to the shader being used to overlay.

Example 1:

base.gdshader

void fragment() {
#ifdef BASE_GDSHADER
    ALBEDO=vec3(1.0,0.0,0.0);
#else
    ALBEDO=vec3(0.0,1.0,0.0);
#endif
}

A.gdshader

//This would do blend_mix where the base shader has 80% opacity and the shader overriding has 20% opacity
//#overlay 80 "base.gdshader"

#define BASE_GDSHADER

//50% opacity
#overlay "base.gdshader"

void fragment() {
      ALBEDO=vec3(1.0,1.0,0.0);
}

Example 2:

base.gdshader

void fragment() {
#ifdef BASE_GDSHADER
    ALBEDO=vec3(1.0,0.0,0.0);
#else
    ALBEDO=vec3(0.0,1.0,0.0);
#endif
}

A.gdshader

void fragment() {
      ALBEDO=vec3(0.0,0.0,1.0);
}

B.gdshader

#overlay "base.gdshader"
#overlay "A.gdshader"

void fragment() {
      ALBEDO=vec3(1.0,0.0,1.0);
}

turns to

void fragment() {
      ALBEDO = vec3(0.0,1.0,0.0)*.5+(vec3(0.0,0.0,1.0)*.5+(vec3(1.0,0.0,1.0))*.5)*.5;
}

If this enhancement will not be used often, can it be worked around with a few lines of script?

You'd have to copy the whole shaders inherited.

Is there a reason why this should be core and not an add-on in the asset library?

N/A

AThousandShips commented 2 weeks ago

The same arguments in https://github.com/godotengine/godot-proposals/issues/9622#issuecomment-2081657265 apply to this as to:

AThousandShips commented 2 weeks ago

I'd say that this is only relevant or useful when you're reusing the same thing more than a few times, otherwise you can just write specific shaders for those cases, and in those cases putting the code you're reusing into an include and then doing the specific application, merging, etc. in your specific shader is the way to solve this, and it does so without complicating things further with the shader language, and maintaining compatibility and usability and workflows

This is, AFAIK, how it's solved generally

I repeat my question from the other proposal: Is this done in any other shading language out there? In other engines? Or are they using other ways to accomplish this, like composition and includes. I suspect that they do in fact use that to solve things generally

It's important to keep in mind that pretty much every idea has been thought about, at least for things that already exist, so if no one is using a particular solution for a particular problem it's often an indication not of that the idea is revolutionary, but that the idea might not be useful, that's not always true, but it's always useful to look to how others solve particular problems when working out how to solve something