diff --git a/assets/shaders/material.wgsl b/assets/shaders/material.wgsl index a1ecdce..579a975 100644 --- a/assets/shaders/material.wgsl +++ b/assets/shaders/material.wgsl @@ -1,30 +1,46 @@ #import bevy_pbr::{ forward_io::{VertexOutput, FragmentOutput}, - pbr_fragment::pbr_input_from_standard_material, - pbr_functions::{alpha_discard, apply_pbr_lighting, main_pass_post_lighting_processing}, + mesh_view_bindings::view, } -struct MyExtendedMaterial { - quantize_steps: u32, +struct VoluMaterial { + mesh_translation: vec3, + sphere_radius: f32, + color: vec4, } @group(2) @binding(100) -var my_extended_material: MyExtendedMaterial; +var volu_material: VoluMaterial; + +fn raymarch_hit(position_: vec3, direction: vec3) -> bool { + var position = position_; + for (var i = 0; i < 200; i++) { + if sphere_hit(position) { + return true; + } + position += direction * 0.01; + } + return false; +} + +fn sphere_hit(p: vec3) -> bool { + return distance(p, volu_material.mesh_translation) < volu_material.sphere_radius; +} @fragment fn fragment( in: VertexOutput, @builtin(front_facing) is_front: bool, ) -> FragmentOutput { - var pbr_input = pbr_input_from_standard_material(in, is_front); - - pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color); + let view_direction = normalize(in.world_position.xyz - view.world_position); var out: FragmentOutput; - - out.color = apply_pbr_lighting(pbr_input); - - out.color = main_pass_post_lighting_processing(pbr_input, out.color); + if (raymarch_hit(in.world_position.xyz, view_direction)) { + out.color = volu_material.color; + } else { + out.color = vec4(1.0, 1.0, 1.0, 0.2); + } return out; } + diff --git a/src/main.rs b/src/main.rs index e3c92d7..a1a1980 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,53 +1,54 @@ -//! Demonstrates using a custom extension to the `StandardMaterial` to modify the results of the builtin pbr shader. - use bevy::{ - color::palettes::basic::RED, - pbr::{ExtendedMaterial, MaterialExtension, OpaqueRendererMethod}, + pbr::{ExtendedMaterial, MaterialExtension}, prelude::*, - render::render_resource::*, + render::{render_resource::*, storage::ShaderStorageBuffer}, }; -/// This example uses a shader source file from the assets subdirectory const SHADER_ASSET_PATH: &str = "shaders/material.wgsl"; +type VoluMaterial = ExtendedMaterial; + fn main() { App::new() .add_plugins(DefaultPlugins) - .add_plugins(MaterialPlugin::< - ExtendedMaterial, - >::default()) + .add_plugins(MaterialPlugin::::default()) .add_systems(Startup, setup) - .add_systems(Update, rotate_things) + .add_systems(Update, (rotate_things, update_volu_material)) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut>, - mut materials: ResMut>>, + mut materials: ResMut>, + mut buffers: ResMut>, ) { - // sphere + let transform = Transform::from_xyz(0.0, 0.0, 0.0); + + let storage = buffers.add(ShaderStorageBuffer::from(VoluStorage { + mesh_translation: transform.translation, + sphere_radius: 1.0, + color: Vec4::default(), + })); + commands.spawn(( - Mesh3d(meshes.add(Sphere::new(1.0))), + Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))), MeshMaterial3d(materials.add(ExtendedMaterial { base: StandardMaterial { - base_color: RED.into(), - opaque_render_method: OpaqueRendererMethod::Auto, - ..Default::default() + alpha_mode: AlphaMode::Blend, + ..default() }, - extension: MyExtension { quantize_steps: 3 }, + extension: VoluExtension { storage }, })), - Transform::from_xyz(0.0, 0.5, 0.0), - )); - - // light - commands.spawn(( - DirectionalLight::default(), - Transform::from_xyz(1.0, 1.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y), + transform, Rotate, )); - // camera + commands.spawn(( + DirectionalLight::default(), + Transform::from_xyz(1.0, 1.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y), + )); + commands.spawn(( Camera3d::default(), Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), @@ -63,14 +64,48 @@ fn rotate_things(mut q: Query<&mut Transform, With>, time: Res