mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
RenderGraph2: Lights node
This commit is contained in:
parent
c124cbe22f
commit
06b6ade902
3 changed files with 168 additions and 7 deletions
|
@ -39,8 +39,7 @@ use self::{
|
|||
},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
entity_render_resource_assignments_system,
|
||||
resource_providers::{LightResourceProvider, UniformResourceProvider},
|
||||
entity_render_resource_assignments_system, resource_providers::UniformResourceProvider,
|
||||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||
},
|
||||
shader::{uniforms::StandardMaterial, Shader},
|
||||
|
@ -54,7 +53,10 @@ use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
|||
use pass::PassDescriptor;
|
||||
use pipeline::pipelines::build_forward_pipeline;
|
||||
use render_graph_2::{
|
||||
nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode, UniformNode},
|
||||
nodes::{
|
||||
Camera2dNode, CameraNode, LightsNode, PassNode, UniformNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
RenderGraph2,
|
||||
};
|
||||
use render_resource::resource_providers::mesh_resource_provider_system;
|
||||
|
@ -77,7 +79,6 @@ impl RenderPlugin {
|
|||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph
|
||||
.build(&mut pipelines, &mut shaders)
|
||||
.add_resource_provider(LightResourceProvider::new(10))
|
||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true));
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +124,12 @@ impl AppPlugin for RenderPlugin {
|
|||
let resources = app.resources_mut();
|
||||
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("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(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::new(
|
||||
|
@ -185,7 +191,10 @@ impl AppPlugin for RenderPlugin {
|
|||
// TODO: replace these with "autowire" groups
|
||||
render_graph.add_node_edge("camera", "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
|
||||
.add_slot_edge(
|
||||
"swapchain",
|
||||
|
|
|
@ -4,10 +4,12 @@ mod window_texture_node;
|
|||
mod window_swapchain_node;
|
||||
mod pass_node;
|
||||
mod uniform_node;
|
||||
mod lights_node;
|
||||
|
||||
pub use camera_node::*;
|
||||
pub use camera2d_node::*;
|
||||
pub use window_texture_node::*;
|
||||
pub use window_swapchain_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 a new issue