render: add front-to-back drawing

MainPassNodes now have assigned cameras and draw using those camera's VisibleEntities
This commit is contained in:
Carter Anderson 2020-06-23 16:52:50 -07:00
parent ca8625c407
commit 41dc8a5967
5 changed files with 146 additions and 95 deletions

View File

@ -92,9 +92,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
} }
if config.add_main_pass { if config.add_main_pass {
self.add_node( let mut main_pass_node = MainPassNode::new(PassDescriptor {
node::MAIN_PASS,
MainPassNode::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,
@ -114,7 +112,19 @@ impl BaseRenderGraphBuilder for RenderGraph {
clear_stencil: 0, clear_stencil: 0,
}), }),
sample_count: 1, 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) self.add_node_edge(node::TEXTURE_COPY, node::MAIN_PASS)

View File

@ -17,24 +17,40 @@ pub struct VisibleEntities {
pub value: Vec<VisibleEntity>, pub value: Vec<VisibleEntity>,
} }
impl VisibleEntities {
pub fn iter(&self) -> impl DoubleEndedIterator<Item=&VisibleEntity> {
self.value.iter()
}
}
pub fn visible_entities_system( pub fn visible_entities_system(
world: &mut SubWorld, world: &mut SubWorld,
camera_query: &mut Query<(Read<Camera>, Read<Transform>, Write<VisibleEntities>)>, 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) { for (_camera, camera_transform, mut visible_entities) in camera_query.iter_mut(world) {
visible_entities.value.clear(); visible_entities.value.clear();
let camera_position = camera_transform.value.w_axis().truncate(); 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 { if !draw.is_visible {
continue; continue;
} }
let order = if let Some(transform) = world.get_component::<Transform>(entity) {
let position = transform.value.w_axis().truncate(); 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 { visible_entities.value.push(VisibleEntity {
entity, entity,
order: FloatOrd((camera_position - position).length()), order,
}) })
} }

View File

@ -4,7 +4,7 @@ use crate::{
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_graph::{Node, ResourceSlotInfo, ResourceSlots}, render_graph::{Node, ResourceSlotInfo, ResourceSlots},
render_resource::{BindGroupId, BufferId, RenderResourceBindings, RenderResourceType}, render_resource::{BindGroupId, BufferId, RenderResourceBindings, RenderResourceType},
renderer::RenderContext, renderer::RenderContext, ActiveCameras, VisibleEntities,
}; };
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use legion::prelude::*; use legion::prelude::*;
@ -12,6 +12,7 @@ use legion::prelude::*;
pub struct MainPassNode { pub struct MainPassNode {
descriptor: PassDescriptor, descriptor: PassDescriptor,
inputs: Vec<ResourceSlotInfo>, inputs: Vec<ResourceSlotInfo>,
cameras: Vec<String>,
color_attachment_input_indices: Vec<Option<usize>>, color_attachment_input_indices: Vec<Option<usize>>,
depth_stencil_attachment_input_index: Option<usize>, depth_stencil_attachment_input_index: Option<usize>,
} }
@ -46,10 +47,15 @@ impl MainPassNode {
MainPassNode { MainPassNode {
descriptor, descriptor,
inputs, inputs,
cameras: Vec::new(),
color_attachment_input_indices, color_attachment_input_indices,
depth_stencil_attachment_input_index, 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 { impl Node for MainPassNode {
@ -67,6 +73,7 @@ impl Node for MainPassNode {
) { ) {
let render_resource_bindings = resources.get::<RenderResourceBindings>().unwrap(); let render_resource_bindings = resources.get::<RenderResourceBindings>().unwrap();
let pipelines = resources.get::<Assets<PipelineDescriptor>>().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() { for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
if let Some(input_index) = self.color_attachment_input_indices[i] { 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()); 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( render_context.begin_pass(
&self.descriptor, &self.descriptor,
&render_resource_bindings, &render_resource_bindings,
&mut |render_pass| { &mut |render_pass| {
let mut draw_state = DrawState::default(); 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 { if !draw.is_visible {
continue; continue;
} }
@ -154,6 +174,7 @@ impl Node for MainPassNode {
); );
} }
} }
}
/// Tracks the current pipeline state to ensure draw calls are valid. /// Tracks the current pipeline state to ensure draw calls are valid.
#[derive(Default)] #[derive(Default)]

View File

@ -2,7 +2,7 @@ use bevy_asset::{Assets, Handle};
use bevy_render::{ use bevy_render::{
base_render_graph, base_render_graph,
pipeline::{state_descriptors::*, PipelineDescriptor}, pipeline::{state_descriptors::*, PipelineDescriptor},
render_graph::{nodes::CameraNode, RenderGraph}, render_graph::{nodes::{MainPassNode, CameraNode}, RenderGraph},
shader::{Shader, ShaderStage, ShaderStages}, shader::{Shader, ShaderStage, ShaderStages},
texture::TextureFormat, ActiveCameras, texture::TextureFormat, ActiveCameras,
}; };
@ -70,13 +70,17 @@ pub trait UiRenderGraphBuilder {
impl UiRenderGraphBuilder for RenderGraph { impl UiRenderGraphBuilder for RenderGraph {
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self { 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 pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
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));
// 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 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); active_cameras.add(camera::UI_CAMERA);
self self
} }

View File

@ -23,10 +23,10 @@ fn camera_order_color_system(
_material_query: &mut Query<Read<Handle<StandardMaterial>>>, _material_query: &mut Query<Read<Handle<StandardMaterial>>>,
) { ) {
for (_camera, visible_entities) in camera_query.iter(world) { 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) { if let Some(material_handle) = world.get_component::<Handle<StandardMaterial>>(visible_entity.entity) {
let material = materials.get_mut(&material_handle).unwrap(); 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); material.albedo = Color::rgb(value, value, value);
} }
} }