bevy_march/
lib.rs

1use std::marker::PhantomData;
2
3use bevy::{
4    asset::embedded_asset,
5    prelude::*,
6    render::{
7        render_resource::{encase::internal::WriteInto, *},
8        RenderApp,
9    },
10};
11use bevy_prototype_sdf::Sdf3d;
12
13// TODO: We only need to re-render if any of the buffers change, the light changes, or the camera is moved
14// TODO: Document everything and warn(missing_docs)
15
16mod buffers;
17use buffers::BufferPlugin;
18
19mod cone_pass;
20use cone_pass::ConePassPlugin;
21pub use cone_pass::MarcherConeTexture;
22
23mod main_pass;
24pub use main_pass::MarcherMainTextures;
25use main_pass::{MainPassPlugin, MainPassShader};
26
27mod shadow_pass;
28pub use shadow_pass::{MarcherShadowSettings, MarcherShadowTextures};
29
30mod settings;
31pub use settings::MarcherSettings;
32use settings::SettingsPlugin;
33
34mod writeback;
35use writeback::WritebackPlugin;
36
37pub trait MarcherMaterial: Asset + ShaderType + WriteInto + std::fmt::Debug + Clone {}
38
39pub struct RayMarcherPlugin<Material: MarcherMaterial> {
40    shader: Handle<Shader>,
41    _phantom: PhantomData<Material>,
42}
43
44impl<Material: MarcherMaterial> RayMarcherPlugin<Material> {
45    pub fn new(shader: Handle<Shader>) -> Self {
46        Self {
47            shader,
48            _phantom: PhantomData,
49        }
50    }
51}
52
53impl<Material: MarcherMaterial> Plugin for RayMarcherPlugin<Material> {
54    fn build(&self, app: &mut App) {
55        app.add_plugins(bevy_prototype_sdf::SdfPlugin);
56        embedded_asset!(app, "sdf_marcher.wgsl");
57        std::mem::forget(
58            app.world()
59                .resource::<AssetServer>()
60                .load::<Shader>("embedded://bevy_march/sdf_marcher.wgsl"),
61        );
62
63        app.init_asset::<Material>()
64            .add_plugins((
65                BufferPlugin::<Material>::default(),
66                ConePassPlugin,
67                MainPassPlugin,
68                SettingsPlugin,
69                WritebackPlugin,
70            ))
71            .sub_app_mut(RenderApp)
72            .insert_resource(MainPassShader(self.shader.clone()));
73    }
74}
75
76const WORKGROUP_SIZE: u32 = 8;
77const CONE_SIZE: u32 = 8;
78
79/// An SDF instance to be rendered
80#[derive(Component)]
81pub struct RenderedSdf<Material: MarcherMaterial> {
82    /// The SDF handle
83    pub sdf: Handle<Sdf3d>,
84    /// The material handle
85    pub material: Handle<Material>,
86}
87
88#[derive(Component, Deref, DerefMut)]
89pub struct MarcherScale(pub u8);
90
91impl Default for MarcherScale {
92    fn default() -> Self {
93        Self(1)
94    }
95}