render: add RenderPass queries. move ui to its own pass
This commit is contained in:
parent
bd8e979de8
commit
2929197d9b
@ -1,6 +1,7 @@
|
|||||||
use crate::ArchetypeAccess;
|
use crate::ArchetypeAccess;
|
||||||
use hecs::{
|
use hecs::{
|
||||||
Archetype, Component, ComponentError, Entity, Fetch, Query as HecsQuery, Ref, RefMut, World,
|
Archetype, Component, ComponentError, Entity, Fetch, Query as HecsQuery, QueryOne, Ref, RefMut,
|
||||||
|
World,
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
@ -11,10 +12,11 @@ pub struct Query<'a, Q: HecsQuery> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum QueryComponentError {
|
pub enum QueryError {
|
||||||
CannotReadArchetype,
|
CannotReadArchetype,
|
||||||
CannotWriteArchetype,
|
CannotWriteArchetype,
|
||||||
ComponentError(ComponentError),
|
ComponentError(ComponentError),
|
||||||
|
NoSuchEntity,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Q: HecsQuery> Query<'a, Q> {
|
impl<'a, Q: HecsQuery> Query<'a, Q> {
|
||||||
@ -34,7 +36,7 @@ impl<'a, Q: HecsQuery> Query<'a, Q> {
|
|||||||
|
|
||||||
/// Gets a reference to the entity's component of the given type. This will fail if the entity does not have
|
/// Gets a reference to the entity's component of the given type. This will fail if the entity does not have
|
||||||
/// the given component type or if the given component type does not match this query.
|
/// the given component type or if the given component type does not match this query.
|
||||||
pub fn get<T: Component>(&self, entity: Entity) -> Result<Ref<'_, T>, QueryComponentError> {
|
pub fn get<T: Component>(&self, entity: Entity) -> Result<Ref<'_, T>, QueryError> {
|
||||||
if let Some(location) = self.world.get_entity_location(entity) {
|
if let Some(location) = self.world.get_entity_location(entity) {
|
||||||
if self
|
if self
|
||||||
.archetype_access
|
.archetype_access
|
||||||
@ -47,23 +49,38 @@ impl<'a, Q: HecsQuery> Query<'a, Q> {
|
|||||||
{
|
{
|
||||||
self.world
|
self.world
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.map_err(|err| QueryComponentError::ComponentError(err))
|
.map_err(|err| QueryError::ComponentError(err))
|
||||||
} else {
|
} else {
|
||||||
Err(QueryComponentError::CannotReadArchetype)
|
Err(QueryError::CannotReadArchetype)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(QueryComponentError::ComponentError(
|
Err(QueryError::ComponentError(ComponentError::NoSuchEntity))
|
||||||
ComponentError::NoSuchEntity,
|
}
|
||||||
))
|
}
|
||||||
|
|
||||||
|
pub fn entity(&self, entity: Entity) -> Result<QueryOne<'_, Q>, QueryError> {
|
||||||
|
if let Some(location) = self.world.get_entity_location(entity) {
|
||||||
|
if self
|
||||||
|
.archetype_access
|
||||||
|
.immutable
|
||||||
|
.contains(location.archetype as usize)
|
||||||
|
|| self
|
||||||
|
.archetype_access
|
||||||
|
.mutable
|
||||||
|
.contains(location.archetype as usize)
|
||||||
|
{
|
||||||
|
Ok(self.world.query_one(entity).unwrap())
|
||||||
|
} else {
|
||||||
|
Err(QueryError::CannotReadArchetype)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(QueryError::NoSuchEntity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have
|
/// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have
|
||||||
/// the given component type or if the given component type does not match this query.
|
/// the given component type or if the given component type does not match this query.
|
||||||
pub fn get_mut<T: Component>(
|
pub fn get_mut<T: Component>(&self, entity: Entity) -> Result<RefMut<'_, T>, QueryError> {
|
||||||
&self,
|
|
||||||
entity: Entity,
|
|
||||||
) -> Result<RefMut<'_, T>, QueryComponentError> {
|
|
||||||
if let Some(location) = self.world.get_entity_location(entity) {
|
if let Some(location) = self.world.get_entity_location(entity) {
|
||||||
if self
|
if self
|
||||||
.archetype_access
|
.archetype_access
|
||||||
@ -72,14 +89,12 @@ impl<'a, Q: HecsQuery> Query<'a, Q> {
|
|||||||
{
|
{
|
||||||
self.world
|
self.world
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map_err(|err| QueryComponentError::ComponentError(err))
|
.map_err(|err| QueryError::ComponentError(err))
|
||||||
} else {
|
} else {
|
||||||
Err(QueryComponentError::CannotWriteArchetype)
|
Err(QueryError::CannotWriteArchetype)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(QueryComponentError::ComponentError(
|
Err(QueryError::ComponentError(ComponentError::NoSuchEntity))
|
||||||
ComponentError::NoSuchEntity,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,11 +104,7 @@ impl<'a, Q: HecsQuery> Query<'a, Q> {
|
|||||||
|
|
||||||
/// Sets the entity's component to the given value. This will fail if the entity does not already have
|
/// Sets the entity's component to the given value. This will fail if the entity does not already have
|
||||||
/// the given component type or if the given component type does not match this query.
|
/// the given component type or if the given component type does not match this query.
|
||||||
pub fn set<T: Component>(
|
pub fn set<T: Component>(&self, entity: Entity, component: T) -> Result<(), QueryError> {
|
||||||
&self,
|
|
||||||
entity: Entity,
|
|
||||||
component: T,
|
|
||||||
) -> Result<(), QueryComponentError> {
|
|
||||||
let mut current = self.get_mut::<T>(entity)?;
|
let mut current = self.get_mut::<T>(entity)?;
|
||||||
*current = component;
|
*current = component;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -4,7 +4,7 @@ use bevy_ecs::Bundle;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines}, prelude::MainPass,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
|||||||
pub struct PbrComponents {
|
pub struct PbrComponents {
|
||||||
pub mesh: Handle<Mesh>,
|
pub mesh: Handle<Mesh>,
|
||||||
pub material: Handle<StandardMaterial>,
|
pub material: Handle<StandardMaterial>,
|
||||||
|
pub main_pass: MainPass,
|
||||||
pub draw: Draw,
|
pub draw: Draw,
|
||||||
pub render_pipelines: RenderPipelines,
|
pub render_pipelines: RenderPipelines,
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
@ -43,6 +44,7 @@ impl Default for PbrComponents {
|
|||||||
)]),
|
)]),
|
||||||
mesh: Default::default(),
|
mesh: Default::default(),
|
||||||
material: Default::default(),
|
material: Default::default(),
|
||||||
|
main_pass: Default::default(),
|
||||||
draw: Default::default(),
|
draw: Default::default(),
|
||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
translation: Default::default(),
|
translation: Default::default(),
|
||||||
|
@ -8,11 +8,15 @@ use bevy_asset::Handle;
|
|||||||
use bevy_ecs::Bundle;
|
use bevy_ecs::Bundle;
|
||||||
use bevy_transform::components::{Rotation, Scale, Transform, Translation};
|
use bevy_transform::components::{Rotation, Scale, Transform, Translation};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MainPass;
|
||||||
|
|
||||||
#[derive(Bundle, Default)]
|
#[derive(Bundle, Default)]
|
||||||
pub struct MeshComponents {
|
pub struct MeshComponents {
|
||||||
pub mesh: Handle<Mesh>,
|
pub mesh: Handle<Mesh>,
|
||||||
pub draw: Draw,
|
pub draw: Draw,
|
||||||
pub render_pipelines: RenderPipelines,
|
pub render_pipelines: RenderPipelines,
|
||||||
|
pub main_pass: MainPass,
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub translation: Translation,
|
pub translation: Translation,
|
||||||
pub rotation: Rotation,
|
pub rotation: Rotation,
|
||||||
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||||
},
|
},
|
||||||
|
prelude::MainPass,
|
||||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||||
Color,
|
Color,
|
||||||
};
|
};
|
||||||
@ -89,7 +90,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.add_main_pass {
|
if config.add_main_pass {
|
||||||
let mut main_pass_node = PassNode::new(PassDescriptor {
|
let mut main_pass_node = PassNode::<&MainPass>::new(PassDescriptor {
|
||||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("color".to_string()),
|
attachment: TextureAttachment::Input("color".to_string()),
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
|
@ -11,14 +11,15 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_ecs::{Resources, World};
|
use bevy_ecs::{Resources, World, HecsQuery};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
struct CameraInfo {
|
struct CameraInfo {
|
||||||
name: String,
|
name: String,
|
||||||
bind_group_id: Option<BindGroupId>,
|
bind_group_id: Option<BindGroupId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PassNode {
|
pub struct PassNode<Q: HecsQuery> {
|
||||||
descriptor: PassDescriptor,
|
descriptor: PassDescriptor,
|
||||||
inputs: Vec<ResourceSlotInfo>,
|
inputs: Vec<ResourceSlotInfo>,
|
||||||
cameras: Vec<CameraInfo>,
|
cameras: Vec<CameraInfo>,
|
||||||
@ -26,9 +27,10 @@ pub struct PassNode {
|
|||||||
depth_stencil_attachment_input_index: Option<usize>,
|
depth_stencil_attachment_input_index: Option<usize>,
|
||||||
default_clear_color_inputs: Vec<usize>,
|
default_clear_color_inputs: Vec<usize>,
|
||||||
camera_bind_group_descriptor: BindGroupDescriptor,
|
camera_bind_group_descriptor: BindGroupDescriptor,
|
||||||
|
_marker: PhantomData<Q>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PassNode {
|
impl<Q: HecsQuery> PassNode<Q> {
|
||||||
pub fn new(descriptor: PassDescriptor) -> Self {
|
pub fn new(descriptor: PassDescriptor) -> Self {
|
||||||
let mut inputs = Vec::new();
|
let mut inputs = Vec::new();
|
||||||
let mut color_attachment_input_indices = Vec::new();
|
let mut color_attachment_input_indices = Vec::new();
|
||||||
@ -75,6 +77,7 @@ impl PassNode {
|
|||||||
depth_stencil_attachment_input_index,
|
depth_stencil_attachment_input_index,
|
||||||
default_clear_color_inputs: Vec::new(),
|
default_clear_color_inputs: Vec::new(),
|
||||||
camera_bind_group_descriptor,
|
camera_bind_group_descriptor,
|
||||||
|
_marker: PhantomData::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +93,7 @@ impl PassNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for PassNode {
|
impl<Q: HecsQuery + Send + Sync + 'static> Node for PassNode<Q> {
|
||||||
fn input(&self) -> &[ResourceSlotInfo] {
|
fn input(&self) -> &[ResourceSlotInfo] {
|
||||||
&self.inputs
|
&self.inputs
|
||||||
}
|
}
|
||||||
@ -167,6 +170,13 @@ impl Node for PassNode {
|
|||||||
// attempt to draw each visible entity
|
// attempt to draw each visible entity
|
||||||
let mut draw_state = DrawState::default();
|
let mut draw_state = DrawState::default();
|
||||||
for visible_entity in visible_entities.iter() {
|
for visible_entity in visible_entities.iter() {
|
||||||
|
if let Ok(mut query_one) = world.query_one::<Q>(visible_entity.entity) {
|
||||||
|
if query_one.get().is_none() {
|
||||||
|
// visible entity does not match the Pass query
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let draw = if let Ok(draw) = world.get::<Draw>(visible_entity.entity) {
|
let draw = if let Ok(draw) = world.get::<Draw>(visible_entity.entity) {
|
||||||
draw
|
draw
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,7 +7,7 @@ use bevy_ecs::Bundle;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||||
prelude::Draw,
|
prelude::{Draw, MainPass},
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ pub struct SpriteComponents {
|
|||||||
pub sprite: Sprite,
|
pub sprite: Sprite,
|
||||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||||
pub material: Handle<ColorMaterial>,
|
pub material: Handle<ColorMaterial>,
|
||||||
|
pub main_pass: MainPass,
|
||||||
pub draw: Draw,
|
pub draw: Draw,
|
||||||
pub render_pipelines: RenderPipelines,
|
pub render_pipelines: RenderPipelines,
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
@ -51,6 +52,7 @@ impl Default for SpriteComponents {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
sprite: Default::default(),
|
sprite: Default::default(),
|
||||||
|
main_pass: MainPass,
|
||||||
material: Default::default(),
|
material: Default::default(),
|
||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
translation: Default::default(),
|
translation: Default::default(),
|
||||||
@ -66,6 +68,7 @@ pub struct SpriteSheetComponents {
|
|||||||
pub texture_atlas: Handle<TextureAtlas>,
|
pub texture_atlas: Handle<TextureAtlas>,
|
||||||
pub draw: Draw,
|
pub draw: Draw,
|
||||||
pub render_pipelines: RenderPipelines,
|
pub render_pipelines: RenderPipelines,
|
||||||
|
pub main_pass: MainPass,
|
||||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub translation: Translation,
|
pub translation: Translation,
|
||||||
@ -99,6 +102,7 @@ impl Default for SpriteSheetComponents {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
mesh: QUAD_HANDLE,
|
mesh: QUAD_HANDLE,
|
||||||
|
main_pass: MainPass,
|
||||||
sprite: Default::default(),
|
sprite: Default::default(),
|
||||||
texture_atlas: Default::default(),
|
texture_atlas: Default::default(),
|
||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
|
@ -4,9 +4,9 @@ use bevy_ecs::Resources;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::ActiveCameras,
|
camera::ActiveCameras,
|
||||||
pipeline::*,
|
pipeline::*,
|
||||||
render_graph::{base, CameraNode, PassNode, RenderGraph, RenderResourcesNode},
|
render_graph::{base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode, WindowTextureNode},
|
||||||
shader::{Shader, ShaderStage, ShaderStages},
|
shader::{Shader, ShaderStage, ShaderStages},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat, prelude::{Color, MainPass}, pass::{RenderPassColorAttachmentDescriptor, PassDescriptor, TextureAttachment, LoadOp, Operations, RenderPassDepthStencilAttachmentDescriptor},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const UI_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
pub const UI_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||||
@ -60,6 +60,7 @@ pub fn build_ui_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
|||||||
pub mod node {
|
pub mod node {
|
||||||
pub const UI_CAMERA: &'static str = "ui_camera";
|
pub const UI_CAMERA: &'static str = "ui_camera";
|
||||||
pub const NODE: &'static str = "node";
|
pub const NODE: &'static str = "node";
|
||||||
|
pub const UI_PASS: &'static str = "ui_pass";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod camera {
|
pub mod camera {
|
||||||
@ -76,16 +77,56 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||||
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
||||||
|
|
||||||
|
let mut ui_pass_node = PassNode::<&Node>::new(PassDescriptor {
|
||||||
|
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: TextureAttachment::Input("color".to_string()),
|
||||||
|
resolve_target: None,
|
||||||
|
ops: Operations {
|
||||||
|
load: LoadOp::Load,
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||||
|
attachment: TextureAttachment::Input("depth".to_string()),
|
||||||
|
depth_ops: Some(Operations {
|
||||||
|
load: LoadOp::Clear(1.0),
|
||||||
|
store: true,
|
||||||
|
}),
|
||||||
|
stencil_ops: None,
|
||||||
|
}),
|
||||||
|
sample_count: 1,
|
||||||
|
});
|
||||||
|
ui_pass_node.add_camera(camera::UI_CAMERA);
|
||||||
|
self.add_node(node::UI_PASS, ui_pass_node);
|
||||||
|
|
||||||
|
self.add_slot_edge(
|
||||||
|
base::node::PRIMARY_SWAP_CHAIN,
|
||||||
|
WindowSwapChainNode::OUT_TEXTURE,
|
||||||
|
node::UI_PASS,
|
||||||
|
"color",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
self.add_slot_edge(
|
||||||
|
base::node::MAIN_DEPTH_TEXTURE,
|
||||||
|
WindowTextureNode::OUT_TEXTURE,
|
||||||
|
node::UI_PASS,
|
||||||
|
"depth",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// ensure ui pass runs after main pass
|
||||||
|
self.add_node_edge(base::node::MAIN_PASS, node::UI_PASS)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// setup ui camera
|
// setup ui camera
|
||||||
self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA));
|
self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA));
|
||||||
self.add_node_edge(node::UI_CAMERA, base::node::MAIN_PASS)
|
self.add_node_edge(node::UI_CAMERA, node::UI_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.add_system_node(node::NODE, RenderResourcesNode::<Node>::new(true));
|
self.add_system_node(node::NODE, RenderResourcesNode::<Node>::new(true));
|
||||||
self.add_node_edge(node::NODE, base::node::MAIN_PASS)
|
self.add_node_edge(node::NODE, node::UI_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
||||||
let main_pass_node: &mut PassNode = self.get_node_mut(base::node::MAIN_PASS).unwrap();
|
|
||||||
main_pass_node.add_camera(camera::UI_CAMERA);
|
|
||||||
active_cameras.add(camera::UI_CAMERA);
|
active_cameras.add(camera::UI_CAMERA);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ fn setup(
|
|||||||
render_graph.add_system_node("secondary_camera", CameraNode::new("Secondary"));
|
render_graph.add_system_node("secondary_camera", CameraNode::new("Secondary"));
|
||||||
|
|
||||||
// add a new render pass for our new camera
|
// add a new render pass for our new camera
|
||||||
let mut second_window_pass = PassNode::new(PassDescriptor {
|
let mut second_window_pass = PassNode::<&MainPass>::new(PassDescriptor {
|
||||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("color".to_string()),
|
attachment: TextureAttachment::Input("color".to_string()),
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
|
Loading…
Reference in New Issue
Block a user