Skip to content

Commit

Permalink
render: multi-window cameras ready to go!
Browse files Browse the repository at this point in the history
passes now bind camera buffers and cameras can now be assigned non-primary windows
  • Loading branch information
cart committed Jun 26, 2020
1 parent ca4726e commit 69925f0
Show file tree
Hide file tree
Showing 18 changed files with 238 additions and 159 deletions.
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ impl Default for MeshComponents {
dynamic_bindings: vec![
// Transform
DynamicBinding {
bind_group: 1,
bind_group: 2,
binding: 0,
},
// StandardMaterial_albedo
DynamicBinding {
bind_group: 2,
bind_group: 3,
binding: 0,
},
],
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_pbr/src/pipelines/forward/forward.frag
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj;
};

layout(set = 0, binding = 1) uniform Lights {
layout(set = 1, binding = 0) uniform Lights {
uvec4 NumLights;
Light SceneLights[MAX_LIGHTS];
};

layout(set = 2, binding = 0) uniform StandardMaterial_albedo {
layout(set = 3, binding = 0) uniform StandardMaterial_albedo {
vec4 Albedo;
};

# ifdef STANDARDMATERIAL_ALBEDO_TEXTURE
layout(set = 3, binding = 0) uniform texture2D StandardMaterial_albedo_texture;
layout(set = 3, binding = 1) uniform sampler StandardMaterial_albedo_texture_sampler;
layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture;
layout(set = 3, binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler;
# endif

void main() {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/pipelines/forward/forward.vert
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj;
};

layout(set = 1, binding = 0) uniform Transform {
layout(set = 2, binding = 0) uniform Transform {
mat4 Model;
};

Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_render/src/base_render_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct BaseRenderGraphConfig {

pub mod node {
pub const PRIMARY_SWAP_CHAIN: &str = "swapchain";
pub const CAMERA: &str = "camera";
pub const CAMERA3D: &str = "camera3d";
pub const CAMERA2D: &str = "camera2d";
pub const TEXTURE_COPY: &str = "texture_copy";
pub const MAIN_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
Expand All @@ -35,7 +35,7 @@ pub mod node {
}

pub mod camera {
pub const CAMERA: &str = "Camera";
pub const CAMERA3D: &str = "Camera3d";
pub const CAMERA2D: &str = "Camera2d";
}

Expand All @@ -62,7 +62,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self {
self.add_node(node::TEXTURE_COPY, TextureCopyNode::default());
if config.add_3d_camera {
self.add_system_node(node::CAMERA, CameraNode::new(camera::CAMERA));
self.add_system_node(node::CAMERA3D, CameraNode::new(camera::CAMERA3D));
}

if config.add_2d_camera {
Expand Down Expand Up @@ -117,7 +117,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
main_pass_node.use_default_clear_color(0);

if config.add_3d_camera {
main_pass_node.add_camera(camera::CAMERA);
main_pass_node.add_camera(camera::CAMERA3D);
}

if config.add_2d_camera {
Expand All @@ -135,7 +135,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
.unwrap();

if config.add_3d_camera {
self.add_node_edge(node::CAMERA, node::MAIN_PASS).unwrap();
self.add_node_edge(node::CAMERA3D, node::MAIN_PASS).unwrap();
}

if config.add_2d_camera {
Expand Down
65 changes: 49 additions & 16 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use crate::CameraProjection;
use bevy_app::{EventReader, Events};
use bevy_property::Properties;
use bevy_window::{WindowCreated, WindowResized, Windows};
use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows};
use glam::Mat4;
use legion::{prelude::*, storage::Component};

#[derive(Default, Debug, Properties)]
pub struct Camera {
pub projection_matrix: Mat4,
pub name: Option<String>,
#[property(ignore)]
pub window: WindowReference,
}

pub fn camera_system<T: CameraProjection + Component>() -> Box<dyn Schedulable> {
Expand All @@ -19,27 +21,58 @@ pub fn camera_system<T: CameraProjection + Component>() -> Box<dyn Schedulable>
window_created_events: Res<Events<WindowCreated>>,
windows: Res<Windows>,
query: &mut Query<(Write<Camera>, Write<T>)>| {
let primary_window_resized_event = window_resized_event_reader
.find_latest(&window_resized_events, |event| event.is_primary);
let mut changed_window_ids = Vec::new();
let mut changed_primary_window_id = None;
// handle resize events. latest events are handled first because we only want to resize each window once
for event in window_resized_event_reader
.iter(&window_resized_events)
.rev()
{
if changed_window_ids.contains(&event.id) {
continue;
}

if event.is_primary {
changed_primary_window_id = Some(event.id);
} else {
changed_window_ids.push(event.id);
}
}

for event in window_created_event_reader.iter(&window_created_events) {
if !event.is_primary {
// handle resize events. latest events are handled first because we only want to resize each window once
for event in window_created_event_reader
.iter(&window_created_events)
.rev()
{
if changed_window_ids.contains(&event.id) {
continue;
}
if let Some(window) = windows.get(event.id) {
for (mut camera, mut camera_projection) in query.iter_mut(world) {
camera_projection.update(window.width as usize, window.height as usize);
camera.projection_matrix = camera_projection.get_projection_matrix();
}

if event.is_primary {
changed_primary_window_id = Some(event.id);
} else {
changed_window_ids.push(event.id);
}
}

if let Some(primary_window_resized_event) = primary_window_resized_event {
for (mut camera, mut camera_projection) in query.iter_mut(world) {
camera_projection.update(
primary_window_resized_event.width,
primary_window_resized_event.height,
);
for (mut camera, mut camera_projection) in query.iter_mut(world) {
if let Some(window) = match camera.window {
WindowReference::Id(id) => {
if changed_window_ids.contains(&id) {
windows.get(id)
} else {
None
}
}
WindowReference::Primary => {
if let Some(id) = changed_primary_window_id {
windows.get(id)
} else {
None
}
}
} {
camera_projection.update(window.width as usize, window.height as usize);
camera.projection_matrix = camera_projection.get_projection_matrix();
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Default for PerspectiveCameraComponents {
fn default() -> Self {
PerspectiveCameraComponents {
camera: Camera {
name: Some(base_render_graph::camera::CAMERA.to_string()),
name: Some(base_render_graph::camera::CAMERA3D.to_string()),
..Default::default()
},
perspective_projection: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl AppPlugin for RenderPlugin {
render_graph.add_base_graph(config);
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
if config.add_3d_camera {
active_cameras.add(base_render_graph::camera::CAMERA);
active_cameras.add(base_render_graph::camera::CAMERA3D);
}

if config.add_2d_camera {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/pipeline/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl BindType {
match self {
BindType::Uniform { properties, .. } => {
Some(properties.iter().fold(0, |total, property| {
total + property.property_type.get_size()
total + property.get_size()
}))
}
_ => None,
Expand Down
39 changes: 16 additions & 23 deletions crates/bevy_render/src/pipeline/pipeline_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,7 @@ impl PipelineLayout {
}

#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct UniformProperty {
pub name: String,
pub property_type: UniformPropertyType,
}

#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum UniformPropertyType {
// TODO: Use VertexFormat here
pub enum UniformProperty {
UInt,
Int,
IVec2,
Expand All @@ -104,27 +97,27 @@ pub enum UniformPropertyType {
Mat3,
Mat4,
Struct(Vec<UniformProperty>),
Array(Box<UniformPropertyType>, usize),
Array(Box<UniformProperty>, usize),
}

impl UniformPropertyType {
impl UniformProperty {
pub fn get_size(&self) -> u64 {
match self {
UniformPropertyType::UInt => 4,
UniformPropertyType::Int => 4,
UniformPropertyType::IVec2 => 4 * 2,
UniformPropertyType::Float => 4,
UniformPropertyType::UVec4 => 4 * 4,
UniformPropertyType::Vec2 => 4 * 2,
UniformPropertyType::Vec3 => 4 * 3,
UniformPropertyType::Vec4 => 4 * 4,
UniformPropertyType::Mat3 => 4 * 4 * 3,
UniformPropertyType::Mat4 => 4 * 4 * 4,
UniformPropertyType::Struct(properties) => properties
UniformProperty::UInt => 4,
UniformProperty::Int => 4,
UniformProperty::IVec2 => 4 * 2,
UniformProperty::Float => 4,
UniformProperty::UVec4 => 4 * 4,
UniformProperty::Vec2 => 4 * 2,
UniformProperty::Vec3 => 4 * 3,
UniformProperty::Vec4 => 4 * 4,
UniformProperty::Mat3 => 4 * 4 * 3,
UniformProperty::Mat4 => 4 * 4 * 4,
UniformProperty::Struct(properties) => properties
.iter()
.map(|p| p.property_type.get_size())
.map(|p| p.get_size())
.fold(0, |total, size| total + size),
UniformPropertyType::Array(property, length) => property.get_size() * *length as u64,
UniformProperty::Array(property, length) => property.get_size() * *length as u64,
}
}
}
Loading

0 comments on commit 69925f0

Please sign in to comment.