RenderGraph2: Lights node
This commit is contained in:
parent
c124cbe22f
commit
06b6ade902
@ -39,8 +39,7 @@ use self::{
|
|||||||
},
|
},
|
||||||
render_graph::RenderGraph,
|
render_graph::RenderGraph,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
entity_render_resource_assignments_system,
|
entity_render_resource_assignments_system, resource_providers::UniformResourceProvider,
|
||||||
resource_providers::{LightResourceProvider, UniformResourceProvider},
|
|
||||||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||||
},
|
},
|
||||||
shader::{uniforms::StandardMaterial, Shader},
|
shader::{uniforms::StandardMaterial, Shader},
|
||||||
@ -54,7 +53,10 @@ use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
|||||||
use pass::PassDescriptor;
|
use pass::PassDescriptor;
|
||||||
use pipeline::pipelines::build_forward_pipeline;
|
use pipeline::pipelines::build_forward_pipeline;
|
||||||
use render_graph_2::{
|
use render_graph_2::{
|
||||||
nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode, UniformNode},
|
nodes::{
|
||||||
|
Camera2dNode, CameraNode, LightsNode, PassNode, UniformNode, WindowSwapChainNode,
|
||||||
|
WindowTextureNode,
|
||||||
|
},
|
||||||
RenderGraph2,
|
RenderGraph2,
|
||||||
};
|
};
|
||||||
use render_resource::resource_providers::mesh_resource_provider_system;
|
use render_resource::resource_providers::mesh_resource_provider_system;
|
||||||
@ -77,7 +79,6 @@ impl RenderPlugin {
|
|||||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||||
render_graph
|
render_graph
|
||||||
.build(&mut pipelines, &mut shaders)
|
.build(&mut pipelines, &mut shaders)
|
||||||
.add_resource_provider(LightResourceProvider::new(10))
|
|
||||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true));
|
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +124,12 @@ impl AppPlugin for RenderPlugin {
|
|||||||
let resources = app.resources_mut();
|
let resources = app.resources_mut();
|
||||||
render_graph.add_system_node_named("camera", CameraNode::default(), resources);
|
render_graph.add_system_node_named("camera", CameraNode::default(), resources);
|
||||||
render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources);
|
render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources);
|
||||||
render_graph.add_system_node_named("standard_material", UniformNode::<StandardMaterial>::new(true), resources);
|
render_graph.add_system_node_named(
|
||||||
|
"standard_material",
|
||||||
|
UniformNode::<StandardMaterial>::new(true),
|
||||||
|
resources,
|
||||||
|
);
|
||||||
|
render_graph.add_system_node_named("lights", LightsNode::new(10), resources);
|
||||||
render_graph.add_node_named(
|
render_graph.add_node_named(
|
||||||
"swapchain",
|
"swapchain",
|
||||||
WindowSwapChainNode::new(
|
WindowSwapChainNode::new(
|
||||||
@ -185,7 +191,10 @@ impl AppPlugin for RenderPlugin {
|
|||||||
// TODO: replace these with "autowire" groups
|
// TODO: replace these with "autowire" groups
|
||||||
render_graph.add_node_edge("camera", "main_pass").unwrap();
|
render_graph.add_node_edge("camera", "main_pass").unwrap();
|
||||||
render_graph.add_node_edge("camera2d", "main_pass").unwrap();
|
render_graph.add_node_edge("camera2d", "main_pass").unwrap();
|
||||||
render_graph.add_node_edge("standard_material", "main_pass").unwrap();
|
render_graph
|
||||||
|
.add_node_edge("standard_material", "main_pass")
|
||||||
|
.unwrap();
|
||||||
|
render_graph.add_node_edge("lights", "main_pass").unwrap();
|
||||||
render_graph
|
render_graph
|
||||||
.add_slot_edge(
|
.add_slot_edge(
|
||||||
"swapchain",
|
"swapchain",
|
||||||
|
|||||||
@ -4,10 +4,12 @@ mod window_texture_node;
|
|||||||
mod window_swapchain_node;
|
mod window_swapchain_node;
|
||||||
mod pass_node;
|
mod pass_node;
|
||||||
mod uniform_node;
|
mod uniform_node;
|
||||||
|
mod lights_node;
|
||||||
|
|
||||||
pub use camera_node::*;
|
pub use camera_node::*;
|
||||||
pub use camera2d_node::*;
|
pub use camera2d_node::*;
|
||||||
pub use window_texture_node::*;
|
pub use window_texture_node::*;
|
||||||
pub use window_swapchain_node::*;
|
pub use window_swapchain_node::*;
|
||||||
pub use pass_node::*;
|
pub use pass_node::*;
|
||||||
pub use uniform_node::*;
|
pub use uniform_node::*;
|
||||||
|
pub use lights_node::*;
|
||||||
150
bevy_render/src/render_graph_2/nodes/lights_node.rs
Normal file
150
bevy_render/src/render_graph_2/nodes/lights_node.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use crate::{
|
||||||
|
render_graph_2::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
|
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||||
|
renderer_2::{GlobalRenderResourceContext, RenderContext},
|
||||||
|
Light, LightRaw,
|
||||||
|
};
|
||||||
|
|
||||||
|
use bevy_transform::prelude::*;
|
||||||
|
use legion::prelude::*;
|
||||||
|
use zerocopy::AsBytes;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LightsNode {
|
||||||
|
command_queue: CommandQueue,
|
||||||
|
max_lights: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightsNode {
|
||||||
|
pub fn new(max_lights: usize) -> Self {
|
||||||
|
LightsNode {
|
||||||
|
max_lights,
|
||||||
|
command_queue: CommandQueue::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node for LightsNode {
|
||||||
|
fn update(
|
||||||
|
&mut self,
|
||||||
|
_world: &World,
|
||||||
|
_resources: &Resources,
|
||||||
|
render_context: &mut dyn RenderContext,
|
||||||
|
_input: &ResourceSlots,
|
||||||
|
_output: &mut ResourceSlots,
|
||||||
|
) {
|
||||||
|
self.command_queue.execute(render_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, AsBytes)]
|
||||||
|
pub struct LightCount {
|
||||||
|
pub num_lights: [u32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SystemNode for LightsNode {
|
||||||
|
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||||
|
let mut light_buffer = None;
|
||||||
|
let mut lights_are_dirty = true;
|
||||||
|
// TODO: merge these
|
||||||
|
let mut tmp_count_buffer = None;
|
||||||
|
let mut tmp_light_buffer = None;
|
||||||
|
let mut command_queue = self.command_queue.clone();
|
||||||
|
let max_lights = self.max_lights;
|
||||||
|
SystemBuilder::new("light_node")
|
||||||
|
.read_resource::<GlobalRenderResourceContext>()
|
||||||
|
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||||
|
.write_resource::<RenderResourceAssignments>()
|
||||||
|
.with_query(<(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query())
|
||||||
|
.build(
|
||||||
|
move |_,
|
||||||
|
world,
|
||||||
|
(render_resource_context, ref mut render_resource_assignments),
|
||||||
|
query| {
|
||||||
|
if !lights_are_dirty {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let render_resources = &render_resource_context.context;
|
||||||
|
if light_buffer.is_none() {
|
||||||
|
let light_uniform_size = std::mem::size_of::<LightCount>()
|
||||||
|
+ max_lights * std::mem::size_of::<LightRaw>();
|
||||||
|
|
||||||
|
let buffer = render_resources.create_buffer(BufferInfo {
|
||||||
|
size: light_uniform_size,
|
||||||
|
buffer_usage: BufferUsage::UNIFORM
|
||||||
|
| BufferUsage::COPY_SRC
|
||||||
|
| BufferUsage::COPY_DST,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer);
|
||||||
|
light_buffer = Some(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let light_count = query.iter(world).count();
|
||||||
|
|
||||||
|
if light_count == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lights_are_dirty = false;
|
||||||
|
let size = std::mem::size_of::<LightRaw>();
|
||||||
|
let total_size = size * light_count;
|
||||||
|
let light_count_size = std::mem::size_of::<LightCount>();
|
||||||
|
|
||||||
|
if let Some(old_tmp_light_buffer) = tmp_light_buffer {
|
||||||
|
render_resources.remove_buffer(old_tmp_light_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(old_tmp_count_buffer) = tmp_count_buffer {
|
||||||
|
render_resources.remove_buffer(old_tmp_count_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_light_buffer = Some(render_resources.create_buffer_mapped(
|
||||||
|
BufferInfo {
|
||||||
|
size: total_size,
|
||||||
|
buffer_usage: BufferUsage::COPY_SRC,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&mut |data, _renderer| {
|
||||||
|
for ((light, local_to_world, translation), slot) in
|
||||||
|
query.iter(world).zip(data.chunks_exact_mut(size))
|
||||||
|
{
|
||||||
|
slot.copy_from_slice(
|
||||||
|
LightRaw::from(&light, &local_to_world.0, &translation)
|
||||||
|
.as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
tmp_count_buffer = Some(render_resources.create_buffer_mapped(
|
||||||
|
BufferInfo {
|
||||||
|
size: light_count_size,
|
||||||
|
buffer_usage: BufferUsage::COPY_SRC,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&mut |data, _renderer| {
|
||||||
|
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
command_queue.copy_buffer_to_buffer(
|
||||||
|
tmp_count_buffer.unwrap(),
|
||||||
|
0,
|
||||||
|
light_buffer.unwrap(),
|
||||||
|
0,
|
||||||
|
light_count_size as u64,
|
||||||
|
);
|
||||||
|
|
||||||
|
command_queue.copy_buffer_to_buffer(
|
||||||
|
tmp_light_buffer.unwrap(),
|
||||||
|
0,
|
||||||
|
light_buffer.unwrap(),
|
||||||
|
light_count_size as u64,
|
||||||
|
total_size as u64,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user