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 <srgb.glsl>
|
||||||
#include <cloud.glsl>
|
#include <cloud.glsl>
|
||||||
|
|
||||||
layout(set = 1, binding = 0)
|
layout(set = 2, binding = 0)
|
||||||
uniform texture2D t_src_color;
|
uniform texture2D t_src_color;
|
||||||
layout(set = 1, binding = 1)
|
layout(set = 2, binding = 1)
|
||||||
uniform sampler s_src_color;
|
uniform sampler s_src_color;
|
||||||
|
|
||||||
layout(set = 1, binding = 2)
|
layout(set = 2, binding = 2)
|
||||||
uniform texture2D t_src_depth;
|
uniform texture2D t_src_depth;
|
||||||
layout(set = 1, binding = 3)
|
layout(set = 2, binding = 3)
|
||||||
uniform sampler s_src_depth;
|
uniform sampler s_src_depth;
|
||||||
|
|
||||||
layout(location = 0) in vec2 uv;
|
layout(location = 0) in vec2 uv;
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 4)
|
layout (std140, set = 2, binding = 4)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
mat4 proj_mat_inv;
|
mat4 proj_mat_inv;
|
||||||
mat4 view_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);
|
// const vec4 sun_pos = vec4(0.0);
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
layout(set = 2, binding = 0)
|
layout(set = 3, binding = 0)
|
||||||
uniform texture2D t_col_light;
|
uniform texture2D t_col_light;
|
||||||
layout(set = 2, binding = 1)
|
layout(set = 3, binding = 1)
|
||||||
uniform sampler s_col_light;
|
uniform sampler s_col_light;
|
||||||
|
|
||||||
//struct ShadowLocals {
|
//struct ShadowLocals {
|
||||||
@ -52,7 +52,7 @@ uniform sampler s_col_light;
|
|||||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||||
//};
|
//};
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 0)
|
layout (std140, set = 2, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
mat4 model_mat;
|
mat4 model_mat;
|
||||||
vec4 highlight_col;
|
vec4 highlight_col;
|
||||||
@ -70,7 +70,7 @@ struct BoneData {
|
|||||||
mat4 normals_mat;
|
mat4 normals_mat;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 1)
|
layout (std140, set = 2, binding = 1)
|
||||||
uniform u_bones {
|
uniform u_bones {
|
||||||
BoneData bones[16];
|
BoneData bones[16];
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,7 @@ layout(location = 1) in uint v_atlas_pos;
|
|||||||
// out vec3 light_pos[2];
|
// out vec3 light_pos[2];
|
||||||
in uint v_ao_bone; */
|
in uint v_ao_bone; */
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 0)
|
layout (std140, set = 2, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
mat4 model_mat;
|
mat4 model_mat;
|
||||||
vec4 highlight_col;
|
vec4 highlight_col;
|
||||||
@ -43,7 +43,7 @@ struct BoneData {
|
|||||||
mat4 normals_mat;
|
mat4 normals_mat;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 1)
|
layout (std140, set = 2, binding = 1)
|
||||||
uniform u_bones {
|
uniform u_bones {
|
||||||
// Warning: might not actually be 16 elements long. Don't index out of bounds!
|
// Warning: might not actually be 16 elements long. Don't index out of bounds!
|
||||||
BoneData bones[16];
|
BoneData bones[16];
|
||||||
|
@ -37,16 +37,16 @@ layout(location = 1) flat in uint f_pos_norm;
|
|||||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||||
// };
|
// };
|
||||||
|
|
||||||
layout(std140, set = 2, binding = 0)
|
layout(std140, set = 3, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
ivec4 atlas_offs;
|
ivec4 atlas_offs;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 1, binding = 0)
|
layout(set = 2, binding = 0)
|
||||||
uniform texture2D t_waves;
|
uniform texture2D t_waves;
|
||||||
layout(set = 1, binding = 1)
|
layout(set = 2, binding = 1)
|
||||||
uniform sampler s_waves;
|
uniform sampler s_waves;
|
||||||
|
|
||||||
layout(location = 0) out vec4 tgt_color;
|
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];
|
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||||
//};
|
//};
|
||||||
|
|
||||||
layout(std140, set = 2, binding = 0)
|
layout(std140, set = 3, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
ivec4 atlas_offs;
|
ivec4 atlas_offs;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 1, binding = 0)
|
layout(set = 2, binding = 0)
|
||||||
uniform texture2D t_waves;
|
uniform texture2D t_waves;
|
||||||
layout(set = 1, binding = 1)
|
layout(set = 2, binding = 1)
|
||||||
uniform sampler s_waves;
|
uniform sampler s_waves;
|
||||||
|
|
||||||
layout(location = 0) out vec4 tgt_color;
|
layout(location = 0) out vec4 tgt_color;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
layout(location = 0) in uint v_pos_norm;
|
layout(location = 0) in uint v_pos_norm;
|
||||||
// in uint v_col_light;
|
// in uint v_col_light;
|
||||||
|
|
||||||
layout(std140, set = 2, binding = 0)
|
layout(std140, set = 3, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
|
@ -330,9 +330,9 @@ vec3 lod_pos(vec2 pos, vec2 focus_pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_LOD_FULL_INFO
|
#ifdef HAS_LOD_FULL_INFO
|
||||||
layout(set = 0, binding = 14)
|
layout(set = 0, binding = 10)
|
||||||
uniform texture2D t_map;
|
uniform texture2D t_map;
|
||||||
layout(set = 0, binding = 15)
|
layout(set = 0, binding = 11)
|
||||||
uniform sampler s_map;
|
uniform sampler s_map;
|
||||||
|
|
||||||
vec3 lod_col(vec2 pos) {
|
vec3 lod_col(vec2 pos) {
|
||||||
|
@ -3,30 +3,26 @@
|
|||||||
|
|
||||||
#ifdef HAS_SHADOW_MAPS
|
#ifdef HAS_SHADOW_MAPS
|
||||||
|
|
||||||
#if (SHADOW_MODE == SHADOW_MODE_MAP)
|
#if (SHADOW_MODE == SHADOW_MODE_MAP)
|
||||||
struct ShadowLocals {
|
layout (std140, set = 0, binding = 9)
|
||||||
|
uniform u_light_shadows {
|
||||||
mat4 shadowMatrices;
|
mat4 shadowMatrices;
|
||||||
mat4 texture_mat;
|
mat4 texture_mat;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (std140, set = 0, binding = 9)
|
|
||||||
uniform u_light_shadows {
|
|
||||||
ShadowLocals shadowMats[/*MAX_LAYER_FACES*//*192*/126];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use with sampler2DShadow
|
// Use with sampler2DShadow
|
||||||
layout(set = 0, binding = 12)
|
layout(set = 1, binding = 2)
|
||||||
uniform texture2D t_directed_shadow_maps;
|
uniform texture2D t_directed_shadow_maps;
|
||||||
layout(set = 0, binding = 13)
|
layout(set = 1, binding = 3)
|
||||||
uniform sampler s_directed_shadow_maps;
|
uniform sampler s_directed_shadow_maps;
|
||||||
// uniform sampler2DArrayShadow t_directed_shadow_maps;
|
// uniform sampler2DArrayShadow t_directed_shadow_maps;
|
||||||
|
|
||||||
// uniform samplerCubeArrayShadow t_shadow_maps;
|
// uniform samplerCubeArrayShadow t_shadow_maps;
|
||||||
// uniform samplerCubeArray t_shadow_maps;
|
// uniform samplerCubeArray t_shadow_maps;
|
||||||
// Use with samplerCubeShadow
|
// Use with samplerCubeShadow
|
||||||
layout(set = 0, binding = 10)
|
layout(set = 1, binding = 0)
|
||||||
uniform textureCube t_point_shadow_maps;
|
uniform textureCube t_point_shadow_maps;
|
||||||
layout(set = 0, binding = 11)
|
layout(set = 1, binding = 1)
|
||||||
uniform sampler s_point_shadow_maps;
|
uniform sampler s_point_shadow_maps;
|
||||||
// uniform samplerCube t_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;
|
// vec3 fragPos = sun_pos.xyz;// / sun_pos.w;//light_pos[lightIndex].xyz;
|
||||||
// sun_pos.z += sun_pos.w * bias;
|
// sun_pos.z += sun_pos.w * bias;
|
||||||
mat4 texture_mat = shadowMats[0].texture_mat;
|
|
||||||
vec4 sun_pos = texture_mat * vec4(fragPos, 1.0);
|
vec4 sun_pos = texture_mat * vec4(fragPos, 1.0);
|
||||||
// sun_pos.z -= sun_pos.w * bias;
|
// sun_pos.z -= sun_pos.w * bias;
|
||||||
float visibility = textureProj(sampler2DShadow(t_directed_shadow_maps, s_directed_shadow_maps), sun_pos);
|
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.
|
// Currently, we only need globals for focus_off.
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
// For shadow locals.
|
// 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!
|
/* Accurate packed shadow maps for many lights at once!
|
||||||
*
|
*
|
||||||
@ -54,7 +60,7 @@ void main() {
|
|||||||
// vec3 f_pos = f_chunk_pos + model_offs;
|
// vec3 f_pos = f_chunk_pos + model_offs;
|
||||||
|
|
||||||
// gl_Position = v_pos + vec4(model_offs, 0.0);
|
// 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 = -gl_Position.z;
|
||||||
// gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
// gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
||||||
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
|
// shadowMapCoord = lights[gl_InstanceID].light_pos * gl_Vertex;
|
||||||
|
@ -24,7 +24,13 @@
|
|||||||
// Currently, we only need globals for focus_off.
|
// Currently, we only need globals for focus_off.
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
// For shadow locals.
|
// 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!
|
/* Accurate packed shadow maps for many lights at once!
|
||||||
*
|
*
|
||||||
@ -73,6 +79,6 @@ void main() {
|
|||||||
vec4(pos, 1.0)
|
vec4(pos, 1.0)
|
||||||
).xyz + (model_pos - focus_off.xyz/* + vec3(0.0, 0.0, 0.0001)*/);
|
).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
|
#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 float f_light;
|
||||||
// in vec4 light_pos[2];
|
// in vec4 light_pos[2];
|
||||||
|
|
||||||
layout(set = 3, binding = 0)
|
layout(set = 4, binding = 0)
|
||||||
uniform texture2D t_col_light;
|
uniform texture2D t_col_light;
|
||||||
layout(set = 3, binding = 1)
|
layout(set = 4, binding = 1)
|
||||||
uniform sampler s_col_light;
|
uniform sampler s_col_light;
|
||||||
|
|
||||||
//struct ShadowLocals {
|
//struct ShadowLocals {
|
||||||
|
@ -34,7 +34,7 @@ struct SpriteLocals {
|
|||||||
vec4 offs;
|
vec4 offs;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140, set = 2, binding = 0)
|
layout(std140, set = 3, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
mat4 mat;
|
mat4 mat;
|
||||||
vec4 wind_sway;
|
vec4 wind_sway;
|
||||||
@ -63,7 +63,7 @@ uniform u_locals {
|
|||||||
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
// ShadowLocals shadowMats[/*MAX_LAYER_FACES*/192];
|
||||||
//};
|
//};
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 0)
|
layout (std140, set = 2, binding = 0)
|
||||||
uniform u_terrain_locals {
|
uniform u_terrain_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
|
@ -45,12 +45,12 @@ in vec4 sun_pos;
|
|||||||
const vec4 sun_pos = vec4(0.0);
|
const vec4 sun_pos = vec4(0.0);
|
||||||
#endif */
|
#endif */
|
||||||
|
|
||||||
layout(set = 2, binding = 0)
|
layout(set = 3, binding = 0)
|
||||||
uniform texture2D t_col_light;
|
uniform texture2D t_col_light;
|
||||||
layout(set = 2, binding = 1)
|
layout(set = 3, binding = 1)
|
||||||
uniform sampler s_col_light;
|
uniform sampler s_col_light;
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 0)
|
layout (std140, set = 2, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
|
@ -28,7 +28,7 @@ layout(location = 0) in uint v_pos_norm;
|
|||||||
// in uint v_col_light;
|
// in uint v_col_light;
|
||||||
layout(location = 1) in uint v_atlas_pos;
|
layout(location = 1) in uint v_atlas_pos;
|
||||||
|
|
||||||
layout (std140, set = 1, binding = 0)
|
layout (std140, set = 2, binding = 0)
|
||||||
uniform u_locals {
|
uniform u_locals {
|
||||||
vec3 model_offs;
|
vec3 model_offs;
|
||||||
float load_time;
|
float load_time;
|
||||||
@ -155,7 +155,7 @@ void main() {
|
|||||||
|
|
||||||
#ifdef HAS_SHADOW_MAPS
|
#ifdef HAS_SHADOW_MAPS
|
||||||
gl_Position =
|
gl_Position =
|
||||||
/*all_mat*/shadowMats[0].shadowMatrices/*texture_mat*/ *
|
/*all_mat*/shadowMatrices/*texture_mat*/ *
|
||||||
vec4(f_pos/*newRay*/, 1);
|
vec4(f_pos/*newRay*/, 1);
|
||||||
gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
gl_Position.z = clamp(gl_Position.z, -abs(gl_Position.w), abs(gl_Position.w));
|
||||||
#else
|
#else
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::render::{
|
use crate::render::{
|
||||||
GlobalModel, Globals, GlobalsBindGroup, Light, LodData, Renderer, Shadow, ShadowLocals,
|
GlobalModel, Globals, GlobalsBindGroup, Light, LodData, PointLightMatrix, Renderer, Shadow,
|
||||||
|
ShadowLocals,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
@ -12,7 +13,8 @@ impl Scene {
|
|||||||
globals: renderer.create_consts(&[Globals::default()]),
|
globals: renderer.create_consts(&[Globals::default()]),
|
||||||
lights: renderer.create_consts(&[Light::default(); 32]),
|
lights: renderer.create_consts(&[Light::default(); 32]),
|
||||||
shadows: renderer.create_consts(&[Shadow::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);
|
let lod_data = LodData::dummy(renderer);
|
||||||
|
@ -28,7 +28,7 @@ pub use self::{
|
|||||||
lod_terrain::{LodData, Vertex as LodTerrainVertex},
|
lod_terrain::{LodData, Vertex as LodTerrainVertex},
|
||||||
particle::{Instance as ParticleInstance, Vertex as ParticleVertex},
|
particle::{Instance as ParticleInstance, Vertex as ParticleVertex},
|
||||||
postprocess::Locals as PostProcessLocals,
|
postprocess::Locals as PostProcessLocals,
|
||||||
shadow::Locals as ShadowLocals,
|
shadow::{Locals as ShadowLocals, PointLightMatrix},
|
||||||
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
|
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
|
||||||
sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex},
|
sprite::{Instance as SpriteInstance, Locals as SpriteLocals, Vertex as SpriteVertex},
|
||||||
terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex},
|
terrain::{Locals as TerrainLocals, TerrainLayout, Vertex as TerrainVertex},
|
||||||
@ -43,7 +43,7 @@ pub use self::{
|
|||||||
renderer::{
|
renderer::{
|
||||||
drawer::{
|
drawer::{
|
||||||
Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer,
|
Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer,
|
||||||
ThirdPassDrawer, UiDrawer,
|
ShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||||
},
|
},
|
||||||
ColLightInfo, Renderer,
|
ColLightInfo, Renderer,
|
||||||
},
|
},
|
||||||
|
@ -153,7 +153,11 @@ impl CloudsPipeline {
|
|||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Clouds pipeline layout"),
|
label: Some("Clouds pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
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 {
|
let samples = match aa_mode {
|
||||||
|
@ -185,6 +185,7 @@ impl FigurePipeline {
|
|||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
&global_layout.globals,
|
&global_layout.globals,
|
||||||
|
&global_layout.shadow_textures,
|
||||||
&layout.locals,
|
&layout.locals,
|
||||||
&global_layout.col_light,
|
&global_layout.col_light,
|
||||||
],
|
],
|
||||||
|
@ -128,6 +128,7 @@ impl FluidPipeline {
|
|||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
&global_layout.globals,
|
&global_layout.globals,
|
||||||
|
&global_layout.shadow_textures,
|
||||||
&layout.waves,
|
&layout.waves,
|
||||||
&terrain_layout.locals,
|
&terrain_layout.locals,
|
||||||
],
|
],
|
||||||
|
@ -148,7 +148,7 @@ impl LodTerrainPipeline {
|
|||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Lod terrain pipeline layout"),
|
label: Some("Lod terrain pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[&global_layout.globals],
|
bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
|
||||||
});
|
});
|
||||||
|
|
||||||
let samples = match aa_mode {
|
let samples = match aa_mode {
|
||||||
|
@ -229,16 +229,19 @@ pub struct GlobalModel {
|
|||||||
pub globals: Consts<Globals>,
|
pub globals: Consts<Globals>,
|
||||||
pub lights: Consts<Light>,
|
pub lights: Consts<Light>,
|
||||||
pub shadows: Consts<Shadow>,
|
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 struct GlobalsBindGroup {
|
||||||
pub(super) bind_group: wgpu::BindGroup,
|
pub(super) bind_group: wgpu::BindGroup,
|
||||||
|
pub(super) shadow_textures: wgpu::BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GlobalsLayouts {
|
pub struct GlobalsLayouts {
|
||||||
pub globals: wgpu::BindGroupLayout,
|
pub globals: wgpu::BindGroupLayout,
|
||||||
pub col_light: wgpu::BindGroupLayout,
|
pub col_light: wgpu::BindGroupLayout,
|
||||||
|
pub shadow_textures: wgpu::BindGroupLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ColLights<Locals> {
|
pub struct ColLights<Locals> {
|
||||||
@ -357,13 +360,13 @@ impl GlobalsLayouts {
|
|||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
},
|
},
|
||||||
// point shadow_maps
|
// lod map (t_map)
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 10,
|
binding: 10,
|
||||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Texture {
|
ty: wgpu::BindingType::Texture {
|
||||||
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
view_dimension: wgpu::TextureViewDimension::Cube,
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
multisampled: false,
|
multisampled: false,
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
@ -371,46 +374,6 @@ impl GlobalsLayouts {
|
|||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 11,
|
binding: 11,
|
||||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
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 {
|
ty: wgpu::BindingType::Sampler {
|
||||||
filtering: true,
|
filtering: true,
|
||||||
comparison: false,
|
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(
|
pub fn bind(
|
||||||
@ -509,36 +522,45 @@ impl GlobalsLayouts {
|
|||||||
binding: 9,
|
binding: 9,
|
||||||
resource: global_model.shadow_mats.buf().as_entire_binding(),
|
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)
|
// lod map (t_map)
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 14,
|
binding: 10,
|
||||||
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
|
resource: wgpu::BindingResource::TextureView(&lod_data.map.view),
|
||||||
},
|
},
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 15,
|
binding: 11,
|
||||||
resource: wgpu::BindingResource::Sampler(&lod_data.map.sampler),
|
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>(
|
pub fn bind_col_light<Locals>(
|
||||||
|
@ -186,7 +186,7 @@ impl ParticlePipeline {
|
|||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Particle pipeline layout"),
|
label: Some("Particle pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[&global_layout.globals],
|
bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
|
||||||
});
|
});
|
||||||
|
|
||||||
let samples = match aa_mode {
|
let samples = match aa_mode {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::super::{
|
use super::super::{
|
||||||
AaMode, ColLightInfo, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout, TerrainVertex,
|
AaMode, Bound, ColLightInfo, Consts, FigureLayout, GlobalsLayouts, Renderer, TerrainLayout,
|
||||||
Texture,
|
TerrainVertex, Texture,
|
||||||
};
|
};
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -21,9 +21,18 @@ impl Locals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
|
pub fn default() -> Self { Self::new(Mat4::identity(), Mat4::identity()) }
|
||||||
|
}
|
||||||
|
|
||||||
fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
pub type BoundLocals = Bound<Consts<Locals>>;
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
|
pub struct ShadowLayout {
|
||||||
|
pub locals: wgpu::BindGroupLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShadowLayout {
|
||||||
|
pub fn new(device: &wgpu::Device) -> Self {
|
||||||
|
Self {
|
||||||
|
locals: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
entries: &[wgpu::BindGroupLayoutEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
@ -35,20 +44,35 @@ impl Locals {
|
|||||||
},
|
},
|
||||||
count: 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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ShadowLayout {
|
#[repr(C)]
|
||||||
pub locals: wgpu::BindGroupLayout,
|
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||||
}
|
pub struct PointLightMatrix([[f32; 4]; 4]);
|
||||||
|
|
||||||
impl ShadowLayout {
|
impl PointLightMatrix {
|
||||||
pub fn new(device: &wgpu::Device) -> Self {
|
pub fn new(shadow_mat: Mat4<f32>) -> Self { Self(shadow_mat.into_col_arrays()) }
|
||||||
Self {
|
|
||||||
locals: Locals::layout(device),
|
pub fn default() -> Self { Self::new(Mat4::identity()) }
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_col_lights(
|
pub fn create_col_lights(
|
||||||
@ -109,23 +133,17 @@ impl ShadowFigurePipeline {
|
|||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
vs_module: &wgpu::ShaderModule,
|
vs_module: &wgpu::ShaderModule,
|
||||||
fs_module: &wgpu::ShaderModule,
|
fs_module: &wgpu::ShaderModule,
|
||||||
sc_desc: &wgpu::SwapChainDescriptor,
|
|
||||||
global_layout: &GlobalsLayouts,
|
global_layout: &GlobalsLayouts,
|
||||||
figure_layout: &FigureLayout,
|
figure_layout: &FigureLayout,
|
||||||
layout: &ShadowLayout,
|
|
||||||
aa_mode: AaMode,
|
aa_mode: AaMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
common::span!(_guard, "new");
|
common::span!(_guard, "new");
|
||||||
tracing::error!("test");
|
|
||||||
let render_pipeline_layout =
|
let render_pipeline_layout =
|
||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Shadow figure pipeline layout"),
|
label: Some("Shadow figure pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[&global_layout.globals, &figure_layout.locals],
|
||||||
&global_layout.globals,
|
|
||||||
&figure_layout.locals,
|
|
||||||
&layout.locals,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let samples = match aa_mode {
|
let samples = match aa_mode {
|
||||||
@ -151,7 +169,7 @@ impl ShadowFigurePipeline {
|
|||||||
front_face: wgpu::FrontFace::Ccw,
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
cull_mode: wgpu::CullMode::Back,
|
cull_mode: wgpu::CullMode::Back,
|
||||||
polygon_mode: wgpu::PolygonMode::Fill,
|
polygon_mode: wgpu::PolygonMode::Fill,
|
||||||
clamp_depth: false,
|
clamp_depth: true,
|
||||||
depth_bias: 0,
|
depth_bias: 0,
|
||||||
depth_bias_slope_scale: 0.0,
|
depth_bias_slope_scale: 0.0,
|
||||||
depth_bias_clamp: 0.0,
|
depth_bias_clamp: 0.0,
|
||||||
@ -193,21 +211,15 @@ impl ShadowPipeline {
|
|||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
vs_module: &wgpu::ShaderModule,
|
vs_module: &wgpu::ShaderModule,
|
||||||
fs_module: &wgpu::ShaderModule,
|
fs_module: &wgpu::ShaderModule,
|
||||||
sc_desc: &wgpu::SwapChainDescriptor,
|
|
||||||
global_layout: &GlobalsLayouts,
|
global_layout: &GlobalsLayouts,
|
||||||
terrain_layout: &TerrainLayout,
|
terrain_layout: &TerrainLayout,
|
||||||
layout: &ShadowLayout,
|
|
||||||
aa_mode: AaMode,
|
aa_mode: AaMode,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let render_pipeline_layout =
|
let render_pipeline_layout =
|
||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Shadow pipeline layout"),
|
label: Some("Shadow pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[&global_layout.globals, &terrain_layout.locals],
|
||||||
&global_layout.globals,
|
|
||||||
&terrain_layout.locals,
|
|
||||||
&layout.locals,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let samples = match aa_mode {
|
let samples = match aa_mode {
|
||||||
@ -233,7 +245,85 @@ impl ShadowPipeline {
|
|||||||
front_face: wgpu::FrontFace::Ccw,
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
cull_mode: wgpu::CullMode::Back,
|
cull_mode: wgpu::CullMode::Back,
|
||||||
polygon_mode: wgpu::PolygonMode::Fill,
|
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: 0,
|
||||||
depth_bias_slope_scale: 0.0,
|
depth_bias_slope_scale: 0.0,
|
||||||
depth_bias_clamp: 0.0,
|
depth_bias_clamp: 0.0,
|
||||||
|
@ -44,7 +44,7 @@ impl SkyboxPipeline {
|
|||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("Skybox pipeline layout"),
|
label: Some("Skybox pipeline layout"),
|
||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[&layouts.globals],
|
bind_group_layouts: &[&layouts.globals, &layouts.shadow_textures],
|
||||||
});
|
});
|
||||||
|
|
||||||
let samples = match aa_mode {
|
let samples = match aa_mode {
|
||||||
|
@ -219,6 +219,7 @@ impl SpritePipeline {
|
|||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
&global_layout.globals,
|
&global_layout.globals,
|
||||||
|
&global_layout.shadow_textures,
|
||||||
&terrain_layout.locals,
|
&terrain_layout.locals,
|
||||||
&layout.locals,
|
&layout.locals,
|
||||||
&global_layout.col_light,
|
&global_layout.col_light,
|
||||||
|
@ -219,6 +219,7 @@ impl TerrainPipeline {
|
|||||||
push_constant_ranges: &[],
|
push_constant_ranges: &[],
|
||||||
bind_group_layouts: &[
|
bind_group_layouts: &[
|
||||||
&global_layout.globals,
|
&global_layout.globals,
|
||||||
|
&global_layout.shadow_textures,
|
||||||
&layout.locals,
|
&layout.locals,
|
||||||
&global_layout.col_light,
|
&global_layout.col_light,
|
||||||
],
|
],
|
||||||
|
@ -124,7 +124,7 @@ pub struct ShadowMapRenderer {
|
|||||||
|
|
||||||
point_depth: Texture,
|
point_depth: Texture,
|
||||||
|
|
||||||
point_pipeline: shadow::ShadowPipeline,
|
point_pipeline: shadow::PointShadowPipeline,
|
||||||
terrain_directed_pipeline: shadow::ShadowPipeline,
|
terrain_directed_pipeline: shadow::ShadowPipeline,
|
||||||
figure_directed_pipeline: shadow::ShadowFigurePipeline,
|
figure_directed_pipeline: shadow::ShadowFigurePipeline,
|
||||||
layout: shadow::ShadowLayout,
|
layout: shadow::ShadowLayout,
|
||||||
@ -292,12 +292,18 @@ impl Renderer {
|
|||||||
|
|
||||||
use wgpu::{Features, Limits};
|
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(
|
let (device, queue) = futures::executor::block_on(adapter.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
// TODO
|
// TODO
|
||||||
label: None,
|
label: None,
|
||||||
features: Features::DEPTH_CLAMPING | Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
features: Features::DEPTH_CLAMPING
|
||||||
limits: Limits::default(),
|
| Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||||
|
| Features::PUSH_CONSTANTS,
|
||||||
|
limits,
|
||||||
shader_validation: true,
|
shader_validation: true,
|
||||||
},
|
},
|
||||||
None,
|
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
|
/// Start recording the frame
|
||||||
/// When the returned `Drawer` is dropped the recorded draw calls will be
|
/// When the returned `Drawer` is dropped the recorded draw calls will be
|
||||||
/// submitted to the queue
|
/// submitted to the queue
|
||||||
@ -2023,7 +2002,7 @@ fn create_pipelines(
|
|||||||
clouds::CloudsPipeline,
|
clouds::CloudsPipeline,
|
||||||
postprocess::PostProcessPipeline,
|
postprocess::PostProcessPipeline,
|
||||||
//figure::FigurePipeline,
|
//figure::FigurePipeline,
|
||||||
Option<shadow::ShadowPipeline>,
|
Option<shadow::PointShadowPipeline>,
|
||||||
Option<shadow::ShadowPipeline>,
|
Option<shadow::ShadowPipeline>,
|
||||||
Option<shadow::ShadowFigurePipeline>,
|
Option<shadow::ShadowFigurePipeline>,
|
||||||
),
|
),
|
||||||
@ -2278,77 +2257,35 @@ fn create_pipelines(
|
|||||||
// gfx::state::CullFace::Back,
|
// gfx::state::CullFace::Back,
|
||||||
// )?;
|
// )?;
|
||||||
|
|
||||||
// Sharp can fix it later ;)
|
// Construct a pipeline for rendering point light terrain shadow maps.
|
||||||
//
|
let point_shadow_pipeline = shadow::PointShadowPipeline::new(
|
||||||
// // Construct a pipeline for rendering point light terrain shadow maps.
|
device,
|
||||||
// let point_shadow_pipeline = match create_shadow_pipeline(
|
&create_shader("point-light-shadows-vert", ShaderKind::Vertex)?,
|
||||||
// factory,
|
&create_shader("light-shadows-frag", ShaderKind::Fragment)?,
|
||||||
// shadow::pipe::new(),
|
&layouts.global,
|
||||||
// &terrain_point_shadow_vert,
|
&layouts.terrain,
|
||||||
// Some(
|
mode.aa,
|
||||||
// &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 directional light terrain shadow maps.
|
// Construct a pipeline for rendering directional light terrain shadow maps.
|
||||||
// let terrain_directed_shadow_pipeline = match create_shadow_pipeline(
|
let terrain_directed_shadow_pipeline = shadow::ShadowPipeline::new(
|
||||||
// factory,
|
device,
|
||||||
// shadow::pipe::new(),
|
&terrain_directed_shadow_vert_mod,
|
||||||
// &terrain_directed_shadow_vert,
|
&directed_shadow_frag_mod,
|
||||||
// None,
|
&layouts.global,
|
||||||
// &directed_shadow_frag,
|
&layouts.terrain,
|
||||||
// &include_ctx,
|
mode.aa,
|
||||||
// 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 figure shadow maps.
|
// Construct a pipeline for rendering directional light figure shadow maps.
|
||||||
// let figure_directed_shadow_pipeline = match create_shadow_pipeline(
|
let figure_directed_shadow_pipeline = shadow::ShadowFigurePipeline::new(
|
||||||
// factory,
|
device,
|
||||||
// shadow::figure_pipe::new(),
|
&figure_directed_shadow_vert_mod,
|
||||||
// &figure_directed_shadow_vert,
|
&directed_shadow_frag_mod,
|
||||||
// None,
|
&layouts.global,
|
||||||
// &directed_shadow_frag,
|
&layouts.figure,
|
||||||
// &include_ctx,
|
mode.aa,
|
||||||
// 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
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
skybox_pipeline,
|
skybox_pipeline,
|
||||||
@ -2362,9 +2299,9 @@ fn create_pipelines(
|
|||||||
clouds_pipeline,
|
clouds_pipeline,
|
||||||
postprocess_pipeline,
|
postprocess_pipeline,
|
||||||
// player_shadow_pipeline,
|
// player_shadow_pipeline,
|
||||||
None,
|
Some(point_shadow_pipeline),
|
||||||
None,
|
Some(terrain_directed_shadow_pipeline),
|
||||||
None,
|
Some(figure_directed_shadow_pipeline),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{
|
use super::{
|
||||||
super::{
|
super::{
|
||||||
pipelines::{
|
pipelines::{
|
||||||
figure, fluid, lod_terrain, sprite, terrain, ui, ColLights, GlobalModel,
|
figure, fluid, lod_terrain, shadow, sprite, terrain, ui, ColLights, GlobalModel,
|
||||||
GlobalsBindGroup,
|
GlobalsBindGroup,
|
||||||
},
|
},
|
||||||
texture::Texture,
|
texture::Texture,
|
||||||
@ -59,6 +59,11 @@ impl Renderer {
|
|||||||
self.layouts.terrain.bind_locals(&self.device, locals)
|
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 {
|
pub fn create_sprite_bound_locals(&mut self, locals: &[sprite::Locals]) -> sprite::BoundLocals {
|
||||||
let locals = self.create_consts(locals);
|
let locals = self.create_consts(locals);
|
||||||
self.layouts.sprite.bind_locals(&self.device, locals)
|
self.layouts.sprite.bind_locals(&self.device, locals)
|
||||||
|
@ -5,18 +5,18 @@ use super::{
|
|||||||
instances::Instances,
|
instances::Instances,
|
||||||
model::{DynamicModel, Model, SubModel},
|
model::{DynamicModel, Model, SubModel},
|
||||||
pipelines::{
|
pipelines::{
|
||||||
clouds, figure, fluid, lod_terrain, particle, postprocess, skybox, sprite, terrain, ui,
|
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite,
|
||||||
ColLights, GlobalsBindGroup, Light, Shadow,
|
terrain, ui, ColLights, GlobalsBindGroup, Light, Shadow,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Renderer,
|
Renderer, ShadowMapRenderer,
|
||||||
};
|
};
|
||||||
use std::ops::Range;
|
use std::{ops::Range};
|
||||||
use vek::Aabr;
|
use vek::Aabr;
|
||||||
|
|
||||||
pub struct Drawer<'a> {
|
pub struct Drawer<'a> {
|
||||||
encoder: Option<wgpu::CommandEncoder>,
|
encoder: Option<wgpu::CommandEncoder>,
|
||||||
renderer: &'a mut Renderer,
|
pub renderer: &'a mut Renderer,
|
||||||
tex: wgpu::SwapChainTexture,
|
tex: wgpu::SwapChainTexture,
|
||||||
globals: &'a GlobalsBindGroup,
|
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(0, &self.globals.bind_group, &[]);
|
||||||
|
render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]);
|
||||||
|
|
||||||
FirstPassDrawer {
|
FirstPassDrawer {
|
||||||
render_pass,
|
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 {
|
pub fn second_pass(&mut self) -> SecondPassDrawer {
|
||||||
let mut render_pass =
|
let mut render_pass =
|
||||||
self.encoder
|
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(0, &self.globals.bind_group, &[]);
|
||||||
|
render_pass.set_bind_group(1, &self.globals.shadow_textures, &[]);
|
||||||
|
|
||||||
SecondPassDrawer {
|
SecondPassDrawer {
|
||||||
render_pass,
|
render_pass,
|
||||||
@ -119,6 +153,68 @@ impl<'a> Drawer<'a> {
|
|||||||
renderer: &self.renderer,
|
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> {
|
impl<'a> Drop for Drawer<'a> {
|
||||||
@ -159,9 +255,9 @@ impl<'a> FirstPassDrawer<'a> {
|
|||||||
) {
|
) {
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
|
.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
|
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.set_vertex_buffer(0, model.buf());
|
||||||
self.render_pass.draw(0..model.len(), 0..1);
|
self.render_pass.draw(0..model.len(), 0..1);
|
||||||
}
|
}
|
||||||
@ -174,9 +270,9 @@ impl<'a> FirstPassDrawer<'a> {
|
|||||||
) {
|
) {
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
|
.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
|
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.set_vertex_buffer(0, model.buf().slice(..));
|
||||||
self.render_pass.draw(0..model.len() as u32, 0..1)
|
self.render_pass.draw(0..model.len() as u32, 0..1)
|
||||||
}
|
}
|
||||||
@ -201,10 +297,10 @@ impl<'a> FirstPassDrawer<'a> {
|
|||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
|
.set_pipeline(&self.renderer.sprite_pipeline.pipeline);
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_bind_group(1, &terrain_locals.bind_group, &[]);
|
.set_bind_group(2, &terrain_locals.bind_group, &[]);
|
||||||
self.render_pass.set_bind_group(2, &locals.bind_group, &[]);
|
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
|
||||||
self.render_pass
|
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(0, model.buf().slice(..));
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_vertex_buffer(1, instances.buf().slice(..));
|
.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> {
|
pub fn draw_fluid<'b: 'a>(&mut self, waves: &'b fluid::BindGroup) -> FluidDrawer<'_, 'a> {
|
||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.fluid_pipeline.pipeline);
|
.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 {
|
FluidDrawer {
|
||||||
render_pass: &mut self.render_pass,
|
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> {
|
pub struct FluidDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||||
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
|
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,
|
locals: &'data terrain::BoundLocals,
|
||||||
) {
|
) {
|
||||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
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);
|
self.render_pass.draw(0..model.len() as u32, 0..1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +398,7 @@ impl<'a> SecondPassDrawer<'a> {
|
|||||||
self.render_pass
|
self.render_pass
|
||||||
.set_pipeline(&self.renderer.clouds_pipeline.pipeline);
|
.set_pipeline(&self.renderer.clouds_pipeline.pipeline);
|
||||||
self.render_pass
|
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);
|
self.render_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
render::{
|
render::{
|
||||||
pipelines::{self, ColLights},
|
pipelines::{self, ColLights},
|
||||||
ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel,
|
ColLightInfo, FigureBoneData, FigureLocals, FigureModel, FirstPassDrawer, GlobalModel,
|
||||||
LodData, Mesh, RenderError, Renderer, SubModel, TerrainVertex,
|
LodData, Mesh, RenderError, Renderer, ShadowDrawer, SubModel, TerrainVertex,
|
||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{Camera, CameraMode, Dependents},
|
camera::{Camera, CameraMode, Dependents},
|
||||||
@ -4706,19 +4706,16 @@ impl FigureMgr {
|
|||||||
visible_aabb
|
visible_aabb
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_shadows(
|
pub fn render_shadows<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
renderer: &mut Renderer,
|
drawer: &mut ShadowDrawer<'a>,
|
||||||
state: &State,
|
state: &State,
|
||||||
tick: u64,
|
tick: u64,
|
||||||
global: &GlobalModel,
|
|
||||||
(is_daylight, _light_data): super::LightData,
|
|
||||||
(camera, figure_lod_render_distance): CameraData,
|
(camera, figure_lod_render_distance): CameraData,
|
||||||
) {
|
) {
|
||||||
span!(_guard, "render_shadows", "FigureManager::render_shadows");
|
span!(_guard, "render_shadows", "FigureManager::render_shadows");
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
|
|
||||||
if is_daylight && renderer.render_mode().shadow.is_map() {
|
|
||||||
(
|
(
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
@ -4744,18 +4741,10 @@ impl FigureMgr {
|
|||||||
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||||
|state| state.can_shadow_sun(),
|
|state| state.can_shadow_sun(),
|
||||||
) {
|
) {
|
||||||
// TODO
|
drawer.draw_figure_shadow(model, bound);
|
||||||
//renderer.render_figure_shadow_directed(
|
|
||||||
// model,
|
|
||||||
// global,
|
|
||||||
// locals,
|
|
||||||
// bone_consts,
|
|
||||||
// &global.shadow_mats,
|
|
||||||
//);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||||
pub fn render<'a>(
|
pub fn render<'a>(
|
||||||
|
@ -16,9 +16,9 @@ pub use self::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
|
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
|
||||||
render::{
|
render::{
|
||||||
create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals,
|
create_skybox_mesh, CloudsLocals, Consts, Drawer, FirstPassDrawer, GlobalModel, Globals,
|
||||||
GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals,
|
GlobalsBindGroup, Light, Model, PointLightMatrix, PostProcessLocals, Renderer, Shadow,
|
||||||
SkyboxVertex,
|
ShadowDrawer, ShadowLocals, SkyboxVertex,
|
||||||
},
|
},
|
||||||
settings::Settings,
|
settings::Settings,
|
||||||
window::{AnalogGameInput, Event},
|
window::{AnalogGameInput, Event},
|
||||||
@ -268,8 +268,8 @@ impl Scene {
|
|||||||
globals: renderer.create_consts(&[Globals::default()]),
|
globals: renderer.create_consts(&[Globals::default()]),
|
||||||
lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]),
|
lights: renderer.create_consts(&[Light::default(); MAX_LIGHT_COUNT]),
|
||||||
shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]),
|
shadows: renderer.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]),
|
||||||
shadow_mats: renderer
|
shadow_mats: renderer.create_shadow_bound_locals(&[ShadowLocals::default()]),
|
||||||
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 6]),
|
point_light_matrices: Box::new([PointLightMatrix::default(); MAX_LIGHT_COUNT * 6 + 6]),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lod = Lod::new(renderer, client, settings);
|
let lod = Lod::new(renderer, client, settings);
|
||||||
@ -707,11 +707,200 @@ impl Scene {
|
|||||||
let new_dir = math::Vec3::from(view_dir);
|
let new_dir = math::Vec3::from(view_dir);
|
||||||
let new_dir = new_dir.normalized();
|
let new_dir = new_dir.normalized();
|
||||||
let up: math::Vec3<f32> = math::Vec3::unit_y();
|
let up: math::Vec3<f32> = math::Vec3::unit_y();
|
||||||
directed_shadow_mats.push(math::Mat4::look_at_rh(
|
let light_view_mat = math::Mat4::look_at_rh(look_at, look_at + directed_light_dir, up);
|
||||||
look_at,
|
{
|
||||||
look_at + directed_light_dir,
|
let v_p_orig =
|
||||||
up,
|
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.
|
// This leaves us with five dummy slots, which we push as defaults.
|
||||||
directed_shadow_mats
|
directed_shadow_mats
|
||||||
.extend_from_slice(&[math::Mat4::default(); 6 - NUM_DIRECTED_LIGHTS] as _);
|
.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(
|
shadow_mats.extend(directed_shadow_mats.iter().enumerate().map(
|
||||||
move |(idx, &light_view_mat)| {
|
move |(idx, &light_view_mat)| {
|
||||||
if idx >= NUM_DIRECTED_LIGHTS {
|
if idx >= NUM_DIRECTED_LIGHTS {
|
||||||
return ShadowLocals::new(Mat4::identity(), Mat4::identity());
|
return PointLightMatrix::new(Mat4::identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
let v_p_orig =
|
let v_p_orig =
|
||||||
@ -911,17 +1100,13 @@ impl Scene {
|
|||||||
let shadow_all_mat: Mat4<f32> =
|
let shadow_all_mat: Mat4<f32> =
|
||||||
Mat4::from_col_arrays(shadow_all_mat.into_col_arrays());
|
Mat4::from_col_arrays(shadow_all_mat.into_col_arrays());
|
||||||
|
|
||||||
let directed_texture_proj_mat = texture_mat * directed_proj_mat;
|
PointLightMatrix::new(directed_proj_mat * shadow_all_mat)
|
||||||
ShadowLocals::new(
|
|
||||||
directed_proj_mat * shadow_all_mat,
|
|
||||||
directed_texture_proj_mat * shadow_all_mat,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
// Now, we tackle point lights.
|
// Now, we tackle point lights.
|
||||||
// First, create a perspective projection matrix at 90 degrees (to cover a whole
|
// First, create a perspective projection matrix at 90 degrees (to cover a whole
|
||||||
// face of the cube map we're using).
|
// 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(),
|
90.0f32.to_radians(),
|
||||||
point_shadow_aspect,
|
point_shadow_aspect,
|
||||||
SHADOW_NEAR,
|
SHADOW_NEAR,
|
||||||
@ -947,14 +1132,13 @@ impl Scene {
|
|||||||
orientations.iter().map(move |&(forward, up)| {
|
orientations.iter().map(move |&(forward, up)| {
|
||||||
// NOTE: We don't currently try to linearize point lights or need a separate
|
// NOTE: We don't currently try to linearize point lights or need a separate
|
||||||
// transform for them.
|
// transform for them.
|
||||||
ShadowLocals::new(
|
PointLightMatrix::new(shadow_proj * Mat4::look_at_rh(eye, eye + forward, up))
|
||||||
shadow_proj * Mat4::look_at_rh(eye, eye + forward, up),
|
|
||||||
Mat4::identity(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
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.
|
// Remove unused figures.
|
||||||
@ -976,7 +1160,87 @@ impl Scene {
|
|||||||
|
|
||||||
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
|
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>(
|
pub fn render<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
drawer: &mut FirstPassDrawer<'a>,
|
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 cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||||
|
|
||||||
let global = &self.data;
|
let global = &self.data;
|
||||||
let light_data = (is_daylight, &*self.light_data);
|
|
||||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
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();
|
let lod = self.lod.get_data();
|
||||||
|
|
||||||
self.figure_mgr
|
self.figure_mgr
|
||||||
|
@ -2,8 +2,8 @@ use crate::{
|
|||||||
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
|
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
|
||||||
render::{
|
render::{
|
||||||
create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals,
|
create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals,
|
||||||
GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals,
|
GlobalsBindGroup, Light, LodData, Mesh, Model, PointLightMatrix, Renderer, Shadow,
|
||||||
SkyboxVertex, TerrainVertex,
|
ShadowLocals, SkyboxVertex, TerrainVertex,
|
||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{self, Camera, CameraMode},
|
camera::{self, Camera, CameraMode},
|
||||||
@ -109,7 +109,8 @@ impl Scene {
|
|||||||
globals: renderer.create_consts(&[Globals::default()]),
|
globals: renderer.create_consts(&[Globals::default()]),
|
||||||
lights: renderer.create_consts(&[Light::default(); 20]),
|
lights: renderer.create_consts(&[Light::default(); 20]),
|
||||||
shadows: renderer.create_consts(&[Shadow::default(); 24]),
|
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);
|
let lod = LodData::dummy(renderer);
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
render::{
|
render::{
|
||||||
pipelines::{self, ColLights},
|
pipelines::{self, ColLights},
|
||||||
ColLightInfo, Consts, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel, Instances,
|
ColLightInfo, Consts, Drawer, FirstPassDrawer, FluidVertex, FluidWaves, GlobalModel,
|
||||||
LodData, Mesh, Model, RenderError, Renderer, SpriteInstance, SpriteLocals, SpriteVertex,
|
Instances, LodData, Mesh, Model, RenderError, Renderer, ShadowDrawer, SpriteInstance,
|
||||||
TerrainLocals, TerrainVertex, Texture,
|
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 shadow_chunk_count(&self) -> usize { self.shadow_chunks.len() }
|
||||||
|
|
||||||
pub fn render_shadows(
|
pub fn render_shadows<'a>(
|
||||||
&self,
|
&'a self,
|
||||||
renderer: &mut Renderer,
|
drawer: &mut ShadowDrawer<'a>,
|
||||||
global: &GlobalModel,
|
global: &GlobalModel,
|
||||||
(is_daylight, light_data): super::LightData,
|
(is_daylight, light_data): super::LightData,
|
||||||
focus_pos: Vec3<f32>,
|
focus_pos: Vec3<f32>,
|
||||||
) {
|
) {
|
||||||
span!(_guard, "render_shadows", "Terrain::render_shadows");
|
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| {
|
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||||
(e as i32).div_euclid(sz as i32)
|
(e as i32).div_euclid(sz as i32)
|
||||||
});
|
});
|
||||||
@ -1430,16 +1426,27 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
.clone()
|
.clone()
|
||||||
.filter(|chunk| chunk.can_shadow_sun())
|
.filter(|chunk| chunk.can_shadow_sun())
|
||||||
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
||||||
.for_each(|chunk| {
|
.for_each(|chunk| drawer.draw_terrain_shadow(&chunk.opaque_model, &chunk.locals));
|
||||||
// Directed light shadows.
|
|
||||||
/*renderer.render_terrain_shadow_directed(
|
|
||||||
&chunk.opaque_model,
|
|
||||||
global,
|
|
||||||
&chunk.locals,
|
|
||||||
&global.shadow_mats,
|
|
||||||
);*/
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Point shadows
|
||||||
//
|
//
|
||||||
@ -1448,12 +1455,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
light_data.iter().take(1).for_each(|_light| {
|
light_data.iter().take(1).for_each(|_light| {
|
||||||
chunk_iter.clone().for_each(|chunk| {
|
chunk_iter.clone().for_each(|chunk| {
|
||||||
if chunk.can_shadow_point {
|
if chunk.can_shadow_point {
|
||||||
/*renderer.render_shadow_point(
|
drawer.draw_point_shadow(
|
||||||
&chunk.opaque_model,
|
&chunk.opaque_model,
|
||||||
global,
|
|
||||||
&chunk.locals,
|
&chunk.locals,
|
||||||
&global.shadow_mats,
|
&global.point_light_matrices,
|
||||||
);*/
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1418,6 +1418,33 @@ impl PlayState for SessionState {
|
|||||||
particles_enabled: settings.graphics.particles_enabled,
|
particles_enabled: settings.graphics.particles_enabled,
|
||||||
is_aiming: self.is_aiming,
|
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(
|
self.scene.render(
|
||||||
&mut drawer.first_pass(),
|
&mut drawer.first_pass(),
|
||||||
client.state(),
|
client.state(),
|
||||||
|
Loading…
Reference in New Issue
Block a user