mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Avoid extra set_pipeline calls
This commit is contained in:
parent
b2f94c1485
commit
624183e3f3
@ -42,8 +42,9 @@ pub use self::{
|
||||
},
|
||||
renderer::{
|
||||
drawer::{
|
||||
Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer,
|
||||
ShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
ChunkSpriteDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer,
|
||||
ParticleDrawer, PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer,
|
||||
TerrainDrawer, TerrainShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
},
|
||||
ColLightInfo, Renderer,
|
||||
},
|
||||
|
@ -36,6 +36,38 @@ impl<'a> Drawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shadow_pass(&mut self) -> Option<ShadowPassDrawer> {
|
||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
||||
let mut render_pass =
|
||||
self.encoder
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(
|
||||
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &shadow_renderer.directed_depth.view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||
|
||||
Some(ShadowPassDrawer {
|
||||
render_pass,
|
||||
renderer: &self.renderer,
|
||||
shadow_renderer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn first_pass(&mut self) -> FirstPassDrawer {
|
||||
let mut render_pass =
|
||||
self.encoder
|
||||
@ -71,38 +103,6 @@ impl<'a> Drawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shadow_pass(&mut self) -> Option<ShadowDrawer> {
|
||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
||||
let mut render_pass =
|
||||
self.encoder
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(
|
||||
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &shadow_renderer.directed_depth.view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||
|
||||
Some(ShadowDrawer {
|
||||
render_pass,
|
||||
renderer: &self.renderer,
|
||||
shadow_renderer,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn second_pass(&mut self) -> SecondPassDrawer {
|
||||
let mut render_pass =
|
||||
self.encoder
|
||||
@ -154,10 +154,11 @@ impl<'a> Drawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_point_shadow<'b: 'a>(
|
||||
pub fn draw_point_shadows<'data: 'a>(
|
||||
&mut self,
|
||||
matrices: &[shadow::PointLightMatrix; 126],
|
||||
chunks: impl Clone + Iterator<Item = (&'b Model<terrain::Vertex>, &'b terrain::BoundLocals)>,
|
||||
chunks: impl Clone
|
||||
+ Iterator<Item = (&'data Model<terrain::Vertex>, &'data terrain::BoundLocals)>,
|
||||
) {
|
||||
if let ShadowMap::Enabled(ref shadow_renderer) = self.renderer.shadow_map {
|
||||
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
|
||||
@ -228,57 +229,110 @@ impl<'a> Drop for Drawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FirstPassDrawer<'a> {
|
||||
pub(super) render_pass: wgpu::RenderPass<'a>,
|
||||
pub renderer: &'a Renderer,
|
||||
// Shadow pass
|
||||
pub struct ShadowPassDrawer<'pass> {
|
||||
render_pass: wgpu::RenderPass<'pass>,
|
||||
pub renderer: &'pass Renderer,
|
||||
shadow_renderer: &'pass ShadowMapRenderer,
|
||||
}
|
||||
|
||||
impl<'a> FirstPassDrawer<'a> {
|
||||
pub fn draw_skybox<'b: 'a>(&mut self, model: &'b Model<skybox::Vertex>) {
|
||||
impl<'pass> ShadowPassDrawer<'pass> {
|
||||
pub fn draw_figure_shadows(&mut self) -> FigureShadowDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
|
||||
|
||||
FigureShadowDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_terrain_shadows(&mut self) -> TerrainShadowDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
|
||||
|
||||
TerrainShadowDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FigureShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> FigureShadowDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: SubModel<'data, terrain::Vertex>,
|
||||
locals: &'data figure::BoundLocals,
|
||||
) {
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf());
|
||||
self.render_pass.draw(0..model.len(), 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TerrainShadowDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> TerrainShadowDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'data Model<terrain::Vertex>,
|
||||
locals: &'data terrain::BoundLocals,
|
||||
) {
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
// First pass
|
||||
pub struct FirstPassDrawer<'pass> {
|
||||
pub(super) render_pass: wgpu::RenderPass<'pass>,
|
||||
pub renderer: &'pass Renderer,
|
||||
}
|
||||
|
||||
impl<'pass> FirstPassDrawer<'pass> {
|
||||
pub fn draw_skybox<'data: 'pass>(&mut self, model: &'data Model<skybox::Vertex>) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.skybox_pipeline.pipeline);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||
}
|
||||
|
||||
pub fn draw_lod_terrain<'b: 'a>(&mut self, model: &'b Model<lod_terrain::Vertex>) {
|
||||
pub fn draw_lod_terrain<'data: 'pass>(&mut self, model: &'data Model<lod_terrain::Vertex>) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.lod_terrain_pipeline.pipeline);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||
}
|
||||
|
||||
pub fn draw_figure<'b: 'a>(
|
||||
&mut self,
|
||||
model: SubModel<'b, terrain::Vertex>,
|
||||
locals: &'b figure::BoundLocals,
|
||||
col_lights: &'b ColLights<figure::Locals>,
|
||||
) {
|
||||
pub fn draw_figures(&mut self) -> FigureDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(3, &col_lights.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf());
|
||||
self.render_pass.draw(0..model.len(), 0..1);
|
||||
|
||||
FigureDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_terrain<'b: 'a>(
|
||||
pub fn draw_terrain<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'b Model<terrain::Vertex>,
|
||||
locals: &'b terrain::BoundLocals,
|
||||
col_lights: &'b ColLights<terrain::Locals>,
|
||||
) {
|
||||
col_lights: &'data ColLights<terrain::Locals>,
|
||||
) -> TerrainDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(3, &col_lights.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1)
|
||||
|
||||
TerrainDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'a> {
|
||||
pub fn draw_particles(&mut self) -> ParticleDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.particle_pipeline.pipeline);
|
||||
|
||||
@ -287,29 +341,24 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_sprite<'b: 'a>(
|
||||
pub fn draw_sprites<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'b Model<sprite::Vertex>,
|
||||
instances: &'b Instances<sprite::Instance>,
|
||||
terrain_locals: &'b terrain::BoundLocals,
|
||||
locals: &'b sprite::BoundLocals,
|
||||
col_lights: &'b ColLights<sprite::Locals>,
|
||||
) {
|
||||
col_lights: &'data ColLights<sprite::Locals>,
|
||||
) -> SpriteDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
|
||||
self.render_pass
|
||||
.set_bind_group(2, &terrain_locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(4, &col_lights.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass
|
||||
.set_vertex_buffer(1, instances.buf().slice(..));
|
||||
self.render_pass
|
||||
.draw(0..model.len() as u32, 0..instances.count() as u32);
|
||||
|
||||
SpriteDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> {
|
||||
pub fn draw_fluid<'data: 'pass>(
|
||||
&mut self,
|
||||
waves: &'data fluid::BindGroup,
|
||||
) -> FluidDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(2, &waves.bind_group, &[]);
|
||||
@ -320,6 +369,42 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FigureDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> FigureDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: SubModel<'data, terrain::Vertex>,
|
||||
locals: &'data figure::BoundLocals,
|
||||
// TODO: don't rebind this every time once they are shared between figures
|
||||
col_lights: &'data ColLights<figure::Locals>,
|
||||
) {
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(3, &col_lights.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf());
|
||||
self.render_pass.draw(0..model.len(), 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TerrainDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> TerrainDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'data Model<terrain::Vertex>,
|
||||
locals: &'data terrain::BoundLocals,
|
||||
) {
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
@ -341,35 +426,40 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShadowDrawer<'pass> {
|
||||
render_pass: wgpu::RenderPass<'pass>,
|
||||
pub renderer: &'pass Renderer,
|
||||
shadow_renderer: &'pass ShadowMapRenderer,
|
||||
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass> ShadowDrawer<'pass> {
|
||||
pub fn draw_figure_shadow<'b: 'pass>(
|
||||
impl<'pass_ref, 'pass: 'pass_ref> SpriteDrawer<'pass_ref, 'pass> {
|
||||
pub fn in_chunk<'data: 'pass>(
|
||||
&mut self,
|
||||
model: SubModel<'b, terrain::Vertex>,
|
||||
locals: &'b figure::BoundLocals,
|
||||
) {
|
||||
terrain_locals: &'data terrain::BoundLocals,
|
||||
) -> ChunkSpriteDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.shadow_renderer.figure_directed_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf());
|
||||
self.render_pass.draw(0..model.len(), 0..1);
|
||||
}
|
||||
.set_bind_group(2, &terrain_locals.bind_group, &[]);
|
||||
|
||||
pub fn draw_terrain_shadow<'b: 'pass>(
|
||||
ChunkSpriteDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct ChunkSpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> ChunkSpriteDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'b Model<terrain::Vertex>,
|
||||
locals: &'b terrain::BoundLocals,
|
||||
model: &'data Model<sprite::Vertex>,
|
||||
instances: &'data Instances<sprite::Instance>,
|
||||
locals: &'data sprite::BoundLocals,
|
||||
) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.shadow_renderer.terrain_directed_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||
self.render_pass
|
||||
.set_vertex_buffer(1, instances.buf().slice(..));
|
||||
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.draw(0..model.len() as u32, 0..instances.count() as u32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,13 +479,14 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SecondPassDrawer<'a> {
|
||||
pub(super) render_pass: wgpu::RenderPass<'a>,
|
||||
pub renderer: &'a Renderer,
|
||||
// Second pass: clouds
|
||||
pub struct SecondPassDrawer<'pass> {
|
||||
pub(super) render_pass: wgpu::RenderPass<'pass>,
|
||||
pub renderer: &'pass Renderer,
|
||||
}
|
||||
|
||||
impl<'a> SecondPassDrawer<'a> {
|
||||
pub fn draw_clouds<'b: 'a>(&mut self) {
|
||||
impl<'pass> SecondPassDrawer<'pass> {
|
||||
pub fn draw_clouds(&mut self) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.clouds_pipeline.pipeline);
|
||||
self.render_pass
|
||||
@ -404,13 +495,14 @@ impl<'a> SecondPassDrawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThirdPassDrawer<'a> {
|
||||
render_pass: wgpu::RenderPass<'a>,
|
||||
renderer: &'a Renderer,
|
||||
// Third pass: postprocess + ui
|
||||
pub struct ThirdPassDrawer<'pass> {
|
||||
render_pass: wgpu::RenderPass<'pass>,
|
||||
renderer: &'pass Renderer,
|
||||
}
|
||||
|
||||
impl<'a> ThirdPassDrawer<'a> {
|
||||
pub fn draw_post_process<'b: 'a>(&mut self) {
|
||||
impl<'pass> ThirdPassDrawer<'pass> {
|
||||
pub fn draw_post_process(&mut self) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.postprocess_pipeline.pipeline);
|
||||
self.render_pass
|
||||
@ -418,7 +510,7 @@ impl<'a> ThirdPassDrawer<'a> {
|
||||
self.render_pass.draw(0..3, 0..1);
|
||||
}
|
||||
|
||||
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'a> {
|
||||
pub fn draw_ui(&mut self) -> UiDrawer<'_, 'pass> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.ui_pipeline.pipeline);
|
||||
|
||||
@ -443,7 +535,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
|
||||
pub fn prepare<'data: 'pass>(
|
||||
&mut self,
|
||||
locals: &'data ui::BoundLocals,
|
||||
//texture: &'b ui::TextureBindGroup,
|
||||
//texture: &'data ui::TextureBindGroup,
|
||||
buf: &'data DynamicModel<ui::Vertex>,
|
||||
scissor: Aabr<u16>,
|
||||
) -> PreparedUiDrawer<'_, 'pass> {
|
||||
@ -467,8 +559,9 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
}
|
||||
|
||||
//pub fn set_texture<'b: 'a>(&mut self, texture: &'b ui::TextureBindGroup) {
|
||||
// self.render_pass.set_bind_group(1, &texture.bind_group, &[]);
|
||||
//pub fn set_texture<'data: 'pass>(&mut self, texture: &'data
|
||||
// ui::TextureBindGroup) { self.render_pass.set_bind_group(1,
|
||||
// &texture.bind_group, &[]);
|
||||
//}
|
||||
|
||||
pub fn set_model<'data: 'pass>(&mut self, model: &'data DynamicModel<ui::Vertex>) {
|
||||
|
@ -8,8 +8,9 @@ use crate::{
|
||||
ecs::comp::Interpolated,
|
||||
render::{
|
||||
pipelines::{self, ColLights},
|
||||
ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel,
|
||||
LodData, Mesh, RenderError, Renderer, ShadowDrawer, SubModel, TerrainVertex,
|
||||
ColLightInfo, FigureBoneData, FigureDrawer, FigureLocals, FigureModel, FigureShadowDrawer,
|
||||
FirstPassDrawer, GlobalModel, LodData, Mesh, RenderError, Renderer, SubModel,
|
||||
TerrainVertex,
|
||||
},
|
||||
scene::{
|
||||
camera::{Camera, CameraMode, Dependents},
|
||||
@ -4397,7 +4398,7 @@ impl FigureMgr {
|
||||
|
||||
pub fn render_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
drawer: &mut FigureShadowDrawer<'_, 'a>,
|
||||
state: &State,
|
||||
tick: u64,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
@ -4430,7 +4431,7 @@ impl FigureMgr {
|
||||
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||
|state| state.can_shadow_sun(),
|
||||
) {
|
||||
drawer.draw_figure_shadow(model, bound);
|
||||
drawer.draw(model, bound);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -4438,12 +4439,10 @@ impl FigureMgr {
|
||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||
pub fn render<'a>(
|
||||
&'a self,
|
||||
drawer: &mut FirstPassDrawer<'a>,
|
||||
drawer: &mut FigureDrawer<'_, 'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
span!(_guard, "render", "FigureManager::render");
|
||||
@ -4452,36 +4451,33 @@ impl FigureMgr {
|
||||
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
||||
let character_state = character_state_storage.get(player_entity);
|
||||
|
||||
for (entity, pos, _, body, _, inventory, scale) in (
|
||||
for (entity, pos, body, _, inventory, scale) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
ecs.read_storage::<Ori>().maybe(),
|
||||
&ecs.read_storage::<Body>(),
|
||||
ecs.read_storage::<Health>().maybe(),
|
||||
ecs.read_storage::<Inventory>().maybe(),
|
||||
ecs.read_storage::<Scale>().maybe(),
|
||||
ecs.read_storage::<Scale>().maybe()
|
||||
)
|
||||
.join()
|
||||
// Don't render dead entities
|
||||
.filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead))
|
||||
.filter(|(_, _, _, health, _)| health.map_or(true, |h| !h.is_dead))
|
||||
// Don't render player
|
||||
.filter(|(entity, _, _, _, _)| *entity != player_entity)
|
||||
{
|
||||
let is_player = entity == player_entity;
|
||||
|
||||
if !is_player {
|
||||
if let Some((bound, model, col_lights)) = self.get_model_for_render(
|
||||
tick,
|
||||
camera,
|
||||
character_state,
|
||||
entity,
|
||||
body,
|
||||
inventory,
|
||||
false,
|
||||
pos.0,
|
||||
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||
|state| state.visible(),
|
||||
) {
|
||||
drawer.draw_figure(model, bound, col_lights);
|
||||
}
|
||||
if let Some((bound, model, col_lights)) = self.get_model_for_render(
|
||||
tick,
|
||||
camera,
|
||||
character_state,
|
||||
entity,
|
||||
body,
|
||||
inventory,
|
||||
false,
|
||||
pos.0,
|
||||
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||
|state| state.visible(),
|
||||
) {
|
||||
drawer.draw(model, bound, col_lights);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4489,12 +4485,10 @@ impl FigureMgr {
|
||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||
pub fn render_player<'a>(
|
||||
&'a self,
|
||||
drawer: &mut FirstPassDrawer<'a>,
|
||||
drawer: &mut FigureDrawer<'_, 'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
global: &GlobalModel,
|
||||
lod: &LodData,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
span!(_guard, "render_player", "FigureManager::render_player");
|
||||
@ -4528,7 +4522,7 @@ impl FigureMgr {
|
||||
figure_lod_render_distance,
|
||||
|state| state.visible(),
|
||||
) {
|
||||
drawer.draw_figure(model, bound, col_lights);
|
||||
drawer.draw(model, bound, col_lights);
|
||||
/*renderer.render_player_shadow(
|
||||
model,
|
||||
&col_lights,
|
||||
|
@ -18,7 +18,7 @@ use crate::{
|
||||
render::{
|
||||
create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals,
|
||||
GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow,
|
||||
ShadowDrawer, ShadowLocals, SkyboxVertex,
|
||||
ShadowLocals, SkyboxVertex,
|
||||
},
|
||||
settings::Settings,
|
||||
window::{AnalogGameInput, Event},
|
||||
@ -1034,90 +1034,10 @@ impl Scene {
|
||||
|
||||
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
|
||||
|
||||
pub fn render_terrain_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
scene_data: &SceneData,
|
||||
) {
|
||||
let sun_dir = scene_data.get_sun_dir();
|
||||
let is_daylight = sun_dir.z < 0.0;
|
||||
let focus_pos = self.camera.get_focus_pos();
|
||||
let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
|
||||
let global = &self.data;
|
||||
let light_data = (is_daylight, &*self.light_data);
|
||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||
|
||||
// would instead have this as an extension.
|
||||
if drawer.renderer.render_mode().shadow.is_map()
|
||||
&& (is_daylight || !light_data.1.is_empty())
|
||||
{
|
||||
// Render terrain shadows.
|
||||
self.terrain
|
||||
.render_shadows(drawer, global, light_data, focus_pos);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_point_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut Drawer<'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
scene_data: &SceneData,
|
||||
) {
|
||||
let sun_dir = scene_data.get_sun_dir();
|
||||
let is_daylight = sun_dir.z < 0.0;
|
||||
let focus_pos = self.camera.get_focus_pos();
|
||||
let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
|
||||
let global = &self.data;
|
||||
let light_data = (is_daylight, &*self.light_data);
|
||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||
|
||||
if drawer.renderer.render_mode().shadow.is_map()
|
||||
&& (is_daylight || !light_data.1.is_empty())
|
||||
{
|
||||
// Render terrain shadows.
|
||||
self.terrain
|
||||
.render_point_shadows(drawer, global, light_data, focus_pos);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_figure_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
scene_data: &SceneData,
|
||||
) {
|
||||
let sun_dir = scene_data.get_sun_dir();
|
||||
let is_daylight = sun_dir.z < 0.0;
|
||||
let focus_pos = self.camera.get_focus_pos();
|
||||
let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
|
||||
let global = &self.data;
|
||||
let light_data = (is_daylight, &*self.light_data);
|
||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||
|
||||
// would instead have this as an extension.
|
||||
if drawer.renderer.render_mode().shadow.is_map()
|
||||
&& (is_daylight || !light_data.1.is_empty())
|
||||
{
|
||||
// Render figure shadows.
|
||||
self.figure_mgr
|
||||
.render_shadows(drawer, state, tick, camera_data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the scene using the provided `FirstPassDrawer`.
|
||||
/// Render the scene using the provided `Drawer`.
|
||||
pub fn render<'a>(
|
||||
&'a self,
|
||||
drawer: &mut FirstPassDrawer<'a>,
|
||||
drawer: &mut Drawer<'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
tick: u64,
|
||||
@ -1129,26 +1049,63 @@ impl Scene {
|
||||
let focus_pos = self.camera.get_focus_pos();
|
||||
let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
|
||||
let global = &self.data;
|
||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||
|
||||
let lod = self.lod.get_data();
|
||||
// would instead have this as an extension.
|
||||
if drawer.renderer.render_mode().shadow.is_map()
|
||||
&& (is_daylight || !self.light_data.is_empty())
|
||||
{
|
||||
if is_daylight {
|
||||
if let Some(mut shadow_pass) = drawer.shadow_pass() {
|
||||
// Render terrain directed shadows.
|
||||
self.terrain
|
||||
.render_shadows(&mut shadow_pass.draw_terrain_shadows(), focus_pos);
|
||||
|
||||
self.figure_mgr
|
||||
.render_player(drawer, state, player_entity, tick, global, lod, camera_data);
|
||||
// Render figure directed shadows.
|
||||
self.figure_mgr.render_shadows(
|
||||
&mut shadow_pass.draw_figure_shadows(),
|
||||
state,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.terrain.render(drawer, focus_pos);
|
||||
// Render terrain point light shadows.
|
||||
drawer.draw_point_shadows(
|
||||
&self.data.point_light_matrices,
|
||||
self.terrain.chunks_for_point_shadows(focus_pos),
|
||||
)
|
||||
}
|
||||
|
||||
self.figure_mgr
|
||||
.render(drawer, state, player_entity, tick, global, lod, camera_data);
|
||||
let mut first_pass = drawer.first_pass();
|
||||
|
||||
self.lod.render(drawer);
|
||||
self.figure_mgr.render_player(
|
||||
&mut first_pass.draw_figures(),
|
||||
state,
|
||||
player_entity,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
|
||||
self.terrain.render(&mut first_pass, focus_pos);
|
||||
|
||||
self.figure_mgr.render(
|
||||
&mut first_pass.draw_figures(),
|
||||
state,
|
||||
player_entity,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
|
||||
self.lod.render(&mut first_pass);
|
||||
|
||||
// Render the skybox.
|
||||
drawer.draw_skybox(&self.skybox.model);
|
||||
first_pass.draw_skybox(&self.skybox.model);
|
||||
|
||||
// Draws translucent terrain and sprites
|
||||
self.terrain.render_translucent(
|
||||
drawer,
|
||||
&mut first_pass,
|
||||
focus_pos,
|
||||
cam_pos,
|
||||
scene_data.sprite_render_distance,
|
||||
@ -1156,6 +1113,6 @@ impl Scene {
|
||||
|
||||
// Render particle effects.
|
||||
self.particle_mgr
|
||||
.render(&mut drawer.draw_particles(), scene_data);
|
||||
.render(&mut first_pass.draw_particles(), scene_data);
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +354,7 @@ impl Scene {
|
||||
body: Option<humanoid::Body>,
|
||||
inventory: Option<&Inventory>,
|
||||
) {
|
||||
let mut figure_drawer = drawer.draw_figures();
|
||||
if let Some(body) = body {
|
||||
let model = &self.figure_model_cache.get_model(
|
||||
&self.col_lights,
|
||||
@ -365,7 +366,7 @@ impl Scene {
|
||||
);
|
||||
|
||||
if let Some(model) = model {
|
||||
drawer.draw_figure(
|
||||
figure_drawer.draw(
|
||||
model.lod_model(0),
|
||||
self.figure_state.bound(),
|
||||
&self.col_lights.texture(model),
|
||||
@ -374,7 +375,7 @@ impl Scene {
|
||||
}
|
||||
|
||||
if let Some((model, state)) = &self.backdrop {
|
||||
drawer.draw_figure(
|
||||
figure_drawer.draw(
|
||||
model.lod_model(0),
|
||||
state.bound(),
|
||||
&self.col_lights.texture(model),
|
||||
|
@ -10,8 +10,8 @@ use crate::{
|
||||
render::{
|
||||
pipelines::{self, ColLights},
|
||||
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel,
|
||||
Instances, LodData, Mesh, Model, RenderError, Renderer, ShadowDrawer, SpriteInstance,
|
||||
SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture,
|
||||
Instances, LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals,
|
||||
SpriteVertex, TerrainLocals, TerrainShadowDrawer, TerrainVertex, Texture,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1264,9 +1264,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
|
||||
pub fn render_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, light_data): super::LightData,
|
||||
drawer: &mut TerrainShadowDrawer<'_, 'a>,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
span!(_guard, "render_shadows", "Terrain::render_shadows");
|
||||
@ -1286,28 +1284,28 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
// NOTE: We also render shadows for dead chunks that were found to still be
|
||||
// potential shadow casters, to avoid shadows suddenly disappearing at
|
||||
// very steep sun angles (e.g. sunrise / sunset).
|
||||
if is_daylight {
|
||||
chunk_iter
|
||||
.clone()
|
||||
.filter(|chunk| chunk.can_shadow_sun())
|
||||
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
||||
.for_each(|chunk| drawer.draw_terrain_shadow(&chunk.opaque_model, &chunk.locals));
|
||||
}
|
||||
chunk_iter
|
||||
.filter(|chunk| chunk.can_shadow_sun())
|
||||
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
||||
.for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals));
|
||||
}
|
||||
|
||||
pub fn render_point_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut Drawer<'a>,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, light_data): super::LightData,
|
||||
pub fn chunks_for_point_shadows(
|
||||
&self,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
) -> impl Clone
|
||||
+ Iterator<
|
||||
Item = (
|
||||
&Model<pipelines::terrain::Vertex>,
|
||||
&pipelines::terrain::BoundLocals,
|
||||
),
|
||||
> {
|
||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||
(e as i32).div_euclid(sz as i32)
|
||||
});
|
||||
|
||||
let chunk_iter = Spiral2d::new()
|
||||
.filter_map(|rpos| {
|
||||
.filter_map(move |rpos| {
|
||||
let pos = focus_chunk + rpos;
|
||||
self.chunks.get(&pos)
|
||||
})
|
||||
@ -1317,35 +1315,27 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
//
|
||||
// NOTE: We don't bother retaining chunks unless they cast sun shadows, so we
|
||||
// don't use `shadow_chunks` here.
|
||||
light_data.iter().take(1).for_each(|_light| {
|
||||
drawer.draw_point_shadow(
|
||||
&global.point_light_matrices,
|
||||
chunk_iter
|
||||
.clone()
|
||||
.filter(|chunk| chunk.can_shadow_point)
|
||||
.map(|chunk| (&chunk.opaque_model, &chunk.locals)),
|
||||
);
|
||||
});
|
||||
chunk_iter
|
||||
.filter(|chunk| chunk.can_shadow_point)
|
||||
.map(|chunk| (&chunk.opaque_model, &chunk.locals))
|
||||
}
|
||||
|
||||
pub fn render<'a>(&'a self, drawer: &mut FirstPassDrawer<'a>, focus_pos: Vec3<f32>) {
|
||||
span!(_guard, "render", "Terrain::render");
|
||||
let mut drawer = drawer.draw_terrain(&self.col_lights);
|
||||
|
||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||
(e as i32).div_euclid(sz as i32)
|
||||
});
|
||||
|
||||
let chunk_iter = Spiral2d::new()
|
||||
Spiral2d::new()
|
||||
.filter_map(|rpos| {
|
||||
let pos = focus_chunk + rpos;
|
||||
self.chunks.get(&pos).map(|c| (pos, c))
|
||||
self.chunks.get(&pos)
|
||||
})
|
||||
.take(self.chunks.len());
|
||||
|
||||
for (_, chunk) in chunk_iter {
|
||||
if chunk.visible.is_visible() {
|
||||
drawer.draw_terrain(&chunk.opaque_model, &chunk.locals, &self.col_lights)
|
||||
}
|
||||
}
|
||||
.take(self.chunks.len())
|
||||
.filter(|chunk| chunk.visible.is_visible())
|
||||
.for_each(|chunk| drawer.draw(&chunk.opaque_model, &chunk.locals));
|
||||
}
|
||||
|
||||
pub fn render_translucent<'a>(
|
||||
@ -1373,8 +1363,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
span!(guard, "Terrain sprites");
|
||||
let chunk_size = V::RECT_SIZE.map(|e| e as f32);
|
||||
let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared();
|
||||
for (pos, chunk) in chunk_iter.clone() {
|
||||
if chunk.visible.is_visible() {
|
||||
let mut sprite_drawer = drawer.draw_sprites(&self.sprite_col_lights);
|
||||
chunk_iter
|
||||
.clone()
|
||||
.filter(|(_, c)| c.visible.is_visible())
|
||||
.for_each(|(pos, chunk)| {
|
||||
let sprite_low_detail_distance = sprite_render_distance * 0.75;
|
||||
let sprite_mid_detail_distance = sprite_render_distance * 0.5;
|
||||
let sprite_hid_detail_distance = sprite_render_distance * 0.35;
|
||||
@ -1396,6 +1389,8 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
chunk_center + chunk_size.x * 0.5 - chunk_size.y * 0.5,
|
||||
));
|
||||
if focus_dist_sqrd < sprite_render_distance.powi(2) {
|
||||
// TODO: skip if sprite_instances is empty
|
||||
let mut chunk_sprite_drawer = sprite_drawer.in_chunk(&chunk.locals);
|
||||
for (kind, instances) in (&chunk.sprite_instances).into_iter() {
|
||||
let SpriteData { model, locals, .. } = if kind
|
||||
.0
|
||||
@ -1417,24 +1412,17 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
&self.sprite_data[&kind][4]
|
||||
};
|
||||
|
||||
drawer.draw_sprite(
|
||||
model,
|
||||
instances,
|
||||
&chunk.locals,
|
||||
locals,
|
||||
&self.sprite_col_lights,
|
||||
);
|
||||
chunk_sprite_drawer.draw(model, instances, locals);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
drop(sprite_drawer);
|
||||
drop(guard);
|
||||
|
||||
// Translucent
|
||||
span!(guard, "Fluid chunks");
|
||||
let mut fluid_drawer = drawer.draw_fluid(&self.waves);
|
||||
chunk_iter
|
||||
.clone()
|
||||
.filter(|(_, chunk)| chunk.visible.is_visible())
|
||||
.filter_map(|(_, chunk)| {
|
||||
chunk
|
||||
|
@ -1318,34 +1318,9 @@ impl PlayState for SessionState {
|
||||
particles_enabled: settings.graphics.particles_enabled,
|
||||
is_aiming: self.is_aiming,
|
||||
};
|
||||
drawer.shadow_pass().map(|mut drawer| {
|
||||
self.scene.render_terrain_shadows(
|
||||
&mut drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
client.get_tick(),
|
||||
&scene_data,
|
||||
);
|
||||
|
||||
self.scene.render_figure_shadows(
|
||||
&mut drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
client.get_tick(),
|
||||
&scene_data,
|
||||
);
|
||||
});
|
||||
|
||||
self.scene.render_point_shadows(
|
||||
&mut drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
client.get_tick(),
|
||||
&scene_data,
|
||||
);
|
||||
|
||||
self.scene.render(
|
||||
&mut drawer.first_pass(),
|
||||
&mut drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
client.get_tick(),
|
||||
|
Loading…
Reference in New Issue
Block a user