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 {
|
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)
|
||||||
|
|||||||
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)]
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user