Make extending `StandardMaterial` wgsl shader easier for common cases
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Preambula
Beforehand I just want to note that this is not a critic of bevy's approach, I'd just like to see some ease-of-use improvements.
I will be talking only about `StandardMaterial` because it is the most widely used and I constantly see a need to extend it (might be a problem with me) while retaining most of its functionality.
I also don't know if Naga will support this or if it is even Naga's responsibility. This is only a general approach that I'd like to see.
## What problem does this solve or what need does it fill?
In short, all code written and maintained by the user should be minimized as much as possible. Ideally, only the custom logic should be written, without **_any_** other noise.
Currently extending standard material shader requires tons of boilerplate code and copy-pasting from examples even for very **_trivial_** modifications. IMHO I'm not even sure if someone can just write it all by hand without examples/sources. No proper IDE support (code completion, suggestions, etc.) when working with `wgsl+imports` exacerbates this problem even more.
Lets see a simple comparison of the `bevy` example vs almost the same thing done in `godot`.
```
One thing to note here is that bevy example modifies color after the shading pass, while godot before.
Bevy provides more customizability this way but my use-cases constantly demand specifically pre-shading customizations (godot approach).
In any case my proposal allows both case to be handled.
```

```
Red marks all of the code that I consider boilerplate.
```
Now let see how to do the "same" thing in `godot`:
```gd
shader_type spatial;
uniform int quantize_steps = 5;
void fragment() {
float steps = float(quantize_steps);
ALBEDO = vec3(round(UV * steps) / steps, 0.0);
}
```
Amount of the code difference is just staggering.
Bevy's implementation doesn't even fit on my screen and it is hard to see the actual custom logic. Not to mention amount of errors developers can make and amount of shaders you need to update in case of internal changes.
## What solution would you like?
What I'd suggest is instead of "custom logic wraps internal" we add "internal logic wraps custom".
What do I meen by this?
Currently shader that we load is the actual user's shader. Because of this all imports, shading and other stuff needs to be handled by the user.
Instead I suggest for standard material shader to just allow some kind of "hooks" to customize its behaviour, so we can write it like:
```wgsl
@group(2) @binding(100)
var quantize_steps: u32;
fn fragment_before_shading(in: PbrInput) -> PbrInput {
let steps = f32(quantize_steps);
in.material.base_color = vec4(round(in.uv * steps) / steps, 0.0, 1.0);
return in;
}
```
## What alternative(s) have you considered?
The only alternative so far is to write all of the above boilerplate code. I didn't find any easier way so far.
## Additional context
I'm not proposing to remove current `ExtendedMaterial`, but instead to add special "hooks" to shaders.
Same problem happens when extending `vertex` stage. I'm not even talking when we need to add a single custom vertex attribute...
Contributor guide
Assessment
This issue has not been assessed yet.