render: add front-to-back drawing
MainPassNodes now have assigned cameras and draw using those camera's VisibleEntities
This commit is contained in:
		
							parent
							
								
									ca8625c407
								
							
						
					
					
						commit
						41dc8a5967
					
				@ -92,9 +92,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if config.add_main_pass {
 | 
			
		||||
            self.add_node(
 | 
			
		||||
                node::MAIN_PASS,
 | 
			
		||||
                MainPassNode::new(PassDescriptor {
 | 
			
		||||
            let mut main_pass_node = MainPassNode::new(PassDescriptor {
 | 
			
		||||
                color_attachments: vec![RenderPassColorAttachmentDescriptor {
 | 
			
		||||
                    attachment: TextureAttachment::Input("color".to_string()),
 | 
			
		||||
                    resolve_target: None,
 | 
			
		||||
@ -114,7 +112,19 @@ impl BaseRenderGraphBuilder for RenderGraph {
 | 
			
		||||
                    clear_stencil: 0,
 | 
			
		||||
                }),
 | 
			
		||||
                sample_count: 1,
 | 
			
		||||
                }),
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            if config.add_3d_camera {
 | 
			
		||||
                main_pass_node.add_camera(camera::CAMERA);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if config.add_2d_camera {
 | 
			
		||||
                main_pass_node.add_camera(camera::CAMERA2D);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.add_node(
 | 
			
		||||
                node::MAIN_PASS,
 | 
			
		||||
                main_pass_node
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            self.add_node_edge(node::TEXTURE_COPY, node::MAIN_PASS)
 | 
			
		||||
 | 
			
		||||
@ -17,24 +17,40 @@ pub struct VisibleEntities {
 | 
			
		||||
    pub value: Vec<VisibleEntity>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl VisibleEntities {
 | 
			
		||||
    pub fn iter(&self) -> impl DoubleEndedIterator<Item=&VisibleEntity> {
 | 
			
		||||
        self.value.iter()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn visible_entities_system(
 | 
			
		||||
    world: &mut SubWorld,
 | 
			
		||||
    camera_query: &mut Query<(Read<Camera>, Read<Transform>, Write<VisibleEntities>)>,
 | 
			
		||||
    entities_query: &mut Query<(Read<Draw>, Read<Transform>)>,
 | 
			
		||||
    entities_query: &mut Query<Read<Draw>>,
 | 
			
		||||
    _transform_entities_query: &mut Query<(Read<Draw>, Read<Transform>)>, // ensures we can optionally access Transforms
 | 
			
		||||
) {
 | 
			
		||||
    for (_camera, camera_transform, mut visible_entities) in camera_query.iter_mut(world) {
 | 
			
		||||
        visible_entities.value.clear();
 | 
			
		||||
        let camera_position = camera_transform.value.w_axis().truncate();
 | 
			
		||||
 | 
			
		||||
        for (entity, (draw, transform)) in entities_query.iter_entities(world) {
 | 
			
		||||
        let mut no_transform_order = 0.0;
 | 
			
		||||
        for (entity, draw) in entities_query.iter_entities(world) {
 | 
			
		||||
            if !draw.is_visible {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let order = if let Some(transform) = world.get_component::<Transform>(entity) {
 | 
			
		||||
                let position = transform.value.w_axis().truncate();
 | 
			
		||||
                // smaller distances are sorted to lower indices by using the negative distance from the camera 
 | 
			
		||||
                FloatOrd(-(camera_position - position).length())
 | 
			
		||||
            } else {
 | 
			
		||||
                let order = FloatOrd(no_transform_order);
 | 
			
		||||
                no_transform_order += 0.1;
 | 
			
		||||
                order
 | 
			
		||||
            };
 | 
			
		||||
            visible_entities.value.push(VisibleEntity {
 | 
			
		||||
                entity,
 | 
			
		||||
                order: FloatOrd((camera_position - position).length()),
 | 
			
		||||
                order,
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ use crate::{
 | 
			
		||||
    pipeline::PipelineDescriptor,
 | 
			
		||||
    render_graph::{Node, ResourceSlotInfo, ResourceSlots},
 | 
			
		||||
    render_resource::{BindGroupId, BufferId, RenderResourceBindings, RenderResourceType},
 | 
			
		||||
    renderer::RenderContext,
 | 
			
		||||
    renderer::RenderContext, ActiveCameras, VisibleEntities,
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use legion::prelude::*;
 | 
			
		||||
@ -12,6 +12,7 @@ use legion::prelude::*;
 | 
			
		||||
pub struct MainPassNode {
 | 
			
		||||
    descriptor: PassDescriptor,
 | 
			
		||||
    inputs: Vec<ResourceSlotInfo>,
 | 
			
		||||
    cameras: Vec<String>,
 | 
			
		||||
    color_attachment_input_indices: Vec<Option<usize>>,
 | 
			
		||||
    depth_stencil_attachment_input_index: Option<usize>,
 | 
			
		||||
}
 | 
			
		||||
@ -46,10 +47,15 @@ impl MainPassNode {
 | 
			
		||||
        MainPassNode {
 | 
			
		||||
            descriptor,
 | 
			
		||||
            inputs,
 | 
			
		||||
            cameras: Vec::new(),
 | 
			
		||||
            color_attachment_input_indices,
 | 
			
		||||
            depth_stencil_attachment_input_index,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_camera(&mut self, camera_name: &str) {
 | 
			
		||||
        self.cameras.push(camera_name.to_string());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Node for MainPassNode {
 | 
			
		||||
@ -67,6 +73,7 @@ impl Node for MainPassNode {
 | 
			
		||||
    ) {
 | 
			
		||||
        let render_resource_bindings = resources.get::<RenderResourceBindings>().unwrap();
 | 
			
		||||
        let pipelines = resources.get::<Assets<PipelineDescriptor>>().unwrap();
 | 
			
		||||
        let active_cameras= resources.get::<ActiveCameras>().unwrap();
 | 
			
		||||
 | 
			
		||||
        for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
 | 
			
		||||
            if let Some(input_index) = self.color_attachment_input_indices[i] {
 | 
			
		||||
@ -84,12 +91,25 @@ impl Node for MainPassNode {
 | 
			
		||||
                TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for camera_name in self.cameras.iter() {
 | 
			
		||||
            let visible_entities = if let Some(camera_entity) = active_cameras.get(camera_name) {
 | 
			
		||||
                world.get_component::<VisibleEntities>(camera_entity).unwrap()
 | 
			
		||||
            } else {
 | 
			
		||||
                continue;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            render_context.begin_pass(
 | 
			
		||||
                &self.descriptor,
 | 
			
		||||
                &render_resource_bindings,
 | 
			
		||||
                &mut |render_pass| {
 | 
			
		||||
                    let mut draw_state = DrawState::default();
 | 
			
		||||
                for draw in <Read<Draw>>::query().iter(&world) {
 | 
			
		||||
                    for visible_entity in visible_entities.iter() {
 | 
			
		||||
                        let draw = if let Some(draw) = world.get_component::<Draw>(visible_entity.entity) {
 | 
			
		||||
                            draw
 | 
			
		||||
                        } else {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
                        if !draw.is_visible {
 | 
			
		||||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
@ -153,6 +173,7 @@ impl Node for MainPassNode {
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Tracks the current pipeline state to ensure draw calls are valid.
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ use bevy_asset::{Assets, Handle};
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    base_render_graph,
 | 
			
		||||
    pipeline::{state_descriptors::*, PipelineDescriptor},
 | 
			
		||||
    render_graph::{nodes::CameraNode, RenderGraph},
 | 
			
		||||
    render_graph::{nodes::{MainPassNode, CameraNode}, RenderGraph},
 | 
			
		||||
    shader::{Shader, ShaderStage, ShaderStages},
 | 
			
		||||
    texture::TextureFormat, ActiveCameras,
 | 
			
		||||
};
 | 
			
		||||
@ -70,13 +70,17 @@ pub trait UiRenderGraphBuilder {
 | 
			
		||||
 | 
			
		||||
impl UiRenderGraphBuilder for RenderGraph {
 | 
			
		||||
    fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
 | 
			
		||||
        self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA));
 | 
			
		||||
        self.add_node_edge(node::UI_CAMERA, base_render_graph::node::MAIN_PASS)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
 | 
			
		||||
        let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
 | 
			
		||||
        pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
 | 
			
		||||
 | 
			
		||||
        // setup ui camera
 | 
			
		||||
        self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA));
 | 
			
		||||
        self.add_node_edge(node::UI_CAMERA, base_render_graph::node::MAIN_PASS)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
 | 
			
		||||
        let main_pass_node: &mut MainPassNode = self.get_node_mut(base_render_graph::node::MAIN_PASS).unwrap();
 | 
			
		||||
        main_pass_node.add_camera(camera::UI_CAMERA);
 | 
			
		||||
        active_cameras.add(camera::UI_CAMERA);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -23,10 +23,10 @@ fn camera_order_color_system(
 | 
			
		||||
    _material_query: &mut Query<Read<Handle<StandardMaterial>>>,
 | 
			
		||||
) {
 | 
			
		||||
    for (_camera, visible_entities) in camera_query.iter(world) {
 | 
			
		||||
        for visible_entity in visible_entities.value.iter() {
 | 
			
		||||
        for visible_entity in visible_entities.iter() {
 | 
			
		||||
            if let Some(material_handle) = world.get_component::<Handle<StandardMaterial>>(visible_entity.entity) {
 | 
			
		||||
                let material = materials.get_mut(&material_handle).unwrap();
 | 
			
		||||
                let value = 1.0 - (20.0 - visible_entity.order.0) / 7.0;
 | 
			
		||||
                let value = 1.0 - (20.0 + visible_entity.order.0) / 7.0;
 | 
			
		||||
                material.albedo = Color::rgb(value, value, value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user