diff --git a/content/news/2023-10-21-bevy-0.12/index.md b/content/news/2023-10-21-bevy-0.12/index.md index 840eaa010f..6f3e8a592d 100644 --- a/content/news/2023-10-21-bevy-0.12/index.md +++ b/content/news/2023-10-21-bevy-0.12/index.md @@ -135,6 +135,89 @@ bevy_pbr::pbr_functions::pbr() Rusty Imports remove a number of "API weirdness" gotchas from the old system and expand the capabilities of the import system. And by reusing Rust syntax and semantics, we remove the need for Bevy users to learn a new system. +## Material Extensions + +
authors: @robtfm
+ +Bevy has a powerful shader import system, allowing modular (and granular) shader code reuse. In previous versions of Bevy, this meant that in theory, you could import Bevy's PBR shader logic and use it in your own shaders. However in practice this was challenging, as you had to re-wire everything up yourself, which required intimate knowledge of the base material. For complicated materials like Bevy's PBR [`StandardMaterial`], this was full of boilerplate, resulted in code duplication, and was prone to errors. + +In **Bevy 0.12**, we've built a **Material Extensions** system, which enables defining new materials that build on existing materials: + +![material extension](material_extension.png) + +This is accomplished via a new [`ExtendedMaterial`] type: + +```rust +app.add_plugin( + MaterialPlugin::>::default() +); + +#[derive(Asset, AsBindGroup, TypePath, Debug, Clone)] +struct QuantizedMaterial { + // Start at a high binding number to ensure bindings don't conflict + // with the base material + #[uniform(100)] + quantize_steps: u32, +} + +impl MaterialExtension for QuantizedMaterial { + fn fragment_shader() -> ShaderRef { + "quantized_material.wgsl".into() + } +} + +let material = ExtendedMaterial { + base: StandardMaterial::from(Color::rgb(0.1, 0.1, 0.8)), + extension: QuantizedMaterial { quantize_steps: 2 }, +}; +``` + +We also paired this with some [`StandardMaterial`] shader refactors to make it much easier to pick and choose which parts you want: + +```rust +// quantized_material.wgsl + +struct QuantizedMaterial { + quantize_steps: u32, +} + +@group(1) @binding(100) +var my_extended_material: QuantizedMaterial; + +@fragment +fn fragment( + input: VertexOutput, + @builtin(front_facing) is_front: bool, +) -> FragmentOutput { + // Generate a PbrInput struct from the StandardMaterial bindings + var pbr_input = pbr_input_from_standard_material(input, is_front); + + // Alpha discard + pbr_input.material.base_color = alpha_discard( + pbr_input.material, + pbr_input.material.base_color + ); + + var out: FragmentOutput; + + // Apply lighting + out.color = apply_pbr_lighting(pbr_input); + + // Our "quantize" effect + out.color = vec4(vec4(out.color * f32(my_extended_material.quantize_steps))) / f32(my_extended_material.quantize_steps); + + // Apply in-shader post processing. + // Ex: fog, alpha-premultiply, etc. For non-hdr cameras: tonemapping and debanding + out.color = main_pass_post_lighting_processing(pbr_input, out.color); + + return out; +} +``` + +This _vastly_ simplifies writing custom PBR materials, making it accessible to pretty much everyone! + +[`ExtendedMaterial`]: https://dev-docs.bevyengine.org/bevy/pbr/struct.ExtendedMaterial.html + ## Deferred Rendering
authors: @DGriffin91
diff --git a/content/news/2023-10-21-bevy-0.12/material_extension.png b/content/news/2023-10-21-bevy-0.12/material_extension.png new file mode 100644 index 0000000000..f848d58667 Binary files /dev/null and b/content/news/2023-10-21-bevy-0.12/material_extension.png differ