refactor camera and mandelbulb to separate modules

This commit is contained in:
TÁNCZOS Vilmos Zsombor 2025-05-31 23:05:05 +02:00
parent c8d45d4fc1
commit 6050607994
4 changed files with 103 additions and 72 deletions

12
src/camera.rs Normal file
View file

@ -0,0 +1,12 @@
use bevy::prelude::*;
pub fn plugin(app: &mut App) {
app.add_systems(Startup, setup);
}
fn setup(mut commands: Commands) {
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}

View file

@ -1,32 +1,27 @@
use bevy::{
color::palettes::css::RED,
pbr::{ExtendedMaterial, MaterialExtension},
prelude::*,
render::{render_resource::*, storage::ShaderStorageBuffer},
};
use bevy::{color::palettes::css::RED, prelude::*, render::storage::ShaderStorageBuffer};
use mandelbulb::{MandelbulbExtension, MandelbulbMaterial, MandelbulbStorage};
const SHADER_ASSET_PATH: &str = "shaders/material.wgsl";
type VoluMaterial = ExtendedMaterial<StandardMaterial, VoluExtension>;
mod camera;
mod mandelbulb;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MaterialPlugin::<VoluMaterial>::default())
.add_plugins((camera::plugin, mandelbulb::plugin))
.add_systems(Startup, setup)
.add_systems(Update, (rotate_things, update_volu_material))
.add_systems(Update, (rotate_things,))
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<VoluMaterial>>,
mut materials: ResMut<Assets<MandelbulbMaterial>>,
mut buffers: ResMut<Assets<ShaderStorageBuffer>>,
) {
let transform = Transform::from_xyz(0.0, 0.0, 0.0);
let storage = buffers.add(ShaderStorageBuffer::from(VoluStorage {
let storage = buffers.add(ShaderStorageBuffer::from(MandelbulbStorage {
mesh_translation: transform.translation,
sphere_radius: 1.0,
color: Vec4::default(),
@ -37,14 +32,14 @@ fn setup(
commands.spawn((
Mesh3d(meshes.add(Cuboid::new(2.0, 2.0, 2.0))),
MeshMaterial3d(materials.add(ExtendedMaterial {
base: StandardMaterial {
MeshMaterial3d(materials.add(MandelbulbExtension::create_material(
StandardMaterial {
base_color: RED.into(),
alpha_mode: AlphaMode::Blend,
..default()
},
extension: VoluExtension { storage },
})),
storage,
))),
transform,
Rotate,
));
@ -54,11 +49,6 @@ fn setup(
Transform::from_xyz(1.0, 1.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y),
Rotate,
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}
#[derive(Component)]
@ -69,53 +59,3 @@ fn rotate_things(mut q: Query<&mut Transform, With<Rotate>>, time: Res<Time>) {
t.rotate_y(time.delta_secs());
}
}
fn update_volu_material(
q: Query<(&Transform, &MeshMaterial3d<VoluMaterial>), Changed<Transform>>,
mut volu_materials: ResMut<Assets<VoluMaterial>>,
mut buffers: ResMut<Assets<ShaderStorageBuffer>>,
time: Res<Time>,
) {
for (transform, material) in q.iter() {
let volu_material = volu_materials.get_mut(material.0.id()).unwrap();
let buffer = buffers
.get_mut(volu_material.extension.storage.id())
.unwrap();
let elapsed = time.elapsed_secs_wrapped();
let volu_storage = VoluStorage {
mesh_translation: transform.translation,
sphere_radius: (elapsed.sin() + 3.) / 4.,
color: vec4((elapsed.sin() + 1.) / 2., 0.0, 0.0, 1.0),
model_inverse: transform.compute_matrix(),
power: 8.0,
iterations: 32,
};
buffer.set_data(volu_storage);
}
}
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
struct VoluExtension {
#[storage(100, read_only)]
storage: Handle<ShaderStorageBuffer>,
}
impl MaterialExtension for VoluExtension {
fn fragment_shader() -> ShaderRef {
SHADER_ASSET_PATH.into()
}
}
#[derive(ShaderType, Clone, Default, Debug)]
pub struct VoluStorage {
mesh_translation: Vec3,
sphere_radius: f32,
color: Vec4,
model_inverse: Mat4,
power: f32,
iterations: i32,
}

79
src/mandelbulb.rs Normal file
View file

@ -0,0 +1,79 @@
use bevy::{
pbr::{ExtendedMaterial, MaterialExtension},
prelude::*,
render::{
render_resource::{AsBindGroup, ShaderRef, ShaderType},
storage::ShaderStorageBuffer,
},
};
pub type MandelbulbMaterial = ExtendedMaterial<StandardMaterial, MandelbulbExtension>;
const SHADER_ASSET_PATH: &str = "shaders/mandelbulb.wgsl";
pub fn plugin(app: &mut App) {
app.add_plugins(MaterialPlugin::<MandelbulbMaterial>::default())
.add_systems(Update, update_volu_material);
}
fn update_volu_material(
q: Query<(&Transform, &MeshMaterial3d<MandelbulbMaterial>)>,
mut volu_materials: ResMut<Assets<MandelbulbMaterial>>,
mut buffers: ResMut<Assets<ShaderStorageBuffer>>,
time: Res<Time>,
) {
for (transform, material) in q.iter() {
let volu_material = volu_materials.get_mut(material.0.id()).unwrap();
let buffer = buffers
.get_mut(volu_material.extension.storage.id())
.unwrap();
let elapsed = time.elapsed_secs_wrapped();
let volu_storage = MandelbulbStorage {
mesh_translation: transform.translation,
sphere_radius: (elapsed.sin() + 3.) / 4.,
color: vec4((elapsed.sin() + 1.) / 2., 0.0, 0.0, 1.0),
model_inverse: transform.compute_matrix(),
power: 8.0,
iterations: 32,
};
buffer.set_data(volu_storage);
}
}
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
pub struct MandelbulbExtension {
#[storage(100, read_only)]
pub storage: Handle<ShaderStorageBuffer>,
}
impl MaterialExtension for MandelbulbExtension {
fn fragment_shader() -> ShaderRef {
SHADER_ASSET_PATH.into()
}
}
impl MandelbulbExtension {
pub fn create_material(
base: StandardMaterial,
storage: Handle<ShaderStorageBuffer>,
) -> MandelbulbMaterial {
MandelbulbMaterial {
base,
extension: Self { storage },
}
}
}
#[derive(ShaderType, Clone, Default, Debug)]
pub struct MandelbulbStorage {
pub mesh_translation: Vec3,
pub sphere_radius: f32,
pub color: Vec4,
pub model_inverse: Mat4,
pub power: f32,
pub iterations: i32,
}