godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Visual Shaders: Move all output nodes into a single shader graph #10520

Open DrCanvas opened 3 weeks ago

DrCanvas commented 3 weeks ago

Describe the project you are working on

VFX, Visual Shaders (e.g. Canvas, Spatial, Particles).

Describe the problem or limitation you are having in your project

Switching between shader graphs (i.e. vertex, fragment, light) is very annoying. If you're working with two functions (e.g. vertex and fragment), you'll have to switch back and forth a lot. It's pretty confusing especially with very complex shaders.

Text shaders are much easier to work with since all the code is in one place. I think we should get rid of the individual graphs and move everything into a single graph.

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

This way the visual shader workflow will become more straightforward and cohesive.

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

This is a mockup of how it could be done: Before After
before_screen after_screen1
before_outputs00 add_outputs00

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

No.

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

This redesign changes the workflow with visual shaders. It can't be implemented as an addon.

tetrapod00 commented 3 weeks ago

One complication with a system like this is that many Input nodes share names between vertex(), fragment(), and light(). I remember this was a problem using other visual shader systems (Unity ShaderGraph or Unreal Blueprints). You could also for example use a single uniform/parameter for the same calculation that feeds into both vertex() and fragment(), but would need two copies of the math because one calculation is per-vertex and the other is per-fragment. The current design with multiple separate pages makes this a lot more clear than single-page designs.

You can solve these problems, of course. You could have a VertexInput node that replaces the current Input node, or you could put all the inputs in a single list and differentiate them on the fly. But they do have to be considered.

I'm personally neutral on single-page vs multiple-page even leaving that aside.

As an example of the kinds of problems that need consideration, this is a Unity ShaderGraph with a single Vector3 parameter. You can connect a single parameter (or input) to multiple outputs in fragment(), but you need a separate copy of the parameter to connect to vertex(). You can't connect single node to both vertex() and fragment() outputs.

Unity_TzLEr5oAvN

DrCanvas commented 2 weeks ago

You could have a VertexInput node that replaces the current Input node

I think simply switching the input node modes will do the trick. But there might be other options.

Details

![input_node](https://github.com/user-attachments/assets/39e6587c-ed2c-46f0-bd4d-76f946e32797)

As an example of the kinds of problems that need consideration, this is a Unity ShaderGraph with a single Vector3 parameter. You can connect a single parameter (or input) to multiple outputs in fragment(), but you need a separate copy of the parameter to connect to vertex(). You can't connect single node to both vertex() and fragment() outputs.

The problem in that example has been discussed many times before. It's about how GPUs and shaders work in general. You can't send data from fragment to vertex shader. Only in reverse. That's what varyings are for ( custom interpolator in Unity). My proposal won't solve that problem. But it won't make it worse than it is:

Details

![varyings](https://github.com/user-attachments/assets/d1f404bd-6959-4cf9-9e91-19d89d31239d)

Duplicates are not a real problem in this case. In text shaders we always make copies of variables when we need to access them. Unity's shader graph looks similar to text shaders in some way:

duplicates

tetrapod00 commented 2 weeks ago

Looks like you've considered all the cases pretty well, then. I just wanted to bring that up as a case where multiple-page shaders do have an advantage - they make it very clear that vertex() and fragment() are different functions that need a varying to pass data. I guess single page makes it clear in a different way, the first time that you are surprised when you can't connect a node and you research why that is.

If you think the other advantages of single-page outweigh that then I'm in support of single-page.