mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fix the shadow drawing code
Very poorly optimized
This commit is contained in:
parent
4941736cec
commit
bbbe4ea368
@ -22,19 +22,19 @@
|
||||
#include <srgb.glsl>
|
||||
#include <cloud.glsl>
|
||||
|
||||
layout(set = 1, binding = 0)
|
||||
layout(set = 2, binding = 0)
|
||||
uniform texture2D t_src_color;
|
||||
layout(set = 1, binding = 1)
|
||||
layout(set = 2, binding = 1)
|
||||
uniform sampler s_src_color;
|
||||
|
||||
layout(set = 1, binding = 2)
|
||||
layout(set = 2, binding = 2)
|
||||
uniform texture2D t_src_depth;
|
||||
layout(set = 1, binding = 3)
|
||||
layout(set = 2, binding = 3)
|
||||
uniform sampler s_src_depth;
|
||||
|
||||
layout(location = 0) in vec2 uv;
|
||||
|
||||
layout (std140, set = 1, binding = 4)
|
||||
layout (std140, set = 2, binding = 4)
|
||||
uniform u_locals {
|
||||
mat4 proj_mat_inv;
|
||||
mat4 view_mat_inv;
|
||||
|
@ -37,9 +37,9 @@ layout(location = 1) flat in vec3 f_norm;
|
||||
// const vec4 sun_pos = vec4(0.0);
|
||||
// #endif
|
||||
|
||||
layout(set = 2, binding = 0)
|
||||
layout(set = 3, binding = 0)
|
||||
uniform texture2D t_col_light;
|
||||
layout(set = 2, binding = 1)
|
||||
layout(set = 3, binding = 1)
|
||||
uniform sampler s_col_light;
|
||||
|
||||
//struct ShadowLocals {
|
||||
@ -52,7 +52,7 @@ uniform sampler s_col_light;
|
||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||
//};
|
||||
|
||||
layout (std140, set = 1, binding = 0)
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_locals {
|
||||
mat4 model_mat;
|
||||
vec4 highlight_col;
|
||||
@ -70,7 +70,7 @@ struct BoneData {
|
||||
mat4 normals_mat;
|
||||
};
|
||||
|
||||
layout (std140, set = 1, binding = 1)
|
||||
layout (std140, set = 2, binding = 1)
|
||||
uniform u_bones {
|
||||
BoneData bones[16];
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ layout(location = 1) in uint v_atlas_pos;
|
||||
// out vec3 light_pos[2];
|
||||
in uint v_ao_bone; */
|
||||
|
||||
layout (std140, set = 1, binding = 0)
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_locals {
|
||||
mat4 model_mat;
|
||||
vec4 highlight_col;
|
||||
@ -43,7 +43,7 @@ struct BoneData {
|
||||
mat4 normals_mat;
|
||||
};
|
||||
|
||||
layout (std140, set = 1, binding = 1)
|
||||
layout (std140, set = 2, binding = 1)
|
||||
uniform u_bones {
|
||||
// Warning: might not actually be 16 elements long. Don't index out of bounds!
|
||||
BoneData bones[16];
|
||||
|
@ -37,16 +37,16 @@ layout(location = 1) flat in uint f_pos_norm;
|
||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||
// };
|
||||
|
||||
layout(std140, set = 2, binding = 0)
|
||||
layout(std140, set = 3, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
ivec4 atlas_offs;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0)
|
||||
layout(set = 2, binding = 0)
|
||||
uniform texture2D t_waves;
|
||||
layout(set = 1, binding = 1)
|
||||
layout(set = 2, binding = 1)
|
||||
uniform sampler s_waves;
|
||||
|
||||
layout(location = 0) out vec4 tgt_color;
|
||||
|
@ -39,16 +39,16 @@ layout(location = 1) flat in uint f_pos_norm;
|
||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||
//};
|
||||
|
||||
layout(std140, set = 2, binding = 0)
|
||||
layout(std140, set = 3, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
ivec4 atlas_offs;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0)
|
||||
layout(set = 2, binding = 0)
|
||||
uniform texture2D t_waves;
|
||||
layout(set = 1, binding = 1)
|
||||
layout(set = 2, binding = 1)
|
||||
uniform sampler s_waves;
|
||||
|
||||
layout(location = 0) out vec4 tgt_color;
|
||||
|
@ -23,7 +23,7 @@
|
||||
layout(location = 0) in uint v_pos_norm;
|
||||
// in uint v_col_light;
|
||||
|
||||
layout(std140, set = 2, binding = 0)
|
||||
layout(std140, set = 3, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
|
@ -330,9 +330,9 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) {
|
||||
}
|
||||
|
||||
#ifdef HAS_LOD_FULL_INFO
|
||||
layout(set = 0, binding = 14)
|
||||
layout(set = 0, binding = 10)
|
||||
uniform texture2D t_map;
|
||||
layout(set = 0, binding = 15)
|
||||
layout(set = 0, binding = 11)
|
||||
uniform sampler s_map;
|
||||
|
||||
vec3 lod_col(vec2 pos) {
|
||||
|
@ -3,30 +3,26 @@
|
||||
|
||||
#ifdef HAS_SHADOW_MAPS
|
||||
|
||||
#if (SHADOW_MODE == SHADOW_MODE_MAP)
|
||||
struct ShadowLocals {
|
||||
#if (SHADOW_MODE == SHADOW_MODE_MAP)
|
||||
layout (std140, set = 0, binding = 9)
|
||||
uniform u_light_shadows {
|
||||
mat4 shadowMatrices;
|
||||
mat4 texture_mat;
|
||||
};
|
||||
|
||||
layout (std140, set = 0, binding = 9)
|
||||
uniform u_light_shadows {
|
||||
ShadowLocals shadowMats[/*MAX_LAYER_FACES*//*192*/126];
|
||||
};
|
||||
|
||||
// Use with sampler2DShadow
|
||||
layout(set = 0, binding = 12)
|
||||
layout(set = 1, binding = 2)
|
||||
uniform texture2D t_directed_shadow_maps;
|
||||
layout(set = 0, binding = 13)
|
||||
layout(set = 1, binding = 3)
|
||||
uniform sampler s_directed_shadow_maps;
|
||||
// uniform sampler2DArrayShadow t_directed_shadow_maps;
|
||||
|
||||
// uniform samplerCubeArrayShadow t_shadow_maps;
|
||||
// uniform samplerCubeArray t_shadow_maps;
|
||||
// Use with samplerCubeShadow
|
||||
layout(set = 0, binding = 10)
|
||||
layout(set = 1, binding = 0)
|
||||
uniform textureCube t_point_shadow_maps;
|
||||
layout(set = 0, binding = 11)
|
||||
layout(set = 1, binding = 1)
|
||||
uniform sampler s_point_shadow_maps;
|
||||
// uniform samplerCube t_shadow_maps;
|
||||
|
||||
@ -165,7 +161,6 @@ 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;
|
||||
mat4 texture_mat = shadowMats[0].texture_mat;
|
||||
vec4 sun_pos = texture_mat * vec4(fragPos, 1.0);
|
||||
// sun_pos.z -= sun_pos.w * bias;
|
||||
float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos);
|
||||
|
@ -22,7 +22,13 @@
|
||||
// Currently, we only need globals for focus_off.
|
||||
#include <globals.glsl>
|
||||
// For shadow locals.
|
||||
#include <shadows.glsl>
|
||||
// #include <shadows.glsl>
|
||||
|
||||
layout (std140, set = 0, binding = 9)
|
||||
uniform u_light_shadows {
|
||||
mat4 shadowMatrices;
|
||||
mat4 texture_mat;
|
||||
};
|
||||
|
||||
/* Accurate packed shadow maps for many lights at once!
|
||||
*
|
||||
@ -54,7 +60,7 @@ void main() {
|
||||
// vec3 f_pos = f_chunk_pos + model_offs;
|
||||
|
||||
// gl_Position = v_pos + vec4(model_offs, 0.0);
|
||||
gl_Position = /*all_mat * */shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0);
|
||||
gl_Position = /*all_mat * */shadowMatrices * vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0);
|
||||
// gl_Position.z = -gl_Position.z;
|
||||
// gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
||||
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
|
||||
|
@ -24,7 +24,13 @@
|
||||
// Currently, we only need globals for focus_off.
|
||||
#include <globals.glsl>
|
||||
// For shadow locals.
|
||||
#include <shadows.glsl>
|
||||
// #include <shadows.glsl>
|
||||
|
||||
layout (std140, set = 0, binding = 9)
|
||||
uniform u_light_shadows {
|
||||
mat4 shadowMatrices;
|
||||
mat4 texture_mat;
|
||||
};
|
||||
|
||||
/* Accurate packed shadow maps for many lights at once!
|
||||
*
|
||||
@ -73,6 +79,6 @@ void main() {
|
||||
vec4(pos, 1.0)
|
||||
).xyz + (model_pos - focus_off.xyz/* + vec3(0.0, 0.0, 0.0001)*/);
|
||||
|
||||
gl_Position = shadowMats[/*layer_face*/0].shadowMatrices * vec4(f_pos, 1.0);
|
||||
gl_Position = shadowMatrices * vec4(f_pos, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
60
assets/voxygen/shaders/point-light-shadows-vert.glsl
Normal file
60
assets/voxygen/shaders/point-light-shadows-vert.glsl
Normal file
@ -0,0 +1,60 @@
|
||||
#version 330 core
|
||||
// #extension ARB_texture_storage : enable
|
||||
|
||||
#include <constants.glsl>
|
||||
|
||||
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
|
||||
|
||||
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
|
||||
|
||||
#if (FLUID_MODE == FLUID_MODE_CHEAP)
|
||||
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
|
||||
#elif (FLUID_MODE == FLUID_MODE_SHINY)
|
||||
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
|
||||
#endif
|
||||
|
||||
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
|
||||
|
||||
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
||||
|
||||
// Currently, we only need globals for focus_off.
|
||||
#include <globals.glsl>
|
||||
|
||||
/* Accurate packed shadow maps for many lights at once!
|
||||
*
|
||||
* Ideally, we would just write to a bitmask...
|
||||
*
|
||||
* */
|
||||
|
||||
layout(location = 1) in uint v_pos_norm;
|
||||
// in uint v_col_light;
|
||||
// in vec4 v_pos;
|
||||
|
||||
// Light projection matrices.
|
||||
layout (std140, set = 1, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
ivec4 atlas_offs;
|
||||
};
|
||||
|
||||
// out vec4 shadowMapCoord;
|
||||
|
||||
const int EXTRA_NEG_Z = 32768;
|
||||
|
||||
layout( push_constant ) uniform PointLightMatrix {
|
||||
vec4 lightShadowMatrix;
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec3 f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z));
|
||||
vec3 f_pos = f_chunk_pos + model_offs - focus_off.xyz;
|
||||
// f_pos = v_pos;
|
||||
// vec3 f_pos = f_chunk_pos + model_offs;
|
||||
|
||||
// gl_Position = v_pos + vec4(model_offs, 0.0);
|
||||
// gl_Position = /*all_mat * */vec4(f_pos/*, 1.0*/, /*float(((f_pos_norm >> 29) & 0x7u) ^ 0x1)*//*uintBitsToFloat(v_pos_norm)*/1.0);
|
||||
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
|
||||
// vec4(v_pos, 0.0, 1.0);
|
||||
gl_Position = lightShadowMatrix * vec4(f_pos, 1.0);
|
||||
}
|
@ -28,9 +28,9 @@ layout(location = 4) in vec2 f_inst_light;
|
||||
// in float f_light;
|
||||
// in vec4 light_pos[2];
|
||||
|
||||
layout(set = 3, binding = 0)
|
||||
layout(set = 4, binding = 0)
|
||||
uniform texture2D t_col_light;
|
||||
layout(set = 3, binding = 1)
|
||||
layout(set = 4, binding = 1)
|
||||
uniform sampler s_col_light;
|
||||
|
||||
//struct ShadowLocals {
|
||||
|
@ -34,7 +34,7 @@ struct SpriteLocals {
|
||||
vec4 offs;
|
||||
};
|
||||
|
||||
layout(std140, set = 2, binding = 0)
|
||||
layout(std140, set = 3, binding = 0)
|
||||
uniform u_locals {
|
||||
mat4 mat;
|
||||
vec4 wind_sway;
|
||||
@ -63,7 +63,7 @@ uniform u_locals {
|
||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||
//};
|
||||
|
||||
layout (std140, set = 1, binding = 0)
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_terrain_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
|
@ -45,12 +45,12 @@ in vec4 sun_pos;
|
||||
const vec4 sun_pos = vec4(0.0);
|
||||
#endif */
|
||||
|
||||
layout(set = 2, binding = 0)
|
||||
layout(set = 3, binding = 0)
|
||||
uniform texture2D t_col_light;
|
||||
layout(set = 2, binding = 1)
|
||||
layout(set = 3, binding = 1)
|
||||
uniform sampler s_col_light;
|
||||
|
||||
layout (std140, set = 1, binding = 0)
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
|
@ -28,7 +28,7 @@ layout(location = 0) in uint v_pos_norm;
|
||||
// in uint v_col_light;
|
||||
layout(location = 1) in uint v_atlas_pos;
|
||||
|
||||
layout (std140, set = 1, binding = 0)
|
||||
layout (std140, set = 2, binding = 0)
|
||||
uniform u_locals {
|
||||
vec3 model_offs;
|
||||
float load_time;
|
||||
@ -155,7 +155,7 @@ void main() {
|
||||
|
||||
#ifdef HAS_SHADOW_MAPS
|
||||
gl_Position =
|
||||
/*all_mat*/shadowMats[0].shadowMatrices/*texture_mat*/ *
|
||||
/*all_mat*/shadowMatrices/*texture_mat*/ *
|
||||
vec4(f_pos/*newRay*/, 1);
|
||||
gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
||||
#else
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::render::{
|
||||
GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Renderer, Shadow, ShadowLocals,
|
||||
GlobalModel, Globals, GlobalsBindGroup, Light, LodData, PointLightMatrix, Renderer, Shadow,
|
||||
ShadowLocals,
|
||||
};
|
||||
|
||||
pub struct Scene {
|
||||
@ -12,7 +13,8 @@ impl Scene {
|
||||
globals: renderer.create_consts(&[Globals::default()]),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]),
|
||||
shadows: renderer.create_consts(&[Shadow::default(); 32]),
|
||||
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
|
||||
shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]),
|
||||
point_light_matrices: Box::new([PointLightMatrix::default(); 126]),
|
||||
};
|
||||
|
||||
let lod_data = LodData::dummy(renderer);
|
||||
|
@ -28,7 +28,7 @@ pub use self::{
|
||||
lod_terrain::{LodData, Vertex as LodTerrainVertex},
|
||||
particle::{Instance as ParticleInstance, Vertex as ParticleVertex},
|
||||
postprocess::Locals as PostProcessLocals,
|
||||
shadow::Locals as ShadowLocals,
|
||||
shadow::{Locals as ShadowLocals, PointLightMatrix},
|
||||
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
|
||||
sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex},
|
||||
terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex},
|
||||
@ -43,7 +43,7 @@ pub use self::{
|
||||
renderer::{
|
||||
drawer::{
|
||||
Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer,
|
||||
ThirdPassDrawer, UiDrawer,
|
||||
ShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
},
|
||||
ColLightInfo, Renderer,
|
||||
},
|
||||
|
@ -153,7 +153,11 @@ impl CloudsPipeline {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Clouds pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[&global_layout.globals, &layout.layout],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&layout.layout,
|
||||
],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
|
@ -185,6 +185,7 @@ impl FigurePipeline {
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&layout.locals,
|
||||
&global_layout.col_light,
|
||||
],
|
||||
|
@ -128,6 +128,7 @@ impl FluidPipeline {
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&layout.waves,
|
||||
&terrain_layout.locals,
|
||||
],
|
||||
|
@ -148,7 +148,7 @@ impl LodTerrainPipeline {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Lod terrain pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[&global_layout.globals],
|
||||
bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
|
@ -229,16 +229,19 @@ pub struct GlobalModel {
|
||||
pub globals: Consts<Globals>,
|
||||
pub lights: Consts<Light>,
|
||||
pub shadows: Consts<Shadow>,
|
||||
pub shadow_mats: Consts<shadow::Locals>,
|
||||
pub shadow_mats: shadow::BoundLocals,
|
||||
pub point_light_matrices: Box<[shadow::PointLightMatrix; 126]>,
|
||||
}
|
||||
|
||||
pub struct GlobalsBindGroup {
|
||||
pub(super) bind_group: wgpu::BindGroup,
|
||||
pub(super) shadow_textures: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
pub struct GlobalsLayouts {
|
||||
pub globals: wgpu::BindGroupLayout,
|
||||
pub col_light: wgpu::BindGroupLayout,
|
||||
pub shadow_textures: wgpu::BindGroupLayout,
|
||||
}
|
||||
|
||||
pub struct ColLights<Locals> {
|
||||
@ -357,13 +360,13 @@ impl GlobalsLayouts {
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// point shadow_maps
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 10,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::Cube,
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
@ -371,46 +374,6 @@ impl GlobalsLayouts {
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 11,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: true,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// directed shadow maps
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 12,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 13,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: true,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 14,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 15,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: false,
|
||||
@ -446,7 +409,57 @@ impl GlobalsLayouts {
|
||||
],
|
||||
});
|
||||
|
||||
Self { globals, col_light }
|
||||
let shadow_textures = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[
|
||||
// point shadow_maps
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::Cube,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: true,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
// directed shadow maps
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison: true,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Self {
|
||||
globals,
|
||||
col_light,
|
||||
shadow_textures,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(
|
||||
@ -509,36 +522,45 @@ impl GlobalsLayouts {
|
||||
binding: 9,
|
||||
resource: global_model.shadow_mats.buf().as_entire_binding(),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 10,
|
||||
resource: wgpu::BindingResource::TextureView(&point_shadow_map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 11,
|
||||
resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler),
|
||||
},
|
||||
// directed shadow maps
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 12,
|
||||
resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 13,
|
||||
resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler),
|
||||
},
|
||||
// lod map (t_map)
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 14,
|
||||
binding: 10,
|
||||
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 15,
|
||||
binding: 11,
|
||||
resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
GlobalsBindGroup { bind_group }
|
||||
let shadow_textures = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &self.shadow_textures,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&point_shadow_map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(&point_shadow_map.sampler),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 2,
|
||||
resource: wgpu::BindingResource::TextureView(&directed_shadow_map.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 3,
|
||||
resource: wgpu::BindingResource::Sampler(&directed_shadow_map.sampler),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
GlobalsBindGroup {
|
||||
bind_group,
|
||||
shadow_textures,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_col_light<Locals>(
|
||||
|
@ -186,7 +186,7 @@ impl ParticlePipeline {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Particle pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[&global_layout.globals],
|
||||
bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::super::{
|
||||
AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex,
|
||||
Texture,
|
||||
AaMode, Bound, ColLightInfo, Consts, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout,
|
||||
TerrainVertex, Texture,
|
||||
};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use vek::*;
|
||||
@ -21,24 +21,10 @@ impl Locals {
|
||||
}
|
||||
|
||||
pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
|
||||
|
||||
fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub type BoundLocals = Bound<Consts<Locals>>;
|
||||
|
||||
pub struct ShadowLayout {
|
||||
pub locals: wgpu::BindGroupLayout,
|
||||
}
|
||||
@ -46,9 +32,47 @@ pub struct ShadowLayout {
|
||||
impl ShadowLayout {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
Self {
|
||||
locals: Locals::layout(device),
|
||||
locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &self.locals,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: locals.buf().as_entire_binding(),
|
||||
}],
|
||||
});
|
||||
|
||||
BoundLocals {
|
||||
bind_group,
|
||||
with: locals,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct PointLightMatrix([[f32; 4]; 4]);
|
||||
|
||||
impl PointLightMatrix {
|
||||
pub fn new(shadow_mat: Mat4<f32>) -> Self { Self(shadow_mat.into_col_arrays()) }
|
||||
|
||||
pub fn default() -> Self { Self::new(Mat4::identity()) }
|
||||
}
|
||||
|
||||
pub fn create_col_lights(
|
||||
@ -109,23 +133,17 @@ impl ShadowFigurePipeline {
|
||||
device: &wgpu::Device,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
global_layout: &GlobalsLayouts,
|
||||
figure_layout: &FigureLayout,
|
||||
layout: &ShadowLayout,
|
||||
aa_mode: AaMode,
|
||||
) -> Self {
|
||||
common::span!(_guard, "new");
|
||||
tracing::error!("test");
|
||||
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Shadow figure pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&figure_layout.locals,
|
||||
&layout.locals,
|
||||
],
|
||||
bind_group_layouts: &[&global_layout.globals, &figure_layout.locals],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
@ -151,7 +169,7 @@ impl ShadowFigurePipeline {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
clamp_depth: false,
|
||||
clamp_depth: true,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
@ -193,21 +211,15 @@ impl ShadowPipeline {
|
||||
device: &wgpu::Device,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
sc_desc: &wgpu::SwapChainDescriptor,
|
||||
global_layout: &GlobalsLayouts,
|
||||
terrain_layout: &TerrainLayout,
|
||||
layout: &ShadowLayout,
|
||||
aa_mode: AaMode,
|
||||
) -> Self {
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Shadow pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&terrain_layout.locals,
|
||||
&layout.locals,
|
||||
],
|
||||
bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
@ -233,7 +245,85 @@ impl ShadowPipeline {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
clamp_depth: false,
|
||||
clamp_depth: true,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[],
|
||||
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
|
||||
format: wgpu::TextureFormat::Depth24Plus,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::Less,
|
||||
stencil: wgpu::StencilStateDescriptor {
|
||||
front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||
read_mask: !0,
|
||||
write_mask: !0,
|
||||
},
|
||||
}),
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: None,
|
||||
vertex_buffers: &[TerrainVertex::desc()],
|
||||
},
|
||||
sample_count: samples,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
});
|
||||
|
||||
Self {
|
||||
pipeline: render_pipeline,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct PointShadowPipeline {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
}
|
||||
|
||||
impl PointShadowPipeline {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
global_layout: &GlobalsLayouts,
|
||||
terrain_layout: &TerrainLayout,
|
||||
aa_mode: AaMode,
|
||||
) -> Self {
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Shadow pipeline layout"),
|
||||
push_constant_ranges: &[wgpu::PushConstantRange {
|
||||
stages: wgpu::ShaderStage::all(),
|
||||
range: 0..64,
|
||||
}],
|
||||
bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
AaMode::None | AaMode::Fxaa => 1,
|
||||
// TODO: Ensure sampling in the shader is exactly between the 4 texels
|
||||
AaMode::MsaaX4 => 4,
|
||||
AaMode::MsaaX8 => 8,
|
||||
AaMode::MsaaX16 => 16,
|
||||
};
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Shadow pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: vs_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
|
||||
module: fs_module,
|
||||
entry_point: "main",
|
||||
}),
|
||||
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
clamp_depth: true,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
|
@ -44,7 +44,7 @@ impl SkyboxPipeline {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Skybox pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[&layouts.globals],
|
||||
bind_group_layouts: &[&layouts.globals, &layouts.shadow_textures],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
|
@ -219,6 +219,7 @@ impl SpritePipeline {
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&terrain_layout.locals,
|
||||
&layout.locals,
|
||||
&global_layout.col_light,
|
||||
|
@ -219,6 +219,7 @@ impl TerrainPipeline {
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[
|
||||
&global_layout.globals,
|
||||
&global_layout.shadow_textures,
|
||||
&layout.locals,
|
||||
&global_layout.col_light,
|
||||
],
|
||||
|
@ -124,7 +124,7 @@ pub struct ShadowMapRenderer {
|
||||
|
||||
point_depth: Texture,
|
||||
|
||||
point_pipeline: shadow::ShadowPipeline,
|
||||
point_pipeline: shadow::PointShadowPipeline,
|
||||
terrain_directed_pipeline: shadow::ShadowPipeline,
|
||||
figure_directed_pipeline: shadow::ShadowFigurePipeline,
|
||||
layout: shadow::ShadowLayout,
|
||||
@ -292,12 +292,18 @@ impl Renderer {
|
||||
|
||||
use wgpu::{Features, Limits};
|
||||
|
||||
let mut limits = Limits::default();
|
||||
limits.max_bind_groups = 5;
|
||||
limits.max_push_constant_size = 64;
|
||||
|
||||
let (device, queue) = futures::executor::block_on(adapter.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
// TODO
|
||||
label: None,
|
||||
features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
limits: Limits::default(),
|
||||
features: Features::DEPTH_CLAMPING
|
||||
| Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||
| Features::PUSH_CONSTANTS,
|
||||
limits,
|
||||
shader_validation: true,
|
||||
},
|
||||
None,
|
||||
@ -956,33 +962,6 @@ impl Renderer {
|
||||
// }
|
||||
}
|
||||
|
||||
// /// Set up shadow rendering.
|
||||
// pub fn start_shadows(&mut self) {
|
||||
// if !self.mode.shadow.is_map() {
|
||||
// return;
|
||||
// }
|
||||
// if let Some(_shadow_map) = self.shadow_map.as_mut() {
|
||||
// self.encoder.flush(&mut self.device);
|
||||
// Self::set_depth_clamp(&mut self.device, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// Perform all queued draw calls for global.shadows.
|
||||
// pub fn flush_shadows(&mut self) {
|
||||
// if !self.mode.shadow.is_map() {
|
||||
// return;
|
||||
// }
|
||||
// if let Some(_shadow_map) = self.shadow_map.as_mut() {
|
||||
// let point_encoder = &mut self.encoder;
|
||||
// // let point_encoder = &mut shadow_map.point_encoder;
|
||||
// point_encoder.flush(&mut self.device);
|
||||
// // let directed_encoder = &mut shadow_map.directed_encoder;
|
||||
// // directed_encoder.flush(&mut self.device);
|
||||
// // Reset depth clamping.
|
||||
// Self::set_depth_clamp(&mut self.device, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Start recording the frame
|
||||
/// When the returned `Drawer` is dropped the recorded draw calls will be
|
||||
/// submitted to the queue
|
||||
@ -2023,7 +2002,7 @@ fn create_pipelines(
|
||||
clouds::CloudsPipeline,
|
||||
postprocess::PostProcessPipeline,
|
||||
//figure::FigurePipeline,
|
||||
Option<shadow::ShadowPipeline>,
|
||||
Option<shadow::PointShadowPipeline>,
|
||||
Option<shadow::ShadowPipeline>,
|
||||
Option<shadow::ShadowFigurePipeline>,
|
||||
),
|
||||
@ -2278,77 +2257,35 @@ fn create_pipelines(
|
||||
// gfx::state::CullFace::Back,
|
||||
// )?;
|
||||
|
||||
// Sharp can fix it later ;)
|
||||
//
|
||||
// // Construct a pipeline for rendering point light terrain shadow maps.
|
||||
// let point_shadow_pipeline = match create_shadow_pipeline(
|
||||
// factory,
|
||||
// shadow::pipe::new(),
|
||||
// &terrain_point_shadow_vert,
|
||||
// Some(
|
||||
// &Glsl::load_watched(
|
||||
// "voxygen.shaders.light-shadows-geom",
|
||||
// shader_reload_indicator,
|
||||
// )
|
||||
// .unwrap(),
|
||||
// ),
|
||||
// &Glsl::load_watched(
|
||||
// "voxygen.shaders.light-shadows-frag",
|
||||
// shader_reload_indicator,
|
||||
// )
|
||||
// .unwrap(),
|
||||
// &include_ctx,
|
||||
// gfx::state::CullFace::Back,
|
||||
// None, // Some(gfx::state::Offset(2, 0))
|
||||
// ) {
|
||||
// Ok(pipe) => Some(pipe),
|
||||
// Err(err) => {
|
||||
// warn!("Could not load point shadow map pipeline: {:?}", err);
|
||||
// None
|
||||
// },
|
||||
// };
|
||||
// Construct a pipeline for rendering point light terrain shadow maps.
|
||||
let point_shadow_pipeline = shadow::PointShadowPipeline::new(
|
||||
device,
|
||||
&create_shader("point-light-shadows-vert", ShaderKind::Vertex)?,
|
||||
&create_shader("light-shadows-frag", ShaderKind::Fragment)?,
|
||||
&layouts.global,
|
||||
&layouts.terrain,
|
||||
mode.aa,
|
||||
);
|
||||
|
||||
// // Construct a pipeline for rendering directional light terrain shadow maps.
|
||||
// let terrain_directed_shadow_pipeline = match create_shadow_pipeline(
|
||||
// factory,
|
||||
// shadow::pipe::new(),
|
||||
// &terrain_directed_shadow_vert,
|
||||
// None,
|
||||
// &directed_shadow_frag,
|
||||
// &include_ctx,
|
||||
// gfx::state::CullFace::Back,
|
||||
// None, // Some(gfx::state::Offset(2, 1))
|
||||
// ) {
|
||||
// Ok(pipe) => Some(pipe),
|
||||
// Err(err) => {
|
||||
// warn!(
|
||||
// "Could not load directed terrain shadow map pipeline: {:?}",
|
||||
// err
|
||||
// );
|
||||
// None
|
||||
// },
|
||||
// };
|
||||
// Construct a pipeline for rendering directional light terrain shadow maps.
|
||||
let terrain_directed_shadow_pipeline = shadow::ShadowPipeline::new(
|
||||
device,
|
||||
&terrain_directed_shadow_vert_mod,
|
||||
&directed_shadow_frag_mod,
|
||||
&layouts.global,
|
||||
&layouts.terrain,
|
||||
mode.aa,
|
||||
);
|
||||
|
||||
// // Construct a pipeline for rendering directional light figure shadow maps.
|
||||
// let figure_directed_shadow_pipeline = match create_shadow_pipeline(
|
||||
// factory,
|
||||
// shadow::figure_pipe::new(),
|
||||
// &figure_directed_shadow_vert,
|
||||
// None,
|
||||
// &directed_shadow_frag,
|
||||
// &include_ctx,
|
||||
// gfx::state::CullFace::Back,
|
||||
// None, // Some(gfx::state::Offset(2, 1))
|
||||
// ) {
|
||||
// Ok(pipe) => Some(pipe),
|
||||
// Err(err) => {
|
||||
// warn!(
|
||||
// "Could not load directed figure shadow map pipeline: {:?}",
|
||||
// err
|
||||
// );
|
||||
// None
|
||||
// },
|
||||
// };
|
||||
// Construct a pipeline for rendering directional light figure shadow maps.
|
||||
let figure_directed_shadow_pipeline = shadow::ShadowFigurePipeline::new(
|
||||
device,
|
||||
&figure_directed_shadow_vert_mod,
|
||||
&directed_shadow_frag_mod,
|
||||
&layouts.global,
|
||||
&layouts.figure,
|
||||
mode.aa,
|
||||
);
|
||||
|
||||
Ok((
|
||||
skybox_pipeline,
|
||||
@ -2362,9 +2299,9 @@ fn create_pipelines(
|
||||
clouds_pipeline,
|
||||
postprocess_pipeline,
|
||||
// player_shadow_pipeline,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(point_shadow_pipeline),
|
||||
Some(terrain_directed_shadow_pipeline),
|
||||
Some(figure_directed_shadow_pipeline),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{
|
||||
super::{
|
||||
pipelines::{
|
||||
figure, fluid, lod_terrain, sprite, terrain, ui, ColLights, GlobalModel,
|
||||
figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel,
|
||||
GlobalsBindGroup,
|
||||
},
|
||||
texture::Texture,
|
||||
@ -59,6 +59,11 @@ impl Renderer {
|
||||
self.layouts.terrain.bind_locals(&self.device, locals)
|
||||
}
|
||||
|
||||
pub fn create_shadow_bound_locals(&mut self, locals: &[shadow::Locals]) -> shadow::BoundLocals {
|
||||
let locals = self.create_consts(locals);
|
||||
self.layouts.shadow.bind_locals(&self.device, locals)
|
||||
}
|
||||
|
||||
pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals {
|
||||
let locals = self.create_consts(locals);
|
||||
self.layouts.sprite.bind_locals(&self.device, locals)
|
||||
|
@ -5,18 +5,18 @@ use super::{
|
||||
instances::Instances,
|
||||
model::{DynamicModel, Model, SubModel},
|
||||
pipelines::{
|
||||
clouds, figure, fluid, lod_terrain, particle, postprocess, skybox, sprite, terrain, ui,
|
||||
ColLights, GlobalsBindGroup, Light, Shadow,
|
||||
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite,
|
||||
terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow,
|
||||
},
|
||||
},
|
||||
Renderer,
|
||||
Renderer, ShadowMapRenderer,
|
||||
};
|
||||
use std::ops::Range;
|
||||
use std::{ops::Range};
|
||||
use vek::Aabr;
|
||||
|
||||
pub struct Drawer<'a> {
|
||||
encoder: Option<wgpu::CommandEncoder>,
|
||||
renderer: &'a mut Renderer,
|
||||
pub renderer: &'a mut Renderer,
|
||||
tex: wgpu::SwapChainTexture,
|
||||
globals: &'a GlobalsBindGroup,
|
||||
}
|
||||
@ -63,6 +63,7 @@ impl<'a> Drawer<'a> {
|
||||
});
|
||||
|
||||
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]);
|
||||
|
||||
FirstPassDrawer {
|
||||
render_pass,
|
||||
@ -70,6 +71,38 @@ impl<'a> Drawer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shadow_pass(&mut self) -> Option<ShadowDrawer> {
|
||||
if let Some(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
|
||||
@ -88,6 +121,7 @@ impl<'a> Drawer<'a> {
|
||||
});
|
||||
|
||||
render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]);
|
||||
|
||||
SecondPassDrawer {
|
||||
render_pass,
|
||||
@ -119,6 +153,68 @@ impl<'a> Drawer<'a> {
|
||||
renderer: &self.renderer,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_point_shadow<'b: 'a>(
|
||||
&mut self,
|
||||
model: &'b Model<terrain::Vertex>,
|
||||
locals: &'b terrain::BoundLocals,
|
||||
matrices: &[shadow::PointLightMatrix; 126],
|
||||
) {
|
||||
if let Some(ref shadow_renderer) = self.renderer.shadow_map {
|
||||
const STRIDE: usize = std::mem::size_of::<shadow::PointLightMatrix>();
|
||||
let data = bytemuck::cast_slice(matrices);
|
||||
|
||||
for face in 0..6 {
|
||||
let view =
|
||||
shadow_renderer
|
||||
.point_depth
|
||||
.tex
|
||||
.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: Some("Point shadow cubemap face"),
|
||||
format: None,
|
||||
dimension: Some(wgpu::TextureViewDimension::D2Array),
|
||||
aspect: wgpu::TextureAspect::All,
|
||||
base_mip_level: 0,
|
||||
level_count: None,
|
||||
base_array_layer: face,
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
let mut render_pass =
|
||||
self.encoder
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(
|
||||
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Drawer<'a> {
|
||||
@ -159,9 +255,9 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(2, &col_lights.bind_group, &[]);
|
||||
.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);
|
||||
}
|
||||
@ -174,9 +270,9 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
) {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(2, &col_lights.bind_group, &[]);
|
||||
.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)
|
||||
}
|
||||
@ -201,10 +297,10 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
|
||||
self.render_pass
|
||||
.set_bind_group(1, &terrain_locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
.set_bind_group(2, &terrain_locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
self.render_pass
|
||||
.set_bind_group(3, &col_lights.bind_group, &[]);
|
||||
.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(..));
|
||||
@ -215,7 +311,7 @@ impl<'a> FirstPassDrawer<'a> {
|
||||
pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
|
||||
self.render_pass.set_bind_group(1, &waves.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(2, &waves.bind_group, &[]);
|
||||
|
||||
FluidDrawer {
|
||||
render_pass: &mut self.render_pass,
|
||||
@ -244,6 +340,38 @@ 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,
|
||||
}
|
||||
|
||||
impl<'pass> ShadowDrawer<'pass> {
|
||||
pub fn draw_figure_shadow<'b: 'pass>(
|
||||
&mut self,
|
||||
model: SubModel<'b, terrain::Vertex>,
|
||||
locals: &'b figure::BoundLocals,
|
||||
) {
|
||||
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);
|
||||
}
|
||||
|
||||
pub fn draw_terrain_shadow<'b: 'pass>(
|
||||
&mut self,
|
||||
model: &'b Model<terrain::Vertex>,
|
||||
locals: &'b terrain::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);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
||||
}
|
||||
@ -255,7 +383,7 @@ impl<'pass_ref, 'pass: 'pass_ref> FluidDrawer<'pass_ref, 'pass> {
|
||||
locals: &'data terrain::BoundLocals,
|
||||
) {
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
||||
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||
}
|
||||
}
|
||||
@ -270,7 +398,7 @@ impl<'a> SecondPassDrawer<'a> {
|
||||
self.render_pass
|
||||
.set_pipeline(&self.renderer.clouds_pipeline.pipeline);
|
||||
self.render_pass
|
||||
.set_bind_group(1, &self.renderer.locals.clouds_bind.bind_group, &[]);
|
||||
.set_bind_group(2, &self.renderer.locals.clouds_bind.bind_group, &[]);
|
||||
self.render_pass.draw(0..3, 0..1);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
render::{
|
||||
pipelines::{self, ColLights},
|
||||
ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel,
|
||||
LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex,
|
||||
LodData, Mesh, RenderError, Renderer, ShadowDrawer, SubModel, TerrainVertex,
|
||||
},
|
||||
scene::{
|
||||
camera::{Camera, CameraMode, Dependents},
|
||||
@ -4706,20 +4706,17 @@ impl FigureMgr {
|
||||
visible_aabb
|
||||
}
|
||||
|
||||
pub fn render_shadows(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
pub fn render_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
state: &State,
|
||||
tick: u64,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, _light_data): super::LightData,
|
||||
(camera, figure_lod_render_distance): CameraData,
|
||||
) {
|
||||
span!(_guard, "render_shadows", "FigureManager::render_shadows");
|
||||
let ecs = state.ecs();
|
||||
|
||||
if is_daylight && renderer.render_mode().shadow.is_map() {
|
||||
(
|
||||
(
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
ecs.read_storage::<Ori>().maybe(),
|
||||
@ -4744,17 +4741,9 @@ impl FigureMgr {
|
||||
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||
|state| state.can_shadow_sun(),
|
||||
) {
|
||||
// TODO
|
||||
//renderer.render_figure_shadow_directed(
|
||||
// model,
|
||||
// global,
|
||||
// locals,
|
||||
// bone_consts,
|
||||
// &global.shadow_mats,
|
||||
//);
|
||||
drawer.draw_figure_shadow(model, bound);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||
|
@ -16,9 +16,9 @@ pub use self::{
|
||||
use crate::{
|
||||
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
|
||||
render::{
|
||||
create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals,
|
||||
GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals,
|
||||
SkyboxVertex,
|
||||
create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals,
|
||||
GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow,
|
||||
ShadowDrawer, ShadowLocals, SkyboxVertex,
|
||||
},
|
||||
settings::Settings,
|
||||
window::{AnalogGameInput, Event},
|
||||
@ -268,8 +268,8 @@ impl Scene {
|
||||
globals: renderer.create_consts(&[Globals::default()]),
|
||||
lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]),
|
||||
shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]),
|
||||
shadow_mats: renderer
|
||||
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]),
|
||||
shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]),
|
||||
point_light_matrices: Box::new([PointLightMatrix::default(); MAX_LIGHT_COUNT * 6 + 6]),
|
||||
};
|
||||
|
||||
let lod = Lod::new(renderer, client, settings);
|
||||
@ -707,11 +707,200 @@ impl Scene {
|
||||
let new_dir = math::Vec3::from(view_dir);
|
||||
let new_dir = new_dir.normalized();
|
||||
let up: math::Vec3<f32> = math::Vec3::unit_y();
|
||||
directed_shadow_mats.push(math::Mat4::look_at_rh(
|
||||
look_at,
|
||||
look_at + directed_light_dir,
|
||||
up,
|
||||
));
|
||||
let light_view_mat = math::Mat4::look_at_rh(look_at, look_at + directed_light_dir, up);
|
||||
{
|
||||
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());
|
||||
|
||||
let directed_texture_proj_mat = texture_mat * directed_proj_mat;
|
||||
let shadow_locals = ShadowLocals::new(
|
||||
directed_proj_mat * shadow_all_mat,
|
||||
directed_texture_proj_mat * shadow_all_mat,
|
||||
);
|
||||
|
||||
renderer.update_consts(&mut self.data.shadow_mats, &[shadow_locals]);
|
||||
}
|
||||
directed_shadow_mats.push(light_view_mat);
|
||||
// This leaves us with five dummy slots, which we push as defaults.
|
||||
directed_shadow_mats
|
||||
.extend_from_slice(&[math::Mat4::default(); 6 - NUM_DIRECTED_LIGHTS] as _);
|
||||
@ -721,7 +910,7 @@ impl Scene {
|
||||
shadow_mats.extend(directed_shadow_mats.iter().enumerate().map(
|
||||
move |(idx, &light_view_mat)| {
|
||||
if idx >= NUM_DIRECTED_LIGHTS {
|
||||
return ShadowLocals::new(Mat4::identity(), Mat4::identity());
|
||||
return PointLightMatrix::new(Mat4::identity());
|
||||
}
|
||||
|
||||
let v_p_orig =
|
||||
@ -911,17 +1100,13 @@ impl Scene {
|
||||
let shadow_all_mat: Mat4<f32> =
|
||||
Mat4::from_col_arrays(shadow_all_mat.into_col_arrays());
|
||||
|
||||
let directed_texture_proj_mat = texture_mat * directed_proj_mat;
|
||||
ShadowLocals::new(
|
||||
directed_proj_mat * shadow_all_mat,
|
||||
directed_texture_proj_mat * shadow_all_mat,
|
||||
)
|
||||
PointLightMatrix::new(directed_proj_mat * shadow_all_mat)
|
||||
},
|
||||
));
|
||||
// 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).
|
||||
let shadow_proj = Mat4::perspective_rh_no(
|
||||
let shadow_proj = Mat4::perspective_rh_zo(
|
||||
90.0f32.to_radians(),
|
||||
point_shadow_aspect,
|
||||
SHADOW_NEAR,
|
||||
@ -947,14 +1132,13 @@ impl Scene {
|
||||
orientations.iter().map(move |&(forward, up)| {
|
||||
// NOTE: We don't currently try to linearize point lights or need a separate
|
||||
// transform for them.
|
||||
ShadowLocals::new(
|
||||
shadow_proj * Mat4::look_at_rh(eye, eye + forward, up),
|
||||
Mat4::identity(),
|
||||
)
|
||||
PointLightMatrix::new(shadow_proj * Mat4::look_at_rh(eye, eye + forward, up))
|
||||
})
|
||||
}));
|
||||
|
||||
renderer.update_consts(&mut self.data.shadow_mats, &shadow_mats);
|
||||
for (i, val) in shadow_mats.into_iter().enumerate() {
|
||||
self.data.point_light_matrices[i] = val
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unused figures.
|
||||
@ -976,7 +1160,87 @@ impl Scene {
|
||||
|
||||
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
|
||||
|
||||
/// Render the scene using the provided `Renderer`.
|
||||
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`.
|
||||
pub fn render<'a>(
|
||||
&'a self,
|
||||
drawer: &mut FirstPassDrawer<'a>,
|
||||
@ -992,29 +1256,8 @@ impl Scene {
|
||||
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 renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) {
|
||||
// if is_daylight {
|
||||
// // Set up shadow mapping.
|
||||
// renderer.start_shadows();
|
||||
// }
|
||||
|
||||
// Render terrain shadows.
|
||||
self.terrain
|
||||
.render_shadows(renderer, global, light_data, focus_pos);
|
||||
|
||||
// Render figure shadows.
|
||||
self.figure_mgr
|
||||
.render_shadows(renderer, state, tick, global, light_data, camera_data);
|
||||
|
||||
// if is_daylight {
|
||||
// // Flush shadows.
|
||||
// renderer.flush_shadows();
|
||||
// }
|
||||
}*/
|
||||
let lod = self.lod.get_data();
|
||||
|
||||
self.figure_mgr
|
||||
|
@ -2,8 +2,8 @@ use crate::{
|
||||
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
|
||||
render::{
|
||||
create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals,
|
||||
GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals,
|
||||
SkyboxVertex, TerrainVertex,
|
||||
GlobalsBindGroup, Light, LodData, Mesh, Model, PointLightMatrix, Renderer, Shadow,
|
||||
ShadowLocals, SkyboxVertex, TerrainVertex,
|
||||
},
|
||||
scene::{
|
||||
camera::{self, Camera, CameraMode},
|
||||
@ -109,7 +109,8 @@ impl Scene {
|
||||
globals: renderer.create_consts(&[Globals::default()]),
|
||||
lights: renderer.create_consts(&[Light::default(); 20]),
|
||||
shadows: renderer.create_consts(&[Shadow::default(); 24]),
|
||||
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
|
||||
shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]),
|
||||
point_light_matrices: Box::new([PointLightMatrix::default(); 126]),
|
||||
};
|
||||
let lod = LodData::dummy(renderer);
|
||||
|
||||
|
@ -9,9 +9,9 @@ use crate::{
|
||||
},
|
||||
render::{
|
||||
pipelines::{self, ColLights},
|
||||
ColLightInfo, Consts, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances,
|
||||
LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex,
|
||||
TerrainLocals, TerrainVertex, Texture,
|
||||
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel,
|
||||
Instances, LodData, Mesh, Model, RenderError, Renderer, ShadowDrawer, SpriteInstance,
|
||||
SpriteLocals, SpriteVertex, TerrainLocals, TerrainVertex, Texture,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1397,18 +1397,14 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
|
||||
pub fn shadow_chunk_count(&self) -> usize { self.shadow_chunks.len() }
|
||||
|
||||
pub fn render_shadows(
|
||||
&self,
|
||||
renderer: &mut Renderer,
|
||||
pub fn render_shadows<'a>(
|
||||
&'a self,
|
||||
drawer: &mut ShadowDrawer<'a>,
|
||||
global: &GlobalModel,
|
||||
(is_daylight, light_data): super::LightData,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
span!(_guard, "render_shadows", "Terrain::render_shadows");
|
||||
if !renderer.render_mode().shadow.is_map() {
|
||||
return;
|
||||
};
|
||||
|
||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||
(e as i32).div_euclid(sz as i32)
|
||||
});
|
||||
@ -1430,16 +1426,27 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
.clone()
|
||||
.filter(|chunk| chunk.can_shadow_sun())
|
||||
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
||||
.for_each(|chunk| {
|
||||
// Directed light shadows.
|
||||
/*renderer.render_terrain_shadow_directed(
|
||||
&chunk.opaque_model,
|
||||
global,
|
||||
&chunk.locals,
|
||||
&global.shadow_mats,
|
||||
);*/
|
||||
});
|
||||
.for_each(|chunk| drawer.draw_terrain_shadow(&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,
|
||||
focus_pos: Vec3<f32>,
|
||||
) {
|
||||
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| {
|
||||
let pos = focus_chunk + rpos;
|
||||
self.chunks.get(&pos)
|
||||
})
|
||||
.take(self.chunks.len());
|
||||
|
||||
// Point shadows
|
||||
//
|
||||
@ -1448,12 +1455,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
light_data.iter().take(1).for_each(|_light| {
|
||||
chunk_iter.clone().for_each(|chunk| {
|
||||
if chunk.can_shadow_point {
|
||||
/*renderer.render_shadow_point(
|
||||
drawer.draw_point_shadow(
|
||||
&chunk.opaque_model,
|
||||
global,
|
||||
&chunk.locals,
|
||||
&global.shadow_mats,
|
||||
);*/
|
||||
&global.point_light_matrices,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1418,6 +1418,33 @@ 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_point_shadows(
|
||||
&mut drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
client.get_tick(),
|
||||
&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(),
|
||||
|
Loading…
Reference in New Issue
Block a user