Skip to content

Instantly share code, notes, and snippets.

@gbrls
Created January 3, 2025 04:36
Show Gist options
  • Select an option

  • Save gbrls/6d3096f7d905c6358dfb023ad96a51ff to your computer and use it in GitHub Desktop.

Select an option

Save gbrls/6d3096f7d905c6358dfb023ad96a51ff to your computer and use it in GitHub Desktop.
genuary-2025
//! Shows how to render to a texture. Useful for mirrors, UI, or exporting images.
use std::f32::consts::PI;
use bevy::{
prelude::*,
render::{
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
view::RenderLayers,
},
};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(WorldInspectorPlugin::new())
.add_systems(Startup, setup)
.add_systems(Update, cube_rotator_system)
.run();
}
// Marks the first pass cube (rendered to a texture.)
#[derive(Component)]
struct Cube {
depth: usize,
}
fn add_layer(
commands: &mut Commands,
images: &mut ResMut<Assets<Image>>,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
layer: usize,
previous: Option<Handle<Image>>,
) -> Handle<Image> {
let size = Extent3d {
width: 512,
height: 512,
..default()
};
let mut image = Image::new_fill(
size,
TextureDimension::D2,
&[0, 0, 0, 0],
TextureFormat::Bgra8UnormSrgb,
RenderAssetUsages::default(),
);
// You need to set these texture usage flags in order to use the image as a render target
// @@step a - setup image
image.texture_descriptor.usage =
TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST | TextureUsages::RENDER_ATTACHMENT;
let image_handle = images.add(image);
commands.spawn((
PointLight::default(),
Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
RenderLayers::layer(layer),
));
let layer_handle = RenderLayers::layer(layer);
let cube_size = 5.0;
let cube_handle = meshes.add(Cuboid::new(cube_size, cube_size, cube_size));
//let cube_handle = meshes.add(Cuboid::new(cube_size, cube_size, cube_size));
let projection = Projection::from(PerspectiveProjection {
fov: 30.0_f32.to_radians(),
..default()
});
let cam_pos = 14.0;
if layer == 0 {
commands.spawn((
Camera3d::default(),
Camera {
clear_color: Color::WHITE.into(),
..default()
},
projection,
Transform::from_xyz(0.0, 0.0, cam_pos).looking_at(Vec3::ZERO, Vec3::Y),
));
} else {
commands.spawn((
Camera3d::default(),
Camera {
target: image_handle.clone().into(),
clear_color: Color::WHITE.into(),
..default()
},
projection,
Transform::from_translation(Vec3::new(0.0, 0.0, cam_pos))
.looking_at(Vec3::ZERO, Vec3::Y),
layer_handle.clone(),
));
}
match previous {
Some(previous_cube_handle) => {
let cube_material_handle = materials.add(StandardMaterial {
base_color_texture: Some(previous_cube_handle),
base_color: Color::srgb(
0.0 + (layer as f32 * 0.01).fract().max(0.9).min(1.0),
1.0 - (layer as f32 * 0.01).fract().max(0.9).min(1.0),
(layer as f32 * 128.0).sin().abs().max(0.9).min(1.0),
)
.into(),
unlit: true,
..default()
});
commands.spawn((
Mesh3d(cube_handle),
MeshMaterial3d(cube_material_handle),
Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
Cube { depth: layer },
layer_handle.clone(),
));
}
None => {
let cube_material_handle = materials.add(StandardMaterial {
base_color: Color::srgb(
0.0 + (layer as f32 * 0.1),
1.0 - (layer as f32 * 0.1),
(layer as f32 * 128.0).sin().abs(),
)
.into(),
unlit: true,
..default()
});
commands.spawn((
Mesh3d(cube_handle),
MeshMaterial3d(cube_material_handle),
Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
Cube { depth: layer },
layer_handle.clone(),
));
}
}
image_handle
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut images: ResMut<Assets<Image>>,
) {
let image_handle = (1..32).fold(None, |acc, i| {
Some(add_layer(
&mut commands,
&mut images,
&mut meshes,
&mut materials,
i,
acc,
))
});
let _final_handle = add_layer(
&mut commands,
&mut images,
&mut meshes,
&mut materials,
0,
image_handle,
);
}
/// Rotates the outer cube (main pass)
fn cube_rotator_system(time: Res<Time>, mut query: Query<(&mut Transform, &Cube)>) {
let scale = 0.5;
for (mut transform, cube) in &mut query {
transform.rotate_x(1.0 * scale * time.delta_secs());
transform.rotate_y(0.11 * scale * time.delta_secs());
transform.rotate_z(0.017 * scale * time.delta_secs());
//if cube.depth % 2 == 0 {
// transform.rotate_x(1.0 * scale * time.delta_secs());
// transform.rotate_y(0.7 * scale * time.delta_secs());
//} else {
// transform.rotate_x(1.5 * scale * time.delta_secs());
// transform.rotate_z(1.3 * scale * time.delta_secs());
//}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment