Various fixes for shadows.

This commit is contained in:
Joshua Yanovski 2020-12-13 05:01:07 +01:00 committed by Avi Weinstock
parent bbbe4ea368
commit ffa8f29732
35 changed files with 149 additions and 274 deletions

View File

@ -1,3 +1,3 @@
vec4 aa_apply(texture2D tex, sampler smplr, vec2 fragCoord, vec2 resolution) {
return texture(src_color, fragCoord / resolution);
return texture(sampler2D(tex, smplr), fragCoord / resolution);
}

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#define FIGURE_SHADER

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>
@ -95,7 +95,7 @@ void main() {
#endif
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy));
vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy));
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
float sun_shade_frac = 1.0;//horizon_at2(f_shadow, f_alt, f_pos, sun_dir);

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -14,7 +14,7 @@ uniform u_light_shadows {
layout(set = 1, binding = 2)
uniform texture2D t_directed_shadow_maps;
layout(set = 1, binding = 3)
uniform sampler s_directed_shadow_maps;
uniform samplerShadow s_directed_shadow_maps;
// uniform sampler2DArrayShadow t_directed_shadow_maps;
// uniform samplerCubeArrayShadow t_shadow_maps;
@ -23,7 +23,7 @@ uniform sampler s_directed_shadow_maps;
layout(set = 1, binding = 0)
uniform textureCube t_point_shadow_maps;
layout(set = 1, binding = 1)
uniform sampler s_point_shadow_maps;
uniform samplerShadow s_point_shadow_maps;
// uniform samplerCube t_shadow_maps;
// uniform sampler2DArray t_directed_shadow_maps;
@ -42,9 +42,13 @@ float VectorToDepth (vec3 Vec)
// float NormZComp = (screen_res.w+screen_res.z) / (screen_res.w-screen_res.z) - (2*screen_res.w*screen_res.z)/(screen_res.w-screen_res.z)/LocalZcomp;
// float NormZComp = 1.0 - shadow_proj_factors.y / shadow_proj_factors.x / LocalZcomp;
// -(1 + 2n/(f-n)) - 2(1 + n/(f-n)) * n/z
// -(1 + n/(f-n)) - (1 + n/(f-n)) * n/z
// f/(f-n) - f
float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp;
// NormZComp = -1000.0 / (NormZComp + 10000.0);
return (NormZComp + 1.0) * 0.5;
// return (NormZComp + 1.0) * 0.5;
return NormZComp;
// float NormZComp = length(LocalZcomp);
// NormZComp = -NormZComp / screen_res.w;
@ -161,7 +165,76 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po
} */
// vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz;
// sun_pos.z += sun_pos.w * bias;
vec4 sun_pos = texture_mat * vec4(fragPos, 1.0);
vec4 sun_pos = texture_mat/*shadowMatrices*/ * vec4(fragPos, 1.0);
// sun_pos.xyz /= abs(sun_pos.w);
// sun_pos.w = sign(sun_pos.w);
// sun_pos.xy = (sun_pos.xy + 1.0) * 0.5;
// vec4 orig_pos = warpViewMat * lightViewMat * vec4(fragPos, 1.0);
//
// vec4 shadow_pos;
// shadow_pos.xyz = (warpProjMat * orig_pos).xyz:
// shadow_pos.w = orig_pos.y;
//
// sun_pos.xy = 0.5 * (shadow_pos.xy + shadow_pos.w) = 0.5 * (shadow_pos.xy + orig_pos.yy);
// sun_pos.z = shadow_pos.z;
//
// sun_pos.w = sign(shadow_pos.w) = sign(orig_pos.y);
// sun_pos.xyz = sun_pos.xyz / shadow_pos.w = vec3(0.5 * shadow_pos.xy / orig_pos.yy + 0.5, shadow_pos.z / orig_pos.y)
// = vec3(0.5 * (2.0 * warp_pos.xy / orig_pos.yy - (max_warp_pos + min_warp_pos).xy) / (max_warp_pos - min_warp_pos).xy + 0.5,
// -(warp_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
// = vec3((warp_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x,
// (warp_pos.y / orig_pos.y - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y,
// -(warp_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
// = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x,
// (((far+near) - 2.0 * near * far / orig_pos.y)/(far-near) - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y,
// -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
// = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x,
// (2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0 - min_warp_pos.y) / (max_warp_pos - min_warp_pos).y,
// -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
// = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x,
// (2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0 - 0.0) / (1.0 - 0.0),
// -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
// = vec3((near * orig_pos.x / orig_pos.y - min_warp_pos.x) / (max_warp_pos - min_warp_pos).x,
// 2.0 * (1.0 - far / orig_pos.y)*near/(far-near) + 1.0,
// -(near * orig_pos.z / orig_pos.y - min_warp_pos.z) / (max_warp_pos - min_warp_pos).z )
//
// orig_pos.y = n: warp_pos.y = 2*(1-f/n)*n/(f-n) + 1 = 2*(n-f)/(f-n) + 1 = 2 * -1 + 1 = -1, sun_pos.y = (-1 - -1) / 2 = 0
// orig_pos.y = f: warp_pos.y = 2*(1-f/f)*n/(f-n) + 1 = 2*(1-1)*n/(f-n) + 1 = 2 * 0 * n/(f-n) + 1 = 1, sun_pos.y = (1 - -1) / 2 = 1
//
// 2*(1-64/(1/((0-1)*63/2-1/64)))*1/63+1
//
// 2*(1-f/x)*n/(f-n) + 1 = 0
// 2*(1-f/x)*n/(f-n) = -1
//
// (1-f/x) = -(f-n)/(2*n)
// 1 + (f-n)/(2*n) = f/x
// x = f/(1 + 0.5 * (f-n)/n)
// = 2*f/(1 + f/n)
// = 2*f*n/(f + n)
// = 2/(1/n + 1/f)
//
// 2/(1/(64/1) + 1/64) = 64 (but has n = f = 64)
// 2/(1/(64/3) + 1/64) = 32
// 2/(1/(64/7) + 1/64) = 16
// 2/(1/(64/15) + 1/64) = 8
// 2/(1/(64/31) + 1/64) = 4
// 2/(1/(64/63) + 1/64) = 2
// 2/(1/(64/127) + 1/64) = 1 (but has f < n)
//
// 2*(1-64/(64/127))*64/127/(64-64/127)+1
//
// (with normed n)
// = 2/(1/n + 1/(1+n))
// = 2*n*(1+n)/(1+2n)
// = 1/((1 +2n)/(2n(1+n)))
// = 1/(1/(2n(1+n)) + 1/(1+n))
// = (1 + n)/(1 + 0.5/n)
// 2*64*1/(64+1)
//
// 2*(1-64/(64/(1 + 0.5 * 63/1)))*1/63+1
//
// sun_pos.xy = sun_pos.w - sun_pos.xy;
// sun_pos.xy = sun_pos.xy * 0.5 + 0.5;
// sun_pos.z -= sun_pos.w * bias;
float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos);
/* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0));

View File

@ -2,7 +2,7 @@
//
// However, in the future we might apply some depth transforms here.
#version 330 core
#version 420 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
@ -36,9 +36,10 @@ uniform u_light_shadows {
*
* */
layout(location = 1) in uint v_pos_norm;
layout(location = 0) in uint v_pos_norm;
// in uint v_col_light;
// in vec4 v_pos;
// layout(location = 1) in uint v_atlas_pos;
// Light projection matrices.
layout (std140, set = 1, binding = 0)

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
// #extension ARB_texture_storage : enable
#define FIGURE_SHADER

View File

@ -2,7 +2,7 @@
//
// However, in the future we might apply some depth transforms here.
#version 330 core
#version 420 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
@ -43,7 +43,7 @@ uniform u_locals {
const int EXTRA_NEG_Z = 32768;
layout( push_constant ) uniform PointLightMatrix {
vec4 lightShadowMatrix;
mat4 lightShadowMatrix;
};
void main() {

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
// #extension GL_ARB_texture_storage : require
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <constants.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <globals.glsl>

View File

@ -1,4 +1,4 @@
#version 330 core
#version 420 core
#include <globals.glsl>

View File

@ -126,8 +126,8 @@ impl Globals {
0,
],
shadow_proj_factors: [
(shadow_planes.y + shadow_planes.x) / (shadow_planes.y - shadow_planes.x),
(2.0 * shadow_planes.y * shadow_planes.x) / (shadow_planes.y - shadow_planes.x),
shadow_planes.y / (shadow_planes.y - shadow_planes.x),
shadow_planes.y * shadow_planes.x / (shadow_planes.y - shadow_planes.x),
0.0,
0.0,
],

View File

@ -141,7 +141,7 @@ impl ShadowFigurePipeline {
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Shadow figure pipeline layout"),
label: Some("Directed figure shadow pipeline layout"),
push_constant_ranges: &[],
bind_group_layouts: &[&global_layout.globals, &figure_layout.locals],
});
@ -155,7 +155,7 @@ impl ShadowFigurePipeline {
};
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Shadow figure pipeline"),
label: Some("Directed shadow figure pipeline"),
layout: Some(&render_pipeline_layout),
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: vs_module,
@ -167,7 +167,7 @@ impl ShadowFigurePipeline {
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
cull_mode: wgpu::CullMode::Front,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: true,
depth_bias: 0,
@ -217,7 +217,7 @@ impl ShadowPipeline {
) -> Self {
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Shadow pipeline layout"),
label: Some("Directed shadow pipeline layout"),
push_constant_ranges: &[],
bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
});
@ -231,7 +231,7 @@ impl ShadowPipeline {
};
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Shadow pipeline"),
label: Some("Directed shadow pipeline"),
layout: Some(&render_pipeline_layout),
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: vs_module,
@ -243,7 +243,7 @@ impl ShadowPipeline {
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
cull_mode: wgpu::CullMode::Front,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: true,
depth_bias: 0,
@ -292,7 +292,7 @@ impl PointShadowPipeline {
) -> Self {
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Shadow pipeline layout"),
label: Some("Point shadow pipeline layout"),
push_constant_ranges: &[wgpu::PushConstantRange {
stages: wgpu::ShaderStage::all(),
range: 0..64,
@ -309,7 +309,7 @@ impl PointShadowPipeline {
};
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Shadow pipeline"),
label: Some("Point shadow pipeline"),
layout: Some(&render_pipeline_layout),
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: vs_module,
@ -321,9 +321,9 @@ impl PointShadowPipeline {
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
cull_mode: wgpu::CullMode::Front,
polygon_mode: wgpu::PolygonMode::Fill,
clamp_depth: true,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,

View File

@ -2106,7 +2106,7 @@ fn create_pipelines(
let figure_vert_mod = create_shader("figure-vert", ShaderKind::Vertex)?;
let terrain_point_shadow_vert_mod = create_shader("light-shadows-vert", ShaderKind::Vertex)?;
let terrain_point_shadow_vert_mod = create_shader("point-light-shadows-vert", ShaderKind::Vertex)?;
let terrain_directed_shadow_vert_mod =
create_shader("light-shadows-directed-vert", ShaderKind::Vertex)?;

View File

@ -11,7 +11,7 @@ use super::{
},
Renderer, ShadowMapRenderer,
};
use std::{ops::Range};
use core::{num::NonZeroU32, ops::Range};
use vek::Aabr;
pub struct Drawer<'a> {
@ -156,9 +156,8 @@ impl<'a> Drawer<'a> {
pub fn draw_point_shadow<'b: 'a>(
&mut self,
model: &'b Model<terrain::Vertex>,
locals: &'b terrain::BoundLocals,
matrices: &[shadow::PointLightMatrix; 126],
chunks: impl Clone + Iterator<Item=(&'b Model<terrain::Vertex>, &'b terrain::BoundLocals)>,
) {
if let Some(ref shadow_renderer) = self.renderer.shadow_map {
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
@ -172,12 +171,12 @@ impl<'a> Drawer<'a> {
.create_view(&wgpu::TextureViewDescriptor {
label: Some("Point shadow cubemap face"),
format: None,
dimension: Some(wgpu::TextureViewDimension::D2Array),
dimension: Some(wgpu::TextureViewDimension::D2),
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
level_count: None,
base_array_layer: face,
array_layer_count: None,
array_layer_count: NonZeroU32::new(1),
});
let mut render_pass =
@ -200,18 +199,20 @@ impl<'a> Drawer<'a> {
render_pass.set_pipeline(&shadow_renderer.point_pipeline.pipeline);
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
render_pass.set_bind_group(1, &locals.bind_group, &[]);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
for point_light in 0..20 {
(0../*20*/1).for_each(|point_light| {
render_pass.set_push_constants(
wgpu::ShaderStage::all(),
0,
&data[(6 * point_light * STRIDE + face as usize * STRIDE)
..(6 * point_light * STRIDE + (face + 1) as usize * STRIDE)],
);
render_pass.draw(0..model.len() as u32, 0..1);
}
chunks.clone().for_each(|(model, locals)| {
render_pass.set_bind_group(1, &locals.bind_group, &[]);
render_pass.set_vertex_buffer(0, model.buf().slice(..));
render_pass.draw(0..model.len() as u32, 0..1);
});
});
}
}
}

View File

@ -80,7 +80,7 @@ pub fn calc_view_frustum_world_coord<T: Float + MulAdd<T, T, Output = T>>(
inv_proj_view: Mat4<T>,
) -> [Vec3<T>; 8] {
let mut world_pts = aabb_to_points(Aabb {
min: -Vec3::one(),
min: Vec3::new(-T::one(), -T::one(), T::zero()),
max: Vec3::one(),
});
mat_mul_points(inv_proj_view, &mut world_pts, |p| Vec3::from(p) / p.w);

View File

@ -695,7 +695,8 @@ impl Scene {
// to transform it correctly into texture coordinates, as well as
// OpenGL coordinates. Note that the matrix for directional light
// is *already* linear in the depth buffer.
let texture_mat = Mat4::scaling_3d(0.5f32) * Mat4::translation_3d(1.0f32);
let texture_mat = Mat4::<f32>::scaling_3d::<Vec3<f32>>(Vec3::new(0.5, 0.5, 1.0))
* Mat4::translation_3d(Vec3::new(1.0, 1.0, 0.0));
// We need to compute these offset matrices to transform world space coordinates
// to the translated ones we use when multiplying by the light space
// matrix; this helps avoid precision loss during the
@ -881,10 +882,10 @@ impl Scene {
);
let s_x = 2.0 / (xmax - xmin);
let s_y = 2.0 / (ymax - ymin);
let s_z = 2.0 / (zmax - zmin);
let s_z = 1.0 / (zmax - zmin);
let o_x = -(xmax + xmin) / (xmax - xmin);
let o_y = -(ymax + ymin) / (ymax - ymin);
let o_z = -(zmax + zmin) / (zmax - zmin);
let o_z = -zmin / (zmax - zmin);
let directed_proj_mat = Mat4::new(
s_x, 0.0, 0.0, o_x, 0.0, s_y, 0.0, o_y, 0.0, 0.0, s_z, o_z, 0.0, 0.0, 0.0, 1.0,
);
@ -907,202 +908,7 @@ impl Scene {
// Now, construct the full projection matrices in the first two directed light
// slots.
let mut shadow_mats = Vec::with_capacity(6 * (lights.len() + 1));
shadow_mats.extend(directed_shadow_mats.iter().enumerate().map(
move |(idx, &light_view_mat)| {
if idx >= NUM_DIRECTED_LIGHTS {
return PointLightMatrix::new(Mat4::identity());
}
let v_p_orig =
math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir));
let mut v_p = v_p_orig.normalized();
let cos_gamma = new_dir
.map(f64::from)
.dot(directed_light_dir.map(f64::from));
let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt();
let gamma = sin_gamma.asin();
let view_mat = math::Mat4::from_col_array(view_mat.into_col_array());
let bounds1 = math::fit_psr(
view_mat.map_cols(math::Vec4::from),
visible_light_volume.iter().copied(),
math::Vec4::homogenized,
);
let n_e = f64::from(-bounds1.max.z);
let factor = compute_warping_parameter_perspective(
gamma,
n_e,
f64::from(fov),
f64::from(aspect_ratio),
);
v_p.z = 0.0;
v_p.normalize();
let l_r: math::Mat4<f32> = if factor > EPSILON_UPSILON {
math::Mat4::look_at_rh(math::Vec3::zero(), -math::Vec3::unit_z(), v_p)
} else {
math::Mat4::identity()
};
let directed_proj_mat = math::Mat4::new(
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0,
1.0,
);
let light_all_mat = l_r * directed_proj_mat * light_view_mat;
let bounds0 = math::fit_psr(
light_all_mat,
visible_light_volume.iter().copied(),
math::Vec4::homogenized,
);
// Vague idea: project z_n from the camera view to the light view (where it's
// tilted by γ).
let (z_0, z_1) = {
let p_z = bounds1.max.z;
let p_y = bounds0.min.y;
let p_x = bounds0.center().x;
let view_inv = view_mat.inverted();
let light_all_inv = light_all_mat.inverted();
let view_point = view_inv * math::Vec4::new(0.0, 0.0, p_z, 1.0);
let view_plane =
view_inv * math::Vec4::from_direction(math::Vec3::unit_z());
let light_point = light_all_inv * math::Vec4::new(0.0, p_y, 0.0, 1.0);
let light_plane =
light_all_inv * math::Vec4::from_direction(math::Vec3::unit_y());
let shadow_point = light_all_inv * math::Vec4::new(p_x, 0.0, 0.0, 1.0);
let shadow_plane =
light_all_inv * math::Vec4::from_direction(math::Vec3::unit_x());
let solve_p0 = math::Mat4::new(
view_plane.x,
view_plane.y,
view_plane.z,
-view_plane.dot(view_point),
light_plane.x,
light_plane.y,
light_plane.z,
-light_plane.dot(light_point),
shadow_plane.x,
shadow_plane.y,
shadow_plane.z,
-shadow_plane.dot(shadow_point),
0.0,
0.0,
0.0,
1.0,
);
let p0_world = solve_p0.inverted() * math::Vec4::unit_w();
let p0 = light_all_mat * p0_world;
let mut p1 = p0;
p1.y = bounds0.max.y;
let view_from_light_mat = view_mat * light_all_inv;
let z0 = view_from_light_mat * p0;
let z1 = view_from_light_mat * p1;
(f64::from(z0.z), f64::from(z1.z))
};
let mut light_focus_pos: math::Vec3<f32> = math::Vec3::zero();
light_focus_pos.x = bounds0.center().x;
light_focus_pos.y = bounds0.min.y;
light_focus_pos.z = bounds0.center().z;
let d = f64::from(bounds0.max.y - bounds0.min.y).abs();
let w_l_y = d;
// NOTE: See section 5.1.2.2 of Lloyd's thesis.
let alpha = z_1 / z_0;
let alpha_sqrt = alpha.sqrt();
let directed_near_normal = if factor < 0.0 {
// Standard shadow map to LiSPSM
(1.0 + alpha_sqrt - factor * (alpha - 1.0))
/ ((alpha - 1.0) * (factor + 1.0))
} else {
// LiSPSM to PSM
((alpha_sqrt - 1.0) * (factor * alpha_sqrt + 1.0)).recip()
};
// Equation 5.14 - 5.16
let y_ = |v: f64| w_l_y * (v + directed_near_normal).abs();
let directed_near = y_(0.0) as f32;
let directed_far = y_(1.0) as f32;
light_focus_pos.y = if factor > EPSILON_UPSILON {
light_focus_pos.y - directed_near
} else {
light_focus_pos.y
};
let w_v: math::Mat4<f32> = math::Mat4::translation_3d(-math::Vec3::new(
light_focus_pos.x,
light_focus_pos.y,
light_focus_pos.z,
));
let shadow_view_mat: math::Mat4<f32> = w_v * light_all_mat;
let w_p: math::Mat4<f32> = {
if factor > EPSILON_UPSILON {
// Projection for y
let near = directed_near;
let far = directed_far;
let left = -1.0;
let right = 1.0;
let bottom = -1.0;
let top = 1.0;
let s_x = 2.0 * near / (right - left);
let o_x = (right + left) / (right - left);
let s_z = 2.0 * near / (top - bottom);
let o_z = (top + bottom) / (top - bottom);
let s_y = (far + near) / (far - near);
let o_y = -2.0 * far * near / (far - near);
math::Mat4::new(
s_x, o_x, 0.0, 0.0, 0.0, s_y, 0.0, o_y, 0.0, o_z, s_z, 0.0, 0.0,
1.0, 0.0, 0.0,
)
} else {
math::Mat4::identity()
}
};
let shadow_all_mat: math::Mat4<f32> = w_p * shadow_view_mat;
let math::Aabb::<f32> {
min:
math::Vec3 {
x: xmin,
y: ymin,
z: zmin,
},
max:
math::Vec3 {
x: xmax,
y: ymax,
z: zmax,
},
} = math::fit_psr(
shadow_all_mat,
visible_light_volume.iter().copied(),
math::Vec4::homogenized,
);
let s_x = 2.0 / (xmax - xmin);
let s_y = 2.0 / (ymax - ymin);
let s_z = 2.0 / (zmax - zmin);
let o_x = -(xmax + xmin) / (xmax - xmin);
let o_y = -(ymax + ymin) / (ymax - ymin);
let o_z = -(zmax + zmin) / (zmax - zmin);
let directed_proj_mat = Mat4::new(
s_x, 0.0, 0.0, o_x, 0.0, s_y, 0.0, o_y, 0.0, 0.0, s_z, o_z, 0.0, 0.0, 0.0,
1.0,
);
let shadow_all_mat: Mat4<f32> =
Mat4::from_col_arrays(shadow_all_mat.into_col_arrays());
PointLightMatrix::new(directed_proj_mat * shadow_all_mat)
},
));
shadow_mats.resize_with(6, PointLightMatrix::default);
// Now, we tackle point lights.
// First, create a perspective projection matrix at 90 degrees (to cover a whole
// face of the cube map we're using).

View File

@ -1453,15 +1453,10 @@ 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| {
chunk_iter.clone().for_each(|chunk| {
if chunk.can_shadow_point {
drawer.draw_point_shadow(
&chunk.opaque_model,
&chunk.locals,
&global.point_light_matrices,
);
}
});
drawer.draw_point_shadow(
&global.point_light_matrices,
chunk_iter.clone().filter(|chunk| chunk.can_shadow_point).map(|chunk| (&chunk.opaque_model, &chunk.locals)),
);
});
}

View File

@ -1426,6 +1426,14 @@ impl PlayState for SessionState {
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(
@ -1436,15 +1444,6 @@ impl PlayState for SessionState {
&scene_data,
);
drawer.shadow_pass().map(|mut drawer| {
self.scene.render_figure_shadows(
&mut drawer,
client.state(),
client.entity(),
client.get_tick(),
&scene_data,
);
});
self.scene.render(
&mut drawer.first_pass(),
client.state(),