mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
render: multi-window cameras ready to go!
passes now bind camera buffers and cameras can now be assigned non-primary windows
This commit is contained in:
parent
ca4726ea7d
commit
69925f0817
18 changed files with 239 additions and 160 deletions
|
@ -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,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
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};
|
||||
|
||||
|
@ -9,6 +9,8 @@ use legion::{prelude::*, storage::Component};
|
|||
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> {
|
||||
|
@ -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);
|
||||
|
||||
for event in window_created_event_reader.iter(&window_created_events) {
|
||||
if !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 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,
|
||||
);
|
||||
// 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 event.is_primary {
|
||||
changed_primary_window_id = Some(event.id);
|
||||
} else {
|
||||
changed_window_ids.push(event.id);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
use crate::{
|
||||
draw::{Draw, RenderCommand},
|
||||
pass::{PassDescriptor, TextureAttachment, ClearColor},
|
||||
pipeline::PipelineDescriptor,
|
||||
pass::{ClearColor, PassDescriptor, TextureAttachment},
|
||||
pipeline::{
|
||||
BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty,
|
||||
},
|
||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::{BindGroupId, BufferId, RenderResourceBindings, RenderResourceType},
|
||||
renderer::RenderContext, ActiveCameras, VisibleEntities,
|
||||
render_resource::{
|
||||
BindGroup, BindGroupId, BufferId, RenderResourceBindings, RenderResourceType,
|
||||
},
|
||||
renderer::RenderContext,
|
||||
ActiveCameras, VisibleEntities,
|
||||
};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use legion::prelude::*;
|
||||
|
||||
struct CameraInfo {
|
||||
name: String,
|
||||
bind_group_id: Option<BindGroupId>,
|
||||
}
|
||||
|
||||
pub struct PassNode {
|
||||
descriptor: PassDescriptor,
|
||||
inputs: Vec<ResourceSlotInfo>,
|
||||
cameras: Vec<String>,
|
||||
cameras: Vec<CameraInfo>,
|
||||
color_attachment_input_indices: Vec<Option<usize>>,
|
||||
depth_stencil_attachment_input_index: Option<usize>,
|
||||
default_clear_color_inputs: Vec<usize>,
|
||||
camera_bind_group_descriptor: BindGroupDescriptor,
|
||||
}
|
||||
|
||||
impl PassNode {
|
||||
|
@ -45,6 +56,18 @@ impl PassNode {
|
|||
}
|
||||
}
|
||||
|
||||
let camera_bind_group_descriptor = BindGroupDescriptor::new(
|
||||
0,
|
||||
vec![BindingDescriptor {
|
||||
name: "Camera".to_string(),
|
||||
index: 0,
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![UniformProperty::Struct(vec![UniformProperty::Mat4])],
|
||||
},
|
||||
}],
|
||||
);
|
||||
|
||||
PassNode {
|
||||
descriptor,
|
||||
inputs,
|
||||
|
@ -52,11 +75,15 @@ impl PassNode {
|
|||
color_attachment_input_indices,
|
||||
depth_stencil_attachment_input_index,
|
||||
default_clear_color_inputs: Vec::new(),
|
||||
camera_bind_group_descriptor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_camera(&mut self, camera_name: &str) {
|
||||
self.cameras.push(camera_name.to_string());
|
||||
self.cameras.push(CameraInfo {
|
||||
name: camera_name.to_string(),
|
||||
bind_group_id: None,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn use_default_clear_color(&mut self, color_attachment_index: usize) {
|
||||
|
@ -79,12 +106,12 @@ impl Node for PassNode {
|
|||
) {
|
||||
let render_resource_bindings = resources.get::<RenderResourceBindings>().unwrap();
|
||||
let pipelines = resources.get::<Assets<PipelineDescriptor>>().unwrap();
|
||||
let active_cameras= resources.get::<ActiveCameras>().unwrap();
|
||||
let active_cameras = resources.get::<ActiveCameras>().unwrap();
|
||||
|
||||
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
|
||||
if self.default_clear_color_inputs.contains(&i) {
|
||||
if let Some(default_clear_color) = resources.get::<ClearColor>() {
|
||||
color_attachment.clear_color = default_clear_color.color;
|
||||
color_attachment.clear_color = default_clear_color.color;
|
||||
}
|
||||
}
|
||||
if let Some(input_index) = self.color_attachment_input_indices[i] {
|
||||
|
@ -101,18 +128,40 @@ impl Node for PassNode {
|
|||
.attachment =
|
||||
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
||||
}
|
||||
for camera_info in self.cameras.iter_mut() {
|
||||
let camera_binding =
|
||||
if let Some(camera_binding) = render_resource_bindings.get(&camera_info.name) {
|
||||
camera_binding.clone()
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let camera_bind_group = BindGroup::build().add_binding(0, camera_binding).finish();
|
||||
render_context
|
||||
.resources()
|
||||
.create_bind_group(self.camera_bind_group_descriptor.id, &camera_bind_group);
|
||||
camera_info.bind_group_id = Some(camera_bind_group.id);
|
||||
}
|
||||
|
||||
render_context.begin_pass(
|
||||
&self.descriptor,
|
||||
&render_resource_bindings,
|
||||
&mut |render_pass| {
|
||||
for camera_name in self.cameras.iter() {
|
||||
let visible_entities = if let Some(camera_entity) = active_cameras.get(camera_name) {
|
||||
for camera_info in self.cameras.iter() {
|
||||
let camera_bind_group_id= if let Some(bind_group_id) = camera_info.bind_group_id {
|
||||
bind_group_id
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// get an ordered list of entities visible to the camera
|
||||
let visible_entities = if let Some(camera_entity) = active_cameras.get(&camera_info.name) {
|
||||
world.get_component::<VisibleEntities>(camera_entity).unwrap()
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// attempt to draw each visible entity
|
||||
let mut draw_state = DrawState::default();
|
||||
for visible_entity in visible_entities.iter() {
|
||||
let draw = if let Some(draw) = world.get_component::<Draw>(visible_entity.entity) {
|
||||
|
@ -124,7 +173,8 @@ impl Node for PassNode {
|
|||
if !draw.is_visible {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// each Draw component contains an ordered list of render commands. we turn those into actual render commands here
|
||||
for render_command in draw.render_commands.iter() {
|
||||
match render_command {
|
||||
RenderCommand::SetPipeline { pipeline } => {
|
||||
|
@ -132,6 +182,20 @@ impl Node for PassNode {
|
|||
render_pass.set_pipeline(*pipeline);
|
||||
let descriptor = pipelines.get(pipeline).unwrap();
|
||||
draw_state.set_pipeline(*pipeline, descriptor);
|
||||
|
||||
// try to set current camera bind group
|
||||
let layout = descriptor.get_layout().unwrap();
|
||||
if let Some(descriptor) = layout.get_bind_group(0) {
|
||||
if *descriptor == self.camera_bind_group_descriptor {
|
||||
draw_state.set_bind_group(0, camera_bind_group_id);
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
descriptor.id,
|
||||
camera_bind_group_id,
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
RenderCommand::DrawIndexed {
|
||||
base_vertex,
|
||||
|
|
|
@ -261,7 +261,7 @@ impl Default for RenderResourceBindingsId {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::pipeline::{BindType, BindingDescriptor, UniformProperty, UniformPropertyType};
|
||||
use crate::pipeline::{BindType, BindingDescriptor, UniformProperty};
|
||||
|
||||
#[test]
|
||||
fn test_bind_groups() {
|
||||
|
@ -273,13 +273,7 @@ mod tests {
|
|||
name: "a".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![UniformProperty {
|
||||
name: "A".to_string(),
|
||||
property_type: UniformPropertyType::Struct(vec![UniformProperty {
|
||||
name: "".to_string(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
}]),
|
||||
}],
|
||||
properties: vec![UniformProperty::Struct(vec![UniformProperty::Mat4])],
|
||||
},
|
||||
},
|
||||
BindingDescriptor {
|
||||
|
@ -287,10 +281,7 @@ mod tests {
|
|||
name: "b".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![UniformProperty {
|
||||
name: "B".to_string(),
|
||||
property_type: UniformPropertyType::Float,
|
||||
}],
|
||||
properties: vec![UniformProperty::Float],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
pipeline::{
|
||||
BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty,
|
||||
UniformPropertyType, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||
VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||
},
|
||||
texture::{TextureComponentType, TextureViewDimension},
|
||||
};
|
||||
|
@ -214,31 +214,26 @@ enum NumberType {
|
|||
}
|
||||
|
||||
fn reflect_uniform(type_description: &ReflectTypeDescription) -> UniformProperty {
|
||||
let uniform_property_type = if type_description
|
||||
if type_description
|
||||
.type_flags
|
||||
.contains(ReflectTypeFlags::STRUCT)
|
||||
{
|
||||
reflect_uniform_struct(type_description)
|
||||
} else {
|
||||
reflect_uniform_numeric(type_description)
|
||||
};
|
||||
|
||||
UniformProperty {
|
||||
name: type_description.type_name.to_string(),
|
||||
property_type: uniform_property_type,
|
||||
}
|
||||
}
|
||||
|
||||
fn reflect_uniform_struct(type_description: &ReflectTypeDescription) -> UniformPropertyType {
|
||||
fn reflect_uniform_struct(type_description: &ReflectTypeDescription) -> UniformProperty {
|
||||
let mut properties = Vec::new();
|
||||
for member in type_description.members.iter() {
|
||||
properties.push(reflect_uniform(member));
|
||||
}
|
||||
|
||||
UniformPropertyType::Struct(properties)
|
||||
UniformProperty::Struct(properties)
|
||||
}
|
||||
|
||||
fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> UniformPropertyType {
|
||||
fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> UniformProperty {
|
||||
let traits = &type_description.traits;
|
||||
let number_type = if type_description.type_flags.contains(ReflectTypeFlags::INT) {
|
||||
match traits.numeric.scalar.signedness {
|
||||
|
@ -266,8 +261,8 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform
|
|||
traits.numeric.matrix.column_count,
|
||||
traits.numeric.matrix.row_count,
|
||||
) {
|
||||
(NumberType::Float, 3, 3) => UniformPropertyType::Mat3,
|
||||
(NumberType::Float, 4, 4) => UniformPropertyType::Mat4,
|
||||
(NumberType::Float, 3, 3) => UniformProperty::Mat3,
|
||||
(NumberType::Float, 4, 4) => UniformProperty::Mat4,
|
||||
(number_type, column_count, row_count) => panic!(
|
||||
"unexpected uniform property matrix format {:?} {}x{}",
|
||||
number_type, column_count, row_count
|
||||
|
@ -275,14 +270,14 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform
|
|||
}
|
||||
} else {
|
||||
match (number_type, traits.numeric.vector.component_count) {
|
||||
(NumberType::UInt, 0) => UniformPropertyType::UInt,
|
||||
(NumberType::Int, 0) => UniformPropertyType::Int,
|
||||
(NumberType::Int, 2) => UniformPropertyType::IVec2,
|
||||
(NumberType::Float, 0) => UniformPropertyType::Float,
|
||||
(NumberType::Float, 2) => UniformPropertyType::Vec2,
|
||||
(NumberType::Float, 3) => UniformPropertyType::Vec3,
|
||||
(NumberType::Float, 4) => UniformPropertyType::Vec4,
|
||||
(NumberType::UInt, 4) => UniformPropertyType::UVec4,
|
||||
(NumberType::UInt, 0) => UniformProperty::UInt,
|
||||
(NumberType::Int, 0) => UniformProperty::Int,
|
||||
(NumberType::Int, 2) => UniformProperty::IVec2,
|
||||
(NumberType::Float, 0) => UniformProperty::Float,
|
||||
(NumberType::Float, 2) => UniformProperty::Vec2,
|
||||
(NumberType::Float, 3) => UniformProperty::Vec3,
|
||||
(NumberType::Float, 4) => UniformProperty::Vec4,
|
||||
(NumberType::UInt, 4) => UniformProperty::UVec4,
|
||||
(number_type, component_count) => panic!(
|
||||
"unexpected uniform property format {:?} {}",
|
||||
number_type, component_count
|
||||
|
@ -414,15 +409,9 @@ mod tests {
|
|||
name: "Camera".into(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![UniformProperty {
|
||||
name: "Camera".into(),
|
||||
property_type: UniformPropertyType::Struct(vec![
|
||||
UniformProperty {
|
||||
name: "".into(),
|
||||
property_type: UniformPropertyType::Mat4,
|
||||
}
|
||||
]),
|
||||
}],
|
||||
properties: vec![UniformProperty::Struct(vec![
|
||||
UniformProperty::Mat4
|
||||
])],
|
||||
},
|
||||
}]
|
||||
),
|
||||
|
|
|
@ -6,7 +6,7 @@ layout(location = 2) in vec2 Vertex_Uv;
|
|||
|
||||
layout(location = 0) out vec2 v_Uv;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera2d {
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,16 +7,9 @@ layout(location = 2) in vec2 Vertex_Uv;
|
|||
layout(location = 0) out vec2 v_Uv;
|
||||
layout(location = 1) out vec4 v_Color;
|
||||
|
||||
// TODO: remove UI shader def and replace with generic "Camera" when its easier to manually bind global RenderResourceBindings
|
||||
#ifdef UI_CAMERA
|
||||
layout(set = 0, binding = 0) uniform UiCamera {
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
# else
|
||||
layout(set = 0, binding = 0) uniform Camera2d {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
#endif
|
||||
|
||||
// TODO: merge dimensions into "sprites" buffer when that is supported in the Uniforms derive abstraction
|
||||
layout(set = 1, binding = 0) uniform TextureAtlas_size {
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy_asset::Assets;
|
|||
use bevy_render::{
|
||||
draw::{Draw, DrawContext, DrawError, Drawable},
|
||||
mesh,
|
||||
pipeline::{PipelineSpecialization, ShaderSpecialization},
|
||||
pipeline::PipelineSpecialization,
|
||||
render_resource::{
|
||||
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
|
||||
RenderResourceId,
|
||||
|
@ -13,7 +13,6 @@ use bevy_render::{
|
|||
};
|
||||
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
||||
use glam::{Mat4, Vec3};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct TextStyle {
|
||||
pub font_size: f32,
|
||||
|
@ -57,16 +56,11 @@ impl<'a> DrawableText<'a> {
|
|||
|
||||
impl<'a> Drawable for DrawableText<'a> {
|
||||
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> {
|
||||
let mut shader_defs = HashSet::new();
|
||||
shader_defs.insert("UI_CAMERA".to_string());
|
||||
context.set_pipeline(
|
||||
draw,
|
||||
bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE,
|
||||
// TODO: remove this shader def specialization when its easier to manually bind global render resources to specific bind groups
|
||||
&PipelineSpecialization {
|
||||
shader_specialization: ShaderSpecialization { shader_defs },
|
||||
..Default::default()
|
||||
},
|
||||
&PipelineSpecialization::default(),
|
||||
)?;
|
||||
|
||||
let render_resource_context = &**context.render_resource_context;
|
||||
|
@ -151,10 +145,10 @@ impl<'a> Drawable for DrawableText<'a> {
|
|||
.shared_buffers
|
||||
.get_buffer(&sprite, BufferUsage::UNIFORM)
|
||||
.unwrap();
|
||||
let sprite_bind_group =
|
||||
BindGroup::build()
|
||||
.add_binding(0, transform_buffer)
|
||||
.add_binding(1, sprite_buffer).finish();
|
||||
let sprite_bind_group = BindGroup::build()
|
||||
.add_binding(0, transform_buffer)
|
||||
.add_binding(1, sprite_buffer)
|
||||
.finish();
|
||||
context.create_bind_group_resource(2, &sprite_bind_group)?;
|
||||
draw.set_bind_group(2, &sprite_bind_group);
|
||||
draw.draw_indexed(indices.clone(), 0, 0..1);
|
||||
|
|
|
@ -6,7 +6,7 @@ layout(location = 2) in vec2 Vertex_Uv;
|
|||
|
||||
layout(location = 0) out vec2 v_Uv;
|
||||
|
||||
layout(set = 0, binding = 0) uniform UiCamera {
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WindowReference {
|
||||
Primary,
|
||||
Id(WindowId),
|
||||
}
|
||||
|
||||
impl Default for WindowReference {
|
||||
fn default() -> Self {
|
||||
WindowReference::Primary
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct WindowId(Uuid);
|
||||
|
||||
|
|
|
@ -1,18 +1,30 @@
|
|||
use bevy::{prelude::*, window::CreateWindow};
|
||||
use bevy_render::{pass::{StoreOp, LoadOp, TextureAttachment, RenderPassColorAttachmentDescriptor, PassDescriptor, RenderPassDepthStencilAttachmentDescriptor}, texture::{TextureDescriptor, TextureFormat, TextureUsage}};
|
||||
use bevy_window::{WindowId, WindowReference};
|
||||
use bevy::{
|
||||
prelude::*,
|
||||
render::{
|
||||
pass::{
|
||||
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment,
|
||||
},
|
||||
texture::{TextureDescriptor, TextureFormat, TextureUsage},
|
||||
ActiveCameras,
|
||||
},
|
||||
window::{CreateWindow, WindowId, WindowReference},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_default_plugins()
|
||||
.add_startup_system(create_second_window_system.system())
|
||||
.add_startup_system(setup_scene.system())
|
||||
.add_startup_system(setup.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
fn create_second_window_system(
|
||||
fn setup(
|
||||
command_buffer: &mut CommandBuffer,
|
||||
mut create_window_events: ResMut<Events<CreateWindow>>,
|
||||
mut active_cameras: ResMut<ActiveCameras>,
|
||||
mut render_graph: ResMut<RenderGraph>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
let window_id = WindowId::new();
|
||||
|
||||
|
@ -48,6 +60,10 @@ fn create_second_window_system(
|
|||
),
|
||||
);
|
||||
|
||||
// add a new depth texture node for our new window
|
||||
render_graph.add_system_node("secondary_camera", CameraNode::new("Secondary"));
|
||||
|
||||
// add a new render pass for our new camera
|
||||
let mut second_window_pass = PassNode::new(PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
|
@ -70,13 +86,10 @@ fn create_second_window_system(
|
|||
sample_count: 1,
|
||||
});
|
||||
|
||||
// TODO: use different camera here
|
||||
second_window_pass.add_camera(bevy::render::base_render_graph::camera::CAMERA);
|
||||
second_window_pass.add_camera("Secondary");
|
||||
active_cameras.add("Secondary");
|
||||
|
||||
render_graph.add_node(
|
||||
"second_window_pass",
|
||||
second_window_pass,
|
||||
);
|
||||
render_graph.add_node("second_window_pass", second_window_pass);
|
||||
|
||||
render_graph
|
||||
.add_slot_edge(
|
||||
|
@ -95,13 +108,13 @@ fn create_second_window_system(
|
|||
"depth",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn setup_scene(
|
||||
command_buffer: &mut CommandBuffer,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
render_graph
|
||||
.add_node_edge("secondary_camera", "second_window_pass")
|
||||
.unwrap();
|
||||
|
||||
// SETUP SCENE
|
||||
|
||||
// load the mesh
|
||||
let mesh_handle = asset_server
|
||||
.load("assets/models/monkey/Monkey.gltf")
|
||||
|
@ -135,18 +148,19 @@ fn setup_scene(
|
|||
Vec3::new(0.0, 1.0, 0.0),
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
// second window camera
|
||||
.entity_with(PerspectiveCameraComponents {
|
||||
camera: Camera {
|
||||
name: Some("Secondary".to_string()),
|
||||
window: WindowReference::Id(window_id),
|
||||
..Default::default()
|
||||
},
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
Vec3::new(6.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
)),
|
||||
..Default::default()
|
||||
});
|
||||
// // second window camera
|
||||
// .entity_with(PerspectiveCameraComponents {
|
||||
// camera: Camera {
|
||||
// name: Some("Secondary".to_string()),
|
||||
// ..Default::default()
|
||||
// },
|
||||
// transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
// Vec3::new(0.0, 0.0, 6.0),
|
||||
// Vec3::new(0.0, 0.0, 0.0),
|
||||
// Vec3::new(0.0, 1.0, 0.0),
|
||||
// )),
|
||||
// ..Default::default()
|
||||
// });
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue