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,29 +92,39 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
||||
}
|
||||
|
||||
if config.add_main_pass {
|
||||
let mut main_pass_node = MainPassNode::new(PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
stencil_read_only: false,
|
||||
depth_read_only: false,
|
||||
clear_depth: 1.0,
|
||||
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,
|
||||
MainPassNode::new(PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
stencil_read_only: false,
|
||||
depth_read_only: false,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
}),
|
||||
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 position = transform.value.w_axis().truncate();
|
||||
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,74 +91,88 @@ impl Node for MainPassNode {
|
||||
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
||||
}
|
||||
|
||||
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) {
|
||||
if !draw.is_visible {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
for render_command in draw.render_commands.iter() {
|
||||
match render_command {
|
||||
RenderCommand::SetPipeline { pipeline } => {
|
||||
// TODO: Filter pipelines
|
||||
render_pass.set_pipeline(*pipeline);
|
||||
let descriptor = pipelines.get(pipeline).unwrap();
|
||||
draw_state.set_pipeline(*pipeline, descriptor);
|
||||
}
|
||||
RenderCommand::DrawIndexed {
|
||||
base_vertex,
|
||||
indices,
|
||||
instances,
|
||||
} => {
|
||||
if draw_state.can_draw_indexed() {
|
||||
render_pass.draw_indexed(
|
||||
indices.clone(),
|
||||
*base_vertex,
|
||||
instances.clone(),
|
||||
);
|
||||
} else {
|
||||
log::info!("Could not draw indexed because the pipeline layout wasn't fully set for pipeline: {:?}", draw_state.pipeline);
|
||||
render_context.begin_pass(
|
||||
&self.descriptor,
|
||||
&render_resource_bindings,
|
||||
&mut |render_pass| {
|
||||
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) {
|
||||
draw
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !draw.is_visible {
|
||||
continue;
|
||||
}
|
||||
|
||||
for render_command in draw.render_commands.iter() {
|
||||
match render_command {
|
||||
RenderCommand::SetPipeline { pipeline } => {
|
||||
// TODO: Filter pipelines
|
||||
render_pass.set_pipeline(*pipeline);
|
||||
let descriptor = pipelines.get(pipeline).unwrap();
|
||||
draw_state.set_pipeline(*pipeline, descriptor);
|
||||
}
|
||||
RenderCommand::DrawIndexed {
|
||||
base_vertex,
|
||||
indices,
|
||||
instances,
|
||||
} => {
|
||||
if draw_state.can_draw_indexed() {
|
||||
render_pass.draw_indexed(
|
||||
indices.clone(),
|
||||
*base_vertex,
|
||||
instances.clone(),
|
||||
);
|
||||
} else {
|
||||
log::info!("Could not draw indexed because the pipeline layout wasn't fully set for pipeline: {:?}", draw_state.pipeline);
|
||||
}
|
||||
}
|
||||
RenderCommand::SetVertexBuffer {
|
||||
buffer,
|
||||
offset,
|
||||
slot,
|
||||
} => {
|
||||
render_pass.set_vertex_buffer(*slot, *buffer, *offset);
|
||||
draw_state.set_vertex_buffer(*slot, *buffer);
|
||||
}
|
||||
RenderCommand::SetIndexBuffer { buffer, offset } => {
|
||||
render_pass.set_index_buffer(*buffer, *offset);
|
||||
draw_state.set_index_buffer(*buffer)
|
||||
}
|
||||
RenderCommand::SetBindGroup {
|
||||
index,
|
||||
bind_group,
|
||||
dynamic_uniform_indices,
|
||||
} => {
|
||||
let pipeline = pipelines.get(&draw_state.pipeline.unwrap()).unwrap();
|
||||
let layout = pipeline.get_layout().unwrap();
|
||||
let bind_group_descriptor = layout.get_bind_group(*index).unwrap();
|
||||
render_pass.set_bind_group(
|
||||
*index,
|
||||
bind_group_descriptor.id,
|
||||
*bind_group,
|
||||
dynamic_uniform_indices
|
||||
.as_ref()
|
||||
.map(|indices| indices.as_slice()),
|
||||
);
|
||||
draw_state.set_bind_group(*index, *bind_group);
|
||||
}
|
||||
}
|
||||
RenderCommand::SetVertexBuffer {
|
||||
buffer,
|
||||
offset,
|
||||
slot,
|
||||
} => {
|
||||
render_pass.set_vertex_buffer(*slot, *buffer, *offset);
|
||||
draw_state.set_vertex_buffer(*slot, *buffer);
|
||||
}
|
||||
RenderCommand::SetIndexBuffer { buffer, offset } => {
|
||||
render_pass.set_index_buffer(*buffer, *offset);
|
||||
draw_state.set_index_buffer(*buffer)
|
||||
}
|
||||
RenderCommand::SetBindGroup {
|
||||
index,
|
||||
bind_group,
|
||||
dynamic_uniform_indices,
|
||||
} => {
|
||||
let pipeline = pipelines.get(&draw_state.pipeline.unwrap()).unwrap();
|
||||
let layout = pipeline.get_layout().unwrap();
|
||||
let bind_group_descriptor = layout.get_bind_group(*index).unwrap();
|
||||
render_pass.set_bind_group(
|
||||
*index,
|
||||
bind_group_descriptor.id,
|
||||
*bind_group,
|
||||
dynamic_uniform_indices
|
||||
.as_ref()
|
||||
.map(|indices| indices.as_slice()),
|
||||
);
|
||||
draw_state.set_bind_group(*index, *bind_group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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