mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 22:18:33 +00:00
# Objective The documentation for camera priority is very confusing at the moment, it requires a bit of "double negative" kind of thinking. # Solution Flipping the wording on the documentation to reflect more common usecases like having an overlay camera and also renaming it to "order", since priority implies that it will override the other camera rather than have both run.
185 lines
5.9 KiB
Rust
185 lines
5.9 KiB
Rust
//! A custom post processing effect, using two cameras, with one reusing the render texture of the first one.
|
|
//! Here a chromatic aberration is applied to a 3d scene containing a rotating cube.
|
|
//! This example is useful to implement your own post-processing effect such as
|
|
//! edge detection, blur, pixelization, vignette... and countless others.
|
|
|
|
use bevy::{
|
|
core_pipeline::clear_color::ClearColorConfig,
|
|
prelude::*,
|
|
reflect::TypeUuid,
|
|
render::{
|
|
camera::RenderTarget,
|
|
render_resource::{
|
|
AsBindGroup, Extent3d, ShaderRef, TextureDescriptor, TextureDimension, TextureFormat,
|
|
TextureUsages,
|
|
},
|
|
texture::BevyDefault,
|
|
view::RenderLayers,
|
|
},
|
|
sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle},
|
|
};
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins)
|
|
.add_plugin(Material2dPlugin::<PostProcessingMaterial>::default())
|
|
.add_startup_system(setup)
|
|
.add_system(main_camera_cube_rotator_system)
|
|
.run();
|
|
}
|
|
|
|
/// Marks the first camera cube (rendered to a texture.)
|
|
#[derive(Component)]
|
|
struct MainCube;
|
|
|
|
fn setup(
|
|
mut commands: Commands,
|
|
mut windows: ResMut<Windows>,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut post_processing_materials: ResMut<Assets<PostProcessingMaterial>>,
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
mut images: ResMut<Assets<Image>>,
|
|
) {
|
|
let window = windows.primary_mut();
|
|
let size = Extent3d {
|
|
width: window.physical_width(),
|
|
height: window.physical_height(),
|
|
..default()
|
|
};
|
|
|
|
// This is the texture that will be rendered to.
|
|
let mut image = Image {
|
|
texture_descriptor: TextureDescriptor {
|
|
label: None,
|
|
size,
|
|
dimension: TextureDimension::D2,
|
|
format: TextureFormat::bevy_default(),
|
|
mip_level_count: 1,
|
|
sample_count: 1,
|
|
usage: TextureUsages::TEXTURE_BINDING
|
|
| TextureUsages::COPY_DST
|
|
| TextureUsages::RENDER_ATTACHMENT,
|
|
},
|
|
..default()
|
|
};
|
|
|
|
// fill image.data with zeroes
|
|
image.resize(size);
|
|
|
|
let image_handle = images.add(image);
|
|
|
|
let cube_handle = meshes.add(Mesh::from(shape::Cube { size: 4.0 }));
|
|
let cube_material_handle = materials.add(StandardMaterial {
|
|
base_color: Color::rgb(0.8, 0.7, 0.6),
|
|
reflectance: 0.02,
|
|
unlit: false,
|
|
..default()
|
|
});
|
|
|
|
// The cube that will be rendered to the texture.
|
|
commands.spawn((
|
|
PbrBundle {
|
|
mesh: cube_handle,
|
|
material: cube_material_handle,
|
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
|
|
..default()
|
|
},
|
|
MainCube,
|
|
));
|
|
|
|
// Light
|
|
// NOTE: Currently lights are ignoring render layers - see https://github.com/bevyengine/bevy/issues/3462
|
|
commands.spawn(PointLightBundle {
|
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
|
|
..default()
|
|
});
|
|
|
|
// Main camera, first to render
|
|
commands.spawn((
|
|
Camera3dBundle {
|
|
camera_3d: Camera3d {
|
|
clear_color: ClearColorConfig::Custom(Color::WHITE),
|
|
..default()
|
|
},
|
|
camera: Camera {
|
|
target: RenderTarget::Image(image_handle.clone()),
|
|
..default()
|
|
},
|
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0))
|
|
.looking_at(Vec3::default(), Vec3::Y),
|
|
..default()
|
|
},
|
|
// Disable UI rendering for the first pass camera. This prevents double rendering of UI at
|
|
// the cost of rendering the UI without any post processing effects.
|
|
UiCameraConfig { show_ui: false },
|
|
));
|
|
|
|
// This specifies the layer used for the post processing camera, which will be attached to the post processing camera and 2d quad.
|
|
let post_processing_pass_layer = RenderLayers::layer((RenderLayers::TOTAL_LAYERS - 1) as u8);
|
|
|
|
let quad_handle = meshes.add(Mesh::from(shape::Quad::new(Vec2::new(
|
|
size.width as f32,
|
|
size.height as f32,
|
|
))));
|
|
|
|
// This material has the texture that has been rendered.
|
|
let material_handle = post_processing_materials.add(PostProcessingMaterial {
|
|
source_image: image_handle,
|
|
});
|
|
|
|
// Post processing 2d quad, with material using the render texture done by the main camera, with a custom shader.
|
|
commands.spawn((
|
|
MaterialMesh2dBundle {
|
|
mesh: quad_handle.into(),
|
|
material: material_handle,
|
|
transform: Transform {
|
|
translation: Vec3::new(0.0, 0.0, 1.5),
|
|
..default()
|
|
},
|
|
..default()
|
|
},
|
|
post_processing_pass_layer,
|
|
));
|
|
|
|
// The post-processing pass camera.
|
|
commands.spawn((
|
|
Camera2dBundle {
|
|
camera: Camera {
|
|
// renders after the first main camera which has default value: 0.
|
|
order: 1,
|
|
..default()
|
|
},
|
|
..Camera2dBundle::default()
|
|
},
|
|
post_processing_pass_layer,
|
|
));
|
|
}
|
|
|
|
/// Rotates the cube rendered by the main camera
|
|
fn main_camera_cube_rotator_system(
|
|
time: Res<Time>,
|
|
mut query: Query<&mut Transform, With<MainCube>>,
|
|
) {
|
|
for mut transform in &mut query {
|
|
transform.rotate_x(0.55 * time.delta_seconds());
|
|
transform.rotate_z(0.15 * time.delta_seconds());
|
|
}
|
|
}
|
|
|
|
// Region below declares of the custom material handling post processing effect
|
|
|
|
/// Our custom post processing material
|
|
#[derive(AsBindGroup, TypeUuid, Clone)]
|
|
#[uuid = "bc2f08eb-a0fb-43f1-a908-54871ea597d5"]
|
|
struct PostProcessingMaterial {
|
|
/// In this example, this image will be the result of the main camera.
|
|
#[texture(0)]
|
|
#[sampler(1)]
|
|
source_image: Handle<Image>,
|
|
}
|
|
|
|
impl Material2d for PostProcessingMaterial {
|
|
fn fragment_shader() -> ShaderRef {
|
|
"shaders/custom_material_chromatic_aberration.wgsl".into()
|
|
}
|
|
}
|