docs/bevy/examples/camera/custom_projection.rs 2.5 K · 84 lines · raw · history

1 //! Demonstrates how to define and use custom camera projections.
2
3 use bevy::camera::CameraProjection;
4 use bevy::prelude::*;
5
6 fn main() {
7 App::new()
8 .add_plugins(DefaultPlugins)
9 .add_systems(Startup, setup)
10 .run();
11 }
12
13 /// Like a perspective projection, but the vanishing point is not centered.
14 #[derive(Debug, Clone)]
15 struct ObliquePerspectiveProjection {
16 horizontal_obliqueness: f32,
17 vertical_obliqueness: f32,
18 perspective: PerspectiveProjection,
19 }
20
21 /// Implement the [`CameraProjection`] trait for our custom projection:
22 impl CameraProjection for ObliquePerspectiveProjection {
23 fn get_clip_from_view(&self) -> Mat4 {
24 let mut mat = self.perspective.get_clip_from_view();
25 mat.col_mut(2)[0] = self.horizontal_obliqueness;
26 mat.col_mut(2)[1] = self.vertical_obliqueness;
27 mat
28 }
29
30 fn get_clip_from_view_for_sub(&self, sub_view: &bevy::camera::SubCameraView) -> Mat4 {
31 let mut mat = self.perspective.get_clip_from_view_for_sub(sub_view);
32 mat.col_mut(2)[0] = self.horizontal_obliqueness;
33 mat.col_mut(2)[1] = self.vertical_obliqueness;
34 mat
35 }
36
37 fn update(&mut self, width: f32, height: f32) {
38 self.perspective.update(width, height);
39 }
40
41 fn far(&self) -> f32 {
42 self.perspective.far
43 }
44
45 fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8] {
46 self.perspective.get_frustum_corners(z_near, z_far)
47 }
48 }
49
50 fn setup(
51 mut commands: Commands,
52 mut meshes: ResMut<Assets<Mesh>>,
53 mut materials: ResMut<Assets<StandardMaterial>>,
54 ) {
55 commands.spawn((
56 Camera3d::default(),
57 // Use our custom projection:
58 Projection::custom(ObliquePerspectiveProjection {
59 horizontal_obliqueness: 0.2,
60 vertical_obliqueness: 0.6,
61 perspective: PerspectiveProjection::default(),
62 }),
63 Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
64 ));
65
66 // Scene setup
67 commands.spawn((
68 Mesh3d(meshes.add(Circle::new(4.0))),
69 MeshMaterial3d(materials.add(Color::WHITE)),
70 Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
71 ));
72 commands.spawn((
73 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
74 MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
75 Transform::from_xyz(0.0, 0.5, 0.0),
76 ));
77 commands.spawn((
78 PointLight {
79 shadow_maps_enabled: true,
80 ..default()
81 },
82 Transform::from_xyz(4.0, 8.0, 4.0),
83 ));
84 }