Shadow maps work for lantern.

This commit is contained in:
Joshua Yanovski 2020-05-17 05:59:00 +02:00
parent 243d0837b8
commit a4d87e1875
16 changed files with 319 additions and 87 deletions

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@ uniform u_globals {
vec4 tick;
vec4 screen_res;
uvec4 light_shadow_count;
vec4 shadow_proj_factors;
uvec4 medium;
ivec4 select_pos;
vec4 gamma;

View File

@ -3,6 +3,7 @@
struct Light {
vec4 light_pos;
vec4 light_col;
// mat4 light_proj;
};
layout (std140)
@ -26,27 +27,86 @@ float attenuation_strength(vec3 rpos) {
}
#ifdef HAS_SHADOW_MAPS
uniform samplerCubeArrayShadow t_shadow_maps;
// uniform samplerCubeArrayShadow t_shadow_maps;
// uniform samplerCubeArray t_shadow_maps;
uniform samplerCubeShadow t_shadow_maps;
// uniform samplerCube t_shadow_maps;
float ShadowCalculation(uint lightIndex, vec3 fragToLight, float currentDepth)
float VectorToDepth (vec3 Vec)
{
// return 1.0;
vec3 AbsVec = abs(Vec);
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
// Replace f and n with the far and near plane values you used when
// you drew your cube map.
// const float f = 2048.0;
// const float n = 1.0;
// float NormZComp = (screen_res.w+screen_res.z) / (screen_res.w-screen_res.z) - (2*screen_res.w*screen_res.z)/(screen_res.w-screen_res.z)/LocalZcomp;
float NormZComp = shadow_proj_factors.x - shadow_proj_factors.y / LocalZcomp;
return (NormZComp + 1.0) * 0.5;
}
const vec3 sampleOffsetDirections[20] = vec3[]
(
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
// vec3(0, 0, 0)
);
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{
// float shadow = 0.0;
float bias = 0.0;//-0.1;//0.0;//0.1
// int samples = 20;
// float lightDistance = length(fragToLight);
// float viewDistance = length(cam_pos.xyz - fragPos);
// // float diskRadius = 0.00001;
// // float diskRadius = 1.0;
// float diskRadius = (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 2.0;
// // float diskRadius = lightDistance;
// for(int i = 0; i < samples; ++i)
// {
// float currentDepth = VectorToDepth(fragToLight + sampleOffsetDirections[i] * diskRadius) + bias;
// // float closestDepth = texture(depthMap, fragToLight).r;
// // closestDepth *= far_plane; // Undo mapping [0;1]
// /* if(currentDepth - bias > closestDepth)
// shadow += 1.0;*/
// float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));
// shadow += visibility;
// }
// shadow /= float(samples);
// // shadow = shadow * shadow * (3.0 - 2.0 * shadow);
// use the light to fragment vector to sample from the depth map
float bias = 0.0;// 0.05;
// float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex)/*, 0.0*//*, 0.0*//*, bias*/).r;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// // it is currently in linear range between [0,1]. Re-transform back to original value
// closestDepth *= screen_res.w; // far plane
// // now test for shadows
// // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
// float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
// float closestDepth = texture(t_shadow_maps, /*vec4*/vec3(fragToLight/*, (lightIndex + 1)*//* * 6*/)/*, 0.0*//*, 0.0*//*, bias*/).r;
// // // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// // // it is currently in linear range between [0,1]. Re-transform back to original value
// closestDepth = (closestDepth + 0.0) * screen_res.w; // far plane
// // // now test for shadows
// // // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// float shadow = currentDepth - bias < closestDepth ? 1.0 : 0.0;
// float visibility = textureProj(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
float visibility = texture(t_shadow_maps, vec4(fragToLight, lightIndex), (currentDepth/* + screen_res.z*/) / screen_res.w);// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
// float visibility = texture(t_shadow_maps, vec4(fragToLight, lightIndex + 1), -(currentDepth/* + screen_res.z*/) / screen_res.w);// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
// currentDepth += bias;
// currentDepth = -1000.0 / (currentDepth + 10000.0);
// currentDepth /= screen_res.w;
float currentDepth = VectorToDepth(fragToLight) + bias;
if (lightIndex != 0u) {
return 1.0;
};
float visibility = texture(t_shadow_maps, vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/);
return visibility;
// return shadow;
}
#else
float ShadowCalculation(uint lightIndex, vec3 fragToLight, float currentDepth)
float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{
return 1.0;
}
@ -164,7 +224,7 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
// Multiply the vec3 only once
const float PI = 3.1415926535897932384626433832795;
const float PI_2 = 2 * PI;
float square_factor = /*2.0 * PI_2 * */2.0 * L.light_col.a;
float square_factor = /*2.0 * PI_2 * *//*2.0 * */L.light_col.a;
vec3 color = /*srgb_to_linear*/L.light_col.rgb;
// // Only access the array once
@ -199,9 +259,11 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
is_direct = true;
#endif
vec3 direct_light = PI * color * strength * square_factor * light_reflection_factor(/*direct_norm_dir*/wnorm, /*cam_to_frag*/view_dir, direct_light_dir, k_d, k_s, alpha, voxel_lighting);
float computed_shadow = ShadowCalculation(i, -difference, light_distance);
directed_light += /*is_direct ? */max(computed_shadow, /*LIGHT_AMBIENCE*/0.0) * direct_light * square_factor/* : vec3(0.0)*/;
ambient_light += is_direct ? vec3(0.0) : vec3(0.0); // direct_light * square_factor * LIGHT_AMBIENCE;
float computed_shadow = ShadowCalculation(i, -difference, wpos/*, light_distance*/);
// directed_light += /*is_direct ? */max(computed_shadow, /*LIGHT_AMBIENCE*/0.0) * direct_light * square_factor/* : vec3(0.0)*/;
directed_light += is_direct ? mix(/*LIGHT_AMBIENCE*/0.0, 1.0, computed_shadow) * direct_light * square_factor : vec3(0.0);
// ambient_light += is_direct ? vec3(0.0) : vec3(0.0); // direct_light * square_factor * LIGHT_AMBIENCE;
// ambient_light += direct_light * (1.0 - square_factor * LIGHT_AMBIENCE);
vec3 cam_light_diff = light_pos - focus_pos.xyz;
float cam_distance_2 = dot(cam_light_diff, cam_light_diff);// + 0.0001;

View File

@ -513,8 +513,8 @@ vec3 illuminate(float max_light, vec3 view_dir, /*vec3 max_light, */vec3 emitted
// vec3 c = sqrt(col_adjusted) * T;
// vec3 c = /*col_adjusted * */col_adjusted * T;
return color;
// return c;
// return color;
return c;
// float sum_col = color.r + color.g + color.b;
// return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma)));
}

View File

@ -3,6 +3,7 @@
// However, in the future we might apply some depth transforms here.
#version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
@ -25,17 +26,23 @@
// Currently, we only need lights for the light position
#include <light.glsl>
in vec4 FragPos; // FragPos from GS (output per emitvertex)
flat in int FragLayer;
// in vec3 FragPos; // FragPos from GS (output per emitvertex)
// flat in int FragLayer;
void main()
{
// Only need to do anything with point lights, since sun and moon should already have nonlinear
// distance.
/*if (FragLayer > 0) */{
// get distance between fragment and light source
float lightDistance = length(FragPos.xyz - lights[FragLayer & 31].light_pos.xyz);
// float lightDistance = length(FragPos - lights[((FragLayer - 1) & 31)].light_pos.xyz);
// map to [0;1] range by dividing by far_plane
lightDistance = lightDistance / /*FragPos.w;*/screen_res.w;
// lightDistance = lightDistance / /*FragPos.w;*/screen_res.w;
// write this as modified depth
gl_FragDepth = lightDistance;
// lightDistance = -1000.0 / (lightDistance + 10000.0);
// lightDistance /= screen_res.w;
// gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance
}
}

View File

@ -2,10 +2,30 @@
// NOTE: We only technically need this for cube map arrays and geometry shader
// instancing.
#version 400 core
#version 330 core
// #extension ARB_texture_storage : enable
// Currently, we only need globals for the max light count (light_shadow_count.x).
#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 the max light count (light_shadow_count.x)
// and the far plane (scene_res.z).
#include <globals.glsl>
// Currently, we only need lights for the light position
#include <light.glsl>
// Since our output primitive is a triangle strip, we have to render three vertices
// each.
@ -140,14 +160,14 @@
// Since wgpu doesn't support geometry shaders anyway, it seems likely that we'll have
// to do the multiple draw calls, anyway... I don't think gl_Layer can be set from
// outside a geometry shader. But in wgpu, such a thing is much cheaper, anyway.
#define MAX_POINT_LIGHTS 32
#define MAX_POINT_LIGHTS 31
// We use geometry shader instancing to construct each face separately.
#define MAX_LAYER_VERTICES_PER_FACE (MAX_POINT_LIGHTS * VERTICES_PER_FACE)
#define MAX_LAYER_FACES (MAX_POINT_LIGHTS * FACES_PER_POINT_LIGHT)
layout (triangles, invocations = 6) in;
layout (triangles/*, invocations = 6*/) in;
layout (triangle_strip, max_vertices = /*MAX_LAYER_VERTICES_PER_FACE*/96) out;
@ -166,33 +186,70 @@ uniform u_light_shadows {
// 128, which would mean FragPos would sum to 4 * 3 * 32 = 384; this could be
// remedied only by setting MAX_POINT_LIGHTS to ), we might enable it again soon.
//
out vec4 FragPos; // FragPos from GS (output per emitvertex)
flat out int FragLayer; // Current layer
// out vec3 FragPos; // FragPos from GS (output per emitvertex)
// flat out int FragLayer; // Current layer
// const vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
void main() {
// return;
// NOTE: Assuming that light_shadow_count.x < MAX_POINT_LIGHTS. We could min
// it, but that might make this less optimized, and I'd like to keep this loop as
// optimized as is reasonably possible.
int face = gl_InvocationID;
for (int layer = 0; layer < light_shadow_count.x; ++layer)
{
// We use instancing here in order to increase the number of emitted vertices.
// int face = gl_InvocationID;
// for(int face = 0; face < FACES_PER_POINT_LIGHT; ++face)
// {
int layer_face = layer * FACES_PER_POINT_LIGHT + face;
// Part 1: emit directed lights.
/* if (face <= light_shadow_count.z) {
// Directed light.
for(int i = 0; i < VERTICES_PER_FACE; ++i) // for each triangle vertex
{
// NOTE: See above, we don't make FragPos a uniform.
FragPos = gl_in[i].gl_Position;
FragLayer = layer;
FragLayer = 0; // 0 is the directed light layer.
// vec4 FragPos = gl_in[i].gl_Position;
gl_Layer = layer_face; // built-in variable that specifies to which face we render.
gl_Position = shadowMats[layer_face].shadowMatrices * FragPos;
gl_Layer = i; // built-in variable that specifies to which face we render.
gl_Position = shadowMats[i].shadowMatrices * FragPos;
EmitVertex();
}
EndPrimitive();
// }
} */
// Part 2: emit point lights.
/* if (light_shadow_count.x == 1) {
return;
} */
for (int layer = 1; layer <= /*light_shadow_count.x*/1; ++layer)
{
int layer_base = layer * FACES_PER_POINT_LIGHT;
// We use instancing here in order to increase the number of emitted vertices.
// int face = gl_InvocationID;
for(int face = 0; face < FACES_PER_POINT_LIGHT; ++face)
{
// int layer_face = layer * FACES_PER_POINT_LIGHT + face;
// int layer_face = layer * FACES_PER_POINT_LIGHT + face;
for(int i = 0; i < VERTICES_PER_FACE; ++i) // for each triangle vertex
{
// NOTE: See above, we don't make FragPos a uniform.
vec3 FragPos = gl_in[i].gl_Position.xyz;
// FragPos = gl_in[i].gl_Position.xyz;
// FragLayer = layer;
// float lightDistance = length(FragPos - lights[((layer - 1) & 31)].light_pos.xyz);
// lightDistance /= screen_res.w;
// vec4 FragPos = gl_in[i].gl_Position;
// NOTE: Our normals map to the same thing as cube map normals, *except* that their normal direction is
// swapped; we can fix this by doing normal ^ 0x1u. However, we also want to cull back faces, not front
// faces, so we only care about the shadow cast by the *back* of the triangle, which means we ^ 0x1u
// again and cancel it out.
// int face = int(((floatBitsToUint(gl_Position.w) >> 29) & 0x7u) ^ 0x1u);
int layer_face = layer_base + face;
gl_Layer = face;//layer_face; // built-in variable that specifies to which face we render.
gl_Position = shadowMats[layer_face].shadowMatrices * vec4(FragPos, 1.0);
// lightDistance = -(lightDistance + screen_res.z) / (screen_res.w - screen_res.z);
// gl_Position.z = lightDistance;
EmitVertex();
}
EndPrimitive();
}
}
}

View File

@ -1,4 +1,5 @@
#version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl>
@ -45,7 +46,7 @@ void main() {
// f_pos = v_pos;
vec3 f_pos = f_chunk_pos + model_offs;
gl_Position = /*all_mat * */vec4(f_pos, 1.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);
}

View File

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

View File

@ -1,4 +1,5 @@
#version 400 core
#version 330 core
// #extension GL_ARB_texture_storage : require
#include <constants.glsl>
@ -38,34 +39,50 @@ out vec4 tgt_color;
void main() {
// tgt_color = vec4(0.0, 0.0, 0.0, 1.0);
// for (uint i = 0u; i < light_shadow_count.x; i ++) {
// float sum = 0.0;
// for (uint i = 0u; i < /* 6 * */light_shadow_count.x; i ++) {
// // uint i = 1u;
// Light L = lights[i];
// Light L = lights[i/* / 6*/];
// vec4 light_col = vec4(
// /* vec4 light_col = vec4(
// hash(vec4(1.0, 0.0, 0.0, i)),
// hash(vec4(1.0, 1.0, 0.0, i)),
// hash(vec4(1.0, 0.0, 1.0, i)),
// 1.0
// );
// ); */
// vec3 light_col = vec3(1.0);//L.light_col.rgb;
// float light_strength = L.light_col.a / 255.0;
// // float light_strength = 1.0 / light_shadow_count.x;
// vec3 light_pos = L.light_pos.xyz;
// // Pre-calculate difference between light and fragment
// vec3 fragToLight = f_pos - light_pos;
// // vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
// // use the light to fragment vector to sample from the depth map
// float bias = 0.05;//0.05;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, i)/*, 0.0*//*, bias*/).r;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
// float visibility = texture(t_shadow_maps, vec4(fragToLight, i), (length(fragToLight) - bias)/* / screen_res.w*/);
// float closestDepth = texture(t_shadow_maps, vec4(fragToLight, i + 1)/*, bias*/).r;
// // float visibility = texture(t_shadow_maps, vec4(fragToLight, i + 1), -(length(fragToLight) - bias)/* / screen_res.w*/);
// // it is currently in linear range between [0,1]. Re-transform back to original value
// // closestDepth *= screen_res.w; // far plane
// // now test for shadows
// // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// // float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
// tgt_color += light_col * vec4(vec3(/*closestDepth*/visibility/* + bias*//* / screen_res.w */) * 1.0 / light_shadow_count.x, 0.0);
// // tgt_color += light_col * vec4(vec3(/*closestDepth*/visibility/* + bias*//* / screen_res.w */) * 1.0 / light_shadow_count.x, 0.0);
// tgt_color.rgb += light_col * vec3(closestDepth + 0.05 / screen_res.w) * 1.0 /*/ light_shadow_count.x*/ * light_strength;
// sum += light_strength;
// }
// /* if (light_shadow_count.x == 1) {
// tgt_color.rgb = vec3(0.0);
// } */
// if (sum > 0.0) {
// tgt_color.rgb /= sum;
// }
// return;

View File

@ -14,6 +14,10 @@ use common::terrain::BlockKind;
use gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
use vek::*;
pub const MAX_POINT_LIGHT_COUNT: usize = 32;
pub const MAX_FIGURE_SHADOW_COUNT: usize = 24;
pub const MAX_DIRECTED_LIGHT_COUNT: usize = 6;
gfx_defines! {
constant Globals {
view_mat: [[f32; 4]; 4] = "view_mat",
@ -37,6 +41,7 @@ gfx_defines! {
/// w, z represent the near and far planes of the shadow map.
screen_res: [f32; 4] = "screen_res",
light_shadow_count: [u32; 4] = "light_shadow_count",
shadow_proj_factors: [f32; 4] = "shadow_proj_factors",
medium: [u32; 4] = "medium",
select_pos: [i32; 4] = "select_pos",
gamma: [f32; 4] = "gamma",
@ -47,6 +52,7 @@ gfx_defines! {
constant Light {
pos: [f32; 4] = "light_pos",
col: [f32; 4] = "light_col",
// proj: [[f32; 4]; 4] = "light_proj";
}
constant Shadow {
@ -70,6 +76,7 @@ impl Globals {
shadow_planes: Vec2<f32>,
light_count: usize,
shadow_count: usize,
directed_light_count: usize,
medium: BlockKind,
select_pos: Option<Vec3<i32>>,
gamma: f32,
@ -92,7 +99,18 @@ impl Globals {
shadow_planes.x,
shadow_planes.y,
],
light_shadow_count: [light_count as u32, shadow_count as u32, 0, 0],
light_shadow_count: [
(light_count % MAX_POINT_LIGHT_COUNT) as u32,
(shadow_count % MAX_FIGURE_SHADOW_COUNT) as u32,
(directed_light_count % MAX_DIRECTED_LIGHT_COUNT) as u32,
0,
],
shadow_proj_factors: [
(shadow_planes.y + shadow_planes.x) / (shadow_planes.y - shadow_planes.x),
(2.0 * shadow_planes.y * shadow_planes.x) / (shadow_planes.y - shadow_planes.x),
0.0,
0.0,
],
medium: [if medium.is_fluid() { 1 } else { 0 }; 4],
select_pos: select_pos
.map(|sp| Vec4::from(sp) + Vec4::unit_w())
@ -121,6 +139,7 @@ impl Default for Globals {
Vec2::new(1.0, 25.0),
0,
0,
0,
BlockKind::Air,
None,
1.0,

View File

@ -31,7 +31,7 @@ gfx_defines! {
// Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_TEST,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
}
}

View File

@ -419,7 +419,7 @@ impl Renderer {
let depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let shadow_tex = factory
.create_texture(
gfx::texture::Kind::CubeArray(size / 4, 32),
gfx::texture::Kind::/*CubeArray*/Cube(size / 4 /* size * 2*//*, 32 */),
1 as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data,
@ -436,7 +436,12 @@ impl Renderer {
sampler_info.comparison = Some(Comparison::LessEqual);
sampler_info.border = [1.0; 4].into();
let shadow_tex_sampler = factory.create_sampler(sampler_info);
/* let tgt_shadow_view = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(1),
gfx::texture::DepthStencilFlags::empty(),
)?; */
let tgt_shadow_view = factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
/* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex,
@ -454,7 +459,24 @@ impl Renderer {
gfx::format::Swizzle::new(),
)?;
Ok((tgt_shadow_view, tgt_shadow_res, shadow_tex_sampler))
/* let tgt_sun_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(0),
gfx::texture::DepthStencilFlags::RO_DEPTH,
)?;
let tgt_moon_res = factory.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
&shadow_tex,
0,
Some(1),
gfx::texture::DepthStencilFlags::RO_DEPTH,
)?; */
Ok((
tgt_shadow_view,
tgt_shadow_res,
/* tgt_directed_res, */ shadow_tex_sampler,
))
}
/// Get the resolution of the render target.
@ -465,13 +487,23 @@ impl Renderer {
)
}
/// Get the resolution of the shadow render target.
pub fn get_shadow_resolution(&self) -> Vec2<u16> {
if let Some(shadow_map) = &self.shadow_map {
let dims = shadow_map.depth_stencil_view.get_dimensions();
Vec2::new(dims.0, dims.1)
} else {
Vec2::new(1, 1)
}
}
/// Queue the clearing of the depth target ready for a new frame to be
/// rendered.
pub fn clear(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() {
shadow_map
.encoder
.clear_depth(&shadow_map.depth_stencil_view, 1.0);
let encoder = &mut shadow_map.encoder;
encoder.clear_depth(&shadow_map.depth_stencil_view, 1.0);
// encoder.clear_stencil(&shadow_map.depth_stencil_view, 0);
}
self.encoder.clear_depth(&self.tgt_depth_stencil_view, 1.0);
self.encoder.clear_stencil(&self.tgt_depth_stencil_view, 0);
@ -481,7 +513,8 @@ impl Renderer {
/// Perform all queued draw calls for shadows.
pub fn flush_shadows(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() {
shadow_map.encoder.flush(&mut self.device);
let encoder = &mut shadow_map.encoder;
encoder.flush(&mut self.device);
}
}
@ -489,7 +522,8 @@ impl Renderer {
/// items.
pub fn flush(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() {
shadow_map.encoder.flush(&mut self.device);
let encoder = &mut shadow_map.encoder;
encoder.flush(&mut self.device);
}
self.encoder.flush(&mut self.device);
self.device.cleanup();
@ -902,7 +936,8 @@ impl Renderer {
} else {
return;
};
shadow_map.encoder.draw(
let encoder = &mut shadow_map.encoder;
encoder.draw(
&gfx::Slice {
start: model.vertex_range().start,
end: model.vertex_range().end,
@ -1471,14 +1506,14 @@ fn create_shadow_pipeline<P: gfx::pso::PipelineInit>(
// Second-depth shadow mapping: should help reduce z-fighting provided all objects
// are "watertight" (every triangle edge is shared with at most one other
// triangle); this *should* be true for Veloren.
cull_face: /*cull_face*//*gfx::state::CullFace::Nothing*/match cull_face {
cull_face: /*gfx::state::CullFace::Nothing*/match cull_face {
gfx::state::CullFace::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
},
method: gfx::state::RasterMethod::Fill,
offset: Some(gfx::state::Offset(4, /*10*/10)),
samples: None,//Some(gfx::state::MultiSample),
offset: None,//Some(gfx::state::Offset(4, /*10*/-10)),
samples:None,//Some(gfx::state::MultiSample),
},
pipe,
)?,

View File

@ -35,6 +35,7 @@ const CURSOR_PAN_SCALE: f32 = 0.005;
const MAX_LIGHT_COUNT: usize = 32;
const MAX_SHADOW_COUNT: usize = 24;
const NUM_DIRECTED_LIGHTS: usize = 2;
const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not emit light from their origin
const SHADOW_DIST_RADIUS: f32 = 8.0;
const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not be visible
@ -42,8 +43,8 @@ const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not
// const NEAR_PLANE: f32 = 0.5;
// const FAR_PLANE: f32 = 100000.0;
const SHADOW_NEAR: f32 = 0.5; //0.5;//1.0; // Near plane for shadow map rendering.
const SHADOW_FAR: f32 = 512.0; //100000.0;//25.0; // Far plane for shadow map rendering.
const SHADOW_NEAR: f32 = 1.0; //1.0; //0.5;//1.0; // Near plane for shadow map rendering.
const SHADOW_FAR: f32 = 128.0; //25.0; //100000.0;//25.0; // Far plane for shadow map rendering.
/// Above this speed is considered running
/// Used for first person camera effects
@ -110,7 +111,7 @@ impl Scene {
.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT])
.unwrap(),
shadow_mats: renderer
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6])
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 2])
.unwrap(),
camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson),
camera_input_state: Vec2::zero(),
@ -358,9 +359,36 @@ impl Scene {
.expect("Failed to update light constants");
// Update light projection matrices for the shadow map.
let time_of_day = scene_data.state.get_time_of_day();
let shadow_res = renderer.get_shadow_resolution();
// NOTE: The aspect ratio is currently always 1 for our cube maps, since they
// are equal on all sides.
let shadow_aspect = 1.0;
let shadow_aspect = shadow_res.x as f32 / shadow_res.y as f32;
// First, add a projected matrix for our directed hard lights.
let directed_view_proj = Mat4::orthographic_rh_no(FrustumPlanes {
left: -(shadow_res.x as f32) / 2.0,
right: shadow_res.x as f32 / 2.0,
bottom: -(shadow_res.y as f32) / 2.0,
top: shadow_res.y as f32 / 2.0,
near: SHADOW_NEAR,
far: SHADOW_FAR,
});
// Construct matrices to transform from world space to light space for the sun
// and moon.
const TIME_FACTOR: f32 = (std::f32::consts::PI * 2.0) / (3600.0 * 24.0);
let angle_rad = time_of_day as f32 * TIME_FACTOR;
let sun_dir = Vec3::new(angle_rad.sin(), 0.0, angle_rad.cos());
let moon_dir = Vec3::new(-angle_rad.sin(), 0.0, angle_rad.cos() - 0.5);
let sun_view_mat = Mat4::model_look_at_rh(-sun_dir, Vec3::zero(), Vec3::up());
let moon_view_mat = Mat4::model_look_at_rh(-moon_dir, Vec3::zero(), Vec3::up());
// Now, construct the full projection matrices in the first two directed light
// slots.
let mut shadow_mats = Vec::with_capacity(6 * (lights.len() + 1));
shadow_mats.push(ShadowLocals::new(directed_view_proj * sun_view_mat));
shadow_mats.push(ShadowLocals::new(directed_view_proj * moon_view_mat));
// This leaves us with four dummy slots, which we push as defaults.
shadow_mats.extend_from_slice(&[ShadowLocals::default(); 6 - NUM_DIRECTED_LIGHTS] as _);
// 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 =
@ -376,18 +404,22 @@ impl Scene {
(Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, -1.0, 0.0)),
];
// NOTE: We could create the shadow map collection at the same time as the
// lights, but then we'd have to sort them both, which wastes time.
let shadow_mats = lights
.iter()
.flat_map(|light| {
// lights, but then we'd have to sort them both, which wastes time. Plus, we
// want to prepend our directed lights.
shadow_mats.extend(lights.iter().flat_map(|light| {
// Now, construct the full projection matrix by making the light look at each
// cube face.
let eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]);
orientations.iter().map(move |&(forward, up)| {
ShadowLocals::new(shadow_proj * Mat4::look_at_rh(eye, eye + forward, up))
})
})
.collect::<Vec<_>>();
}));
/* shadow_mats.push(
Mat4::orthographic_rh_no
float near_plane = 1.0f, far_plane = 7.5f;
glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
); */
renderer
.update_consts(&mut self.shadow_mats, &shadow_mats)
.expect("Failed to update light constants");
@ -402,12 +434,13 @@ impl Scene {
self.loaded_distance,
self.lod.get_data().tgt_detail as f32,
self.map_bounds,
scene_data.state.get_time_of_day(),
time_of_day,
scene_data.state.get_time(),
renderer.get_resolution(),
Vec2::new(SHADOW_NEAR, SHADOW_FAR),
lights.len(),
shadows.len(),
NUM_DIRECTED_LIGHTS,
scene_data
.state
.terrain()
@ -422,8 +455,7 @@ impl Scene {
.expect("Failed to update global constants");
// Maintain LoD.
self.lod
.maintain(renderer, scene_data.state.get_time_of_day());
self.lod.maintain(renderer, time_of_day);
// Maintain the terrain.
self.terrain.maintain(

View File

@ -223,6 +223,7 @@ impl Scene {
Vec2::new(SHADOW_NEAR, SHADOW_FAR),
0,
0,
0,
BlockKind::Air,
None,
scene_data.gamma,