MAJOR rendering overhaul. Snow deformation, persistent light, flowmap out. Also ECS architexture overhaul
This commit is contained in:
139
src/render/shadow.rs
Normal file
139
src/render/shadow.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use glam::Mat4;
|
||||
|
||||
use super::types::{DrawCall, Uniforms, MAX_SPOTLIGHTS};
|
||||
use super::Renderer;
|
||||
|
||||
impl Renderer
|
||||
{
|
||||
pub(super) fn render_shadow_pass(
|
||||
&mut self,
|
||||
draw_calls: &[DrawCall],
|
||||
light_view_projections: &[Mat4],
|
||||
player_position: glam::Vec3,
|
||||
time: f32,
|
||||
)
|
||||
{
|
||||
let spotlight_count = self.spotlights.len().min(MAX_SPOTLIGHTS);
|
||||
|
||||
for layer in 0..spotlight_count
|
||||
{
|
||||
let shadow_uniforms = Uniforms::new(
|
||||
Mat4::IDENTITY,
|
||||
Mat4::IDENTITY,
|
||||
light_view_projections[layer],
|
||||
light_view_projections,
|
||||
glam::Vec3::ZERO,
|
||||
player_position,
|
||||
self.terrain_height_scale,
|
||||
time,
|
||||
self.shadow_bias,
|
||||
2.0,
|
||||
false,
|
||||
false,
|
||||
&self.spotlights,
|
||||
);
|
||||
self.queue.write_buffer(
|
||||
&self.uniform_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[shadow_uniforms]),
|
||||
);
|
||||
|
||||
let layer_view = self
|
||||
.shadow_map_texture
|
||||
.create_view(&wgpu::TextureViewDescriptor {
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
base_array_layer: layer as u32,
|
||||
array_layer_count: Some(1),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let mut encoder = self
|
||||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
||||
label: Some("Shadow Pass Encoder"),
|
||||
});
|
||||
|
||||
{
|
||||
let mut shadow_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Shadow Pass"),
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||
view: &layer_view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: wgpu::StoreOp::Store,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
}),
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
|
||||
shadow_pass.set_pipeline(
|
||||
self.shadow_pipeline
|
||||
.as_ref()
|
||||
.expect("shadow pipeline missing"),
|
||||
);
|
||||
shadow_pass.set_bind_group(
|
||||
0,
|
||||
self.shadow_bind_group
|
||||
.as_ref()
|
||||
.expect("shadow bind group missing"),
|
||||
&[],
|
||||
);
|
||||
|
||||
for draw_call in draw_calls.iter()
|
||||
{
|
||||
shadow_pass.set_vertex_buffer(0, draw_call.vertex_buffer.slice(..));
|
||||
|
||||
if let Some(ref instance_buffer) = draw_call.instance_buffer
|
||||
{
|
||||
shadow_pass.set_vertex_buffer(1, instance_buffer.slice(..));
|
||||
}
|
||||
|
||||
shadow_pass.set_index_buffer(
|
||||
draw_call.index_buffer.slice(..),
|
||||
wgpu::IndexFormat::Uint32,
|
||||
);
|
||||
shadow_pass.draw_indexed(
|
||||
0..draw_call.num_indices,
|
||||
0,
|
||||
0..draw_call.num_instances,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn calculate_light_view_projections(&self) -> Vec<Mat4>
|
||||
{
|
||||
self.spotlights
|
||||
.iter()
|
||||
.take(MAX_SPOTLIGHTS)
|
||||
.map(|spotlight| {
|
||||
let light_position = spotlight.position;
|
||||
let light_target = spotlight.position + spotlight.direction;
|
||||
|
||||
let up_vector = if spotlight.direction.y.abs() > 0.99
|
||||
{
|
||||
glam::Vec3::Z
|
||||
}
|
||||
else
|
||||
{
|
||||
glam::Vec3::Y
|
||||
};
|
||||
|
||||
let light_view = Mat4::look_at_rh(light_position, light_target, up_vector);
|
||||
|
||||
let fov = spotlight.outer_angle * 2.0;
|
||||
let near = 0.1;
|
||||
let far = 150.0;
|
||||
let light_projection = Mat4::perspective_rh(fov, 1.0, near, far);
|
||||
|
||||
light_projection * light_view
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user