From c676907f6540de4709c6ac204fb1c90e87217b6e Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sun, 11 Jun 2023 16:11:59 -0500 Subject: [PATCH] adding a solid shader --- assets/shaders/solid.frag | 19 +++++++++++++++ src/main.rs | 51 ++++++++++++++++++++++----------------- src/materials.rs | 3 +++ src/materials/solid.rs | 34 ++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 assets/shaders/solid.frag create mode 100644 src/materials.rs create mode 100644 src/materials/solid.rs diff --git a/assets/shaders/solid.frag b/assets/shaders/solid.frag new file mode 100644 index 0000000..54b61cf --- /dev/null +++ b/assets/shaders/solid.frag @@ -0,0 +1,19 @@ +#version 450 + +// I don't know what these inputs actually are, but the shader doesn't compile +// if we don't actually consume them. It doesn't seem to matter what type I use +// to describe each field, so I just picked vec2. +// +// I think these are probably declared in the derived AsBindGroup trait that +// binds data between the Rust application and the shader? +layout(location = 0) in vec2 _; +layout(location = 1) in vec2 _; +layout(location = 2) in vec2 _; + +layout(location = 0) out vec4 o_Target; + +void main() { + o_Target = vec4(1.0, 0.0, 1.0, 1.0); +} + +// vim: set ft=glsl: diff --git a/src/main.rs b/src/main.rs index db0fd40..250e3e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +mod materials; + use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, @@ -16,26 +18,34 @@ fn startup( mut meshes: ResMut>, mut materials: ResMut>, mut tiled_materials: ResMut>, + mut solid_materials: ResMut>, ) { - // - let texture = assets.load("grid-texture.png"); - - // This is a solid texture - let material = materials.add(StandardMaterial { - base_color_texture: Some(texture.clone()), - alpha_mode: AlphaMode::Opaque, - unlit: true, - ..default() + let grid_texture = assets.load("grid-texture.png"); + + let grid_material = tiled_materials.add(RepeatMaterial { + color: Color::BLUE, + color_texture: Some(grid_texture.clone()), + alpha_mode: AlphaMode::Blend, }); - // ground plane - commands.spawn(PbrBundle { + // Standard material with opaque grid texture (stretched) + // let material = materials.add(StandardMaterial { + // base_color_texture: Some(grid_texture.clone()), + // alpha_mode: AlphaMode::Opaque, + // unlit: true, + // ..default() + // }); + + let solid_material = solid_materials.add(materials::SolidMaterial{}); + + // a ground plane + commands.spawn(MaterialMeshBundle { mesh: meshes.add(shape::Plane::from_size(5.0).into()), - material, + material: solid_material, ..default() }); - // a subject cube + // a solid colored cube commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), @@ -43,27 +53,23 @@ fn startup( ..default() }); - let grid_tile = tiled_materials.add(RepeatMaterial { - color: Color::BLUE, - color_texture: Some(texture.clone()), - alpha_mode: AlphaMode::Blend, - }); - + // a unit cube using our shader commands.spawn(MaterialMeshBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), - material: grid_tile.clone(), + material: grid_material.clone(), transform: Transform::from_xyz(2.0, 0.5, 0.0), ..default() }); + // a doubly large cube using our shader to test texture tiling (not yet working!!!) commands.spawn(MaterialMeshBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 2.0 })), - material: grid_tile.clone(), + material: grid_material.clone(), transform: Transform::from_xyz(-2.0, 1.0, 0.0), ..default() }); - // single light source + // a single light source commands.spawn(PointLightBundle { point_light: PointLight { intensity: 1500.0, @@ -128,6 +134,7 @@ fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugin(MaterialPlugin::::default()) + .add_plugin(MaterialPlugin::::default()) .add_startup_system(startup) .run(); } diff --git a/src/materials.rs b/src/materials.rs new file mode 100644 index 0000000..4f42d1f --- /dev/null +++ b/src/materials.rs @@ -0,0 +1,3 @@ +mod solid; + +pub use solid::SolidMaterial; diff --git a/src/materials/solid.rs b/src/materials/solid.rs new file mode 100644 index 0000000..d3b5687 --- /dev/null +++ b/src/materials/solid.rs @@ -0,0 +1,34 @@ +use bevy::{ + pbr::{Material, MaterialPipeline, MaterialPipelineKey}, + reflect::TypeUuid, + render::{ + mesh::MeshVertexBufferLayout, + render_resource::{ + AsBindGroup, RenderPipelineDescriptor, ShaderRef, SpecializedMeshPipelineError, + }, + }, +}; + +#[derive(AsBindGroup, Clone, TypeUuid)] +#[uuid = "6dd176cf-c8c2-4cc5-8163-0df87c53139a"] +pub struct SolidMaterial {} + +impl Material for SolidMaterial { + fn fragment_shader() -> ShaderRef { + "shaders/solid.frag".into() + } + + fn specialize( + _: &MaterialPipeline, + descriptor: &mut RenderPipelineDescriptor, + _: &MeshVertexBufferLayout, + _: MaterialPipelineKey, + ) -> Result<(), SpecializedMeshPipelineError> { + let mut frag = descriptor + .fragment + .as_mut() + .expect("should have a fragment entry point here"); + frag.entry_point = "main".into(); + Ok(()) + } +}