diff --git a/Cargo.toml b/Cargo.toml index 70e9a4ca7cb15..5fe0449660fe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1767,6 +1767,17 @@ description = "A shader and a material that uses it" category = "Shaders" wasm = true +[[example]] +name = "shader_material_2d" +path = "examples/shader/shader_material_2d.rs" +doc-scrape-examples = true + +[package.metadata.example.shader_material_2d] +name = "Material" +description = "A shader and a material that uses it on a 2d mesh" +category = "Shaders" +wasm = true + [[example]] name = "extended_material" path = "examples/shader/extended_material.rs" diff --git a/assets/shaders/custom_material_2d.wgsl b/assets/shaders/custom_material_2d.wgsl new file mode 100644 index 0000000000000..98b85afd463b8 --- /dev/null +++ b/assets/shaders/custom_material_2d.wgsl @@ -0,0 +1,12 @@ +#import bevy_sprite::mesh2d_vertex_output::VertexOutput +// we can import items from shader modules in the assets folder with a quoted path +#import "shaders/custom_material_import.wgsl"::COLOR_MULTIPLIER + +@group(1) @binding(0) var material_color: vec4; +@group(1) @binding(1) var base_color_texture: texture_2d; +@group(1) @binding(2) var base_color_sampler: sampler; + +@fragment +fn fragment(mesh: VertexOutput) -> @location(0) vec4 { + return material_color * textureSample(base_color_texture, base_color_sampler, mesh.uv) * COLOR_MULTIPLIER; +} diff --git a/examples/README.md b/examples/README.md index db73c982f060c..70b1842643858 100644 --- a/examples/README.md +++ b/examples/README.md @@ -295,6 +295,7 @@ Example | Description [Extended Material](../examples/shader/extended_material.rs) | A custom shader that builds on the standard material [Instancing](../examples/shader/shader_instancing.rs) | A shader that renders a mesh multiple times in one draw call [Material](../examples/shader/shader_material.rs) | A shader and a material that uses it +[Material](../examples/shader/shader_material_2d.rs) | A shader and a material that uses it on a 2d mesh [Material - GLSL](../examples/shader/shader_material_glsl.rs) | A shader that uses the GLSL shading language [Material - Screenspace Texture](../examples/shader/shader_material_screenspace_texture.rs) | A shader that samples a texture with view-independent UV coordinates [Material Prepass](../examples/shader/shader_prepass.rs) | A shader that uses the various textures generated by the prepass diff --git a/examples/shader/shader_material_2d.rs b/examples/shader/shader_material_2d.rs new file mode 100644 index 0000000000000..351b5c5c8bf72 --- /dev/null +++ b/examples/shader/shader_material_2d.rs @@ -0,0 +1,58 @@ +//! A shader and a material that uses it. + +use bevy::{ + prelude::*, + reflect::TypePath, + render::render_resource::{AsBindGroup, ShaderRef}, + sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle}, +}; + +fn main() { + App::new() + .add_plugins(( + DefaultPlugins, + Material2dPlugin::::default(), + )) + .add_systems(Startup, setup) + .run(); +} + +// Setup a simple 2d scene +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, + asset_server: Res, +) { + // camera + commands.spawn(Camera2dBundle::default()); + + // quad + commands.spawn(MaterialMesh2dBundle { + mesh: meshes.add(Mesh::from(shape::Quad::default())).into(), + transform: Transform::default().with_scale(Vec3::splat(128.)), + material: materials.add(CustomMaterial { + color: Color::BLUE, + color_texture: Some(asset_server.load("branding/icon.png")), + }), + ..default() + }); +} + +// This is the struct that will be passed to your shader +#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)] +pub struct CustomMaterial { + #[uniform(0)] + color: Color, + #[texture(1)] + #[sampler(2)] + color_texture: Option>, +} + +/// The Material2d trait is very configurable, but comes with sensible defaults for all methods. +/// You only need to implement functions for features that need non-default behavior. See the Material2d api docs for details! +impl Material2d for CustomMaterial { + fn fragment_shader() -> ShaderRef { + "shaders/custom_material_2d.wgsl".into() + } +}