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> #include <constants.glsl>

View File

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

View File

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

View File

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

View File

@ -3,6 +3,7 @@
struct Light { struct Light {
vec4 light_pos; vec4 light_pos;
vec4 light_col; vec4 light_col;
// mat4 light_proj;
}; };
layout (std140) layout (std140)
@ -26,27 +27,86 @@ float attenuation_strength(vec3 rpos) {
} }
#ifdef HAS_SHADOW_MAPS #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 // use the light to fragment vector to sample from the depth map
float bias = 0.0;// 0.05; // float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
// float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex)/*, 0.0*//*, 0.0*//*, bias*/).r; // 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); // // // 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 // // // it is currently in linear range between [0,1]. Re-transform back to original value
// closestDepth *= screen_res.w; // far plane // closestDepth = (closestDepth + 0.0) * screen_res.w; // far plane
// // now test for shadows // // // now test for shadows
// // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0; // // // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// float shadow = currentDepth - 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 = 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 visibility;
// return shadow;
} }
#else #else
float ShadowCalculation(uint lightIndex, vec3 fragToLight, float currentDepth) float ShadowCalculation(uint lightIndex, vec3 fragToLight, /*float currentDepth*/vec3 fragPos)
{ {
return 1.0; 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 // Multiply the vec3 only once
const float PI = 3.1415926535897932384626433832795; const float PI = 3.1415926535897932384626433832795;
const float PI_2 = 2 * PI; 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; vec3 color = /*srgb_to_linear*/L.light_col.rgb;
// // Only access the array once // // 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; is_direct = true;
#endif #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); 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); 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 ? */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; 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; vec3 cam_light_diff = light_pos - focus_pos.xyz;
float cam_distance_2 = dot(cam_light_diff, cam_light_diff);// + 0.0001; 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 = sqrt(col_adjusted) * T;
// vec3 c = /*col_adjusted * */col_adjusted * T; // vec3 c = /*col_adjusted * */col_adjusted * T;
return color; // return color;
// return c; return c;
// float sum_col = color.r + color.g + color.b; // 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))); // 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. // However, in the future we might apply some depth transforms here.
#version 330 core #version 330 core
// #extension ARB_texture_storage : enable
#include <constants.glsl> #include <constants.glsl>
@ -25,17 +26,23 @@
// Currently, we only need lights for the light position // Currently, we only need lights for the light position
#include <light.glsl> #include <light.glsl>
in vec4 FragPos; // FragPos from GS (output per emitvertex) // in vec3 FragPos; // FragPos from GS (output per emitvertex)
flat in int FragLayer; // flat in int FragLayer;
void main() void main()
{ {
// get distance between fragment and light source // Only need to do anything with point lights, since sun and moon should already have nonlinear
float lightDistance = length(FragPos.xyz - lights[FragLayer & 31].light_pos.xyz); // distance.
/*if (FragLayer > 0) */{
// get distance between fragment and light source
// float lightDistance = length(FragPos - lights[((FragLayer - 1) & 31)].light_pos.xyz);
// map to [0;1] range by dividing by far_plane // 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 // 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 // NOTE: We only technically need this for cube map arrays and geometry shader
// instancing. // 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> #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 // Since our output primitive is a triangle strip, we have to render three vertices
// each. // each.
@ -140,14 +160,14 @@
// Since wgpu doesn't support geometry shaders anyway, it seems likely that we'll have // 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 // 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. // 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. // 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_VERTICES_PER_FACE (MAX_POINT_LIGHTS * VERTICES_PER_FACE)
#define MAX_LAYER_FACES (MAX_POINT_LIGHTS * FACES_PER_POINT_LIGHT) #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; 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 // 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. // remedied only by setting MAX_POINT_LIGHTS to ), we might enable it again soon.
// //
out vec4 FragPos; // FragPos from GS (output per emitvertex) // out vec3 FragPos; // FragPos from GS (output per emitvertex)
flat out int FragLayer; // Current layer // 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() { void main() {
// return;
// NOTE: Assuming that light_shadow_count.x < MAX_POINT_LIGHTS. We could min // 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 // it, but that might make this less optimized, and I'd like to keep this loop as
// optimized as is reasonably possible. // optimized as is reasonably possible.
int face = gl_InvocationID; // int face = gl_InvocationID;
for (int layer = 0; layer < light_shadow_count.x; ++layer) // 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 = 0; // 0 is the directed light layer.
// vec4 FragPos = gl_in[i].gl_Position;
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. // We use instancing here in order to increase the number of emitted vertices.
// int face = gl_InvocationID; // int face = gl_InvocationID;
// for(int face = 0; face < FACES_PER_POINT_LIGHT; ++face) 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;
// int layer_face = layer * FACES_PER_POINT_LIGHT + face;
for(int i = 0; i < VERTICES_PER_FACE; ++i) // for each triangle vertex for(int i = 0; i < VERTICES_PER_FACE; ++i) // for each triangle vertex
{ {
// NOTE: See above, we don't make FragPos a uniform. // NOTE: See above, we don't make FragPos a uniform.
FragPos = gl_in[i].gl_Position; vec3 FragPos = gl_in[i].gl_Position.xyz;
FragLayer = layer; // 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; // vec4 FragPos = gl_in[i].gl_Position;
gl_Layer = layer_face; // built-in variable that specifies to which face we render. // NOTE: Our normals map to the same thing as cube map normals, *except* that their normal direction is
gl_Position = shadowMats[layer_face].shadowMatrices * FragPos; // 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(); EmitVertex();
} }
EndPrimitive(); EndPrimitive();
// } }
} }
} }

View File

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

View File

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

View File

@ -1,4 +1,5 @@
#version 400 core #version 330 core
// #extension GL_ARB_texture_storage : require
#include <constants.glsl> #include <constants.glsl>
@ -38,34 +39,50 @@ out vec4 tgt_color;
void main() { void main() {
// tgt_color = vec4(0.0, 0.0, 0.0, 1.0); // 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; // // 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, 0.0, 0.0, i)),
// hash(vec4(1.0, 1.0, 0.0, i)), // hash(vec4(1.0, 1.0, 0.0, i)),
// hash(vec4(1.0, 0.0, 1.0, i)), // hash(vec4(1.0, 0.0, 1.0, i)),
// 1.0 // 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; // vec3 light_pos = L.light_pos.xyz;
// // Pre-calculate difference between light and fragment // // Pre-calculate difference between light and fragment
// vec3 fragToLight = f_pos - light_pos; // 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 // // use the light to fragment vector to sample from the depth map
// float bias = 0.05;//0.05; // 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, i)/*, 0.0*//*, bias*/).r;
// // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias); // // 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 // // it is currently in linear range between [0,1]. Re-transform back to original value
// // closestDepth *= screen_res.w; // far plane // // closestDepth *= screen_res.w; // far plane
// // now test for shadows // // now test for shadows
// // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0; // // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
// // float shadow = currentDepth - 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; // 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 gfx::{self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta};
use vek::*; 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! { gfx_defines! {
constant Globals { constant Globals {
view_mat: [[f32; 4]; 4] = "view_mat", 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. /// w, z represent the near and far planes of the shadow map.
screen_res: [f32; 4] = "screen_res", screen_res: [f32; 4] = "screen_res",
light_shadow_count: [u32; 4] = "light_shadow_count", light_shadow_count: [u32; 4] = "light_shadow_count",
shadow_proj_factors: [f32; 4] = "shadow_proj_factors",
medium: [u32; 4] = "medium", medium: [u32; 4] = "medium",
select_pos: [i32; 4] = "select_pos", select_pos: [i32; 4] = "select_pos",
gamma: [f32; 4] = "gamma", gamma: [f32; 4] = "gamma",
@ -47,6 +52,7 @@ gfx_defines! {
constant Light { constant Light {
pos: [f32; 4] = "light_pos", pos: [f32; 4] = "light_pos",
col: [f32; 4] = "light_col", col: [f32; 4] = "light_col",
// proj: [[f32; 4]; 4] = "light_proj";
} }
constant Shadow { constant Shadow {
@ -70,6 +76,7 @@ impl Globals {
shadow_planes: Vec2<f32>, shadow_planes: Vec2<f32>,
light_count: usize, light_count: usize,
shadow_count: usize, shadow_count: usize,
directed_light_count: usize,
medium: BlockKind, medium: BlockKind,
select_pos: Option<Vec3<i32>>, select_pos: Option<Vec3<i32>>,
gamma: f32, gamma: f32,
@ -92,7 +99,18 @@ impl Globals {
shadow_planes.x, shadow_planes.x,
shadow_planes.y, 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], medium: [if medium.is_fluid() { 1 } else { 0 }; 4],
select_pos: select_pos select_pos: select_pos
.map(|sp| Vec4::from(sp) + Vec4::unit_w()) .map(|sp| Vec4::from(sp) + Vec4::unit_w())
@ -121,6 +139,7 @@ impl Default for Globals {
Vec2::new(1.0, 25.0), Vec2::new(1.0, 25.0),
0, 0,
0, 0,
0,
BlockKind::Air, BlockKind::Air,
None, None,
1.0, 1.0,

View File

@ -31,7 +31,7 @@ gfx_defines! {
// Shadow stuff // Shadow stuff
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows", 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 depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
let shadow_tex = factory let shadow_tex = factory
.create_texture( .create_texture(
gfx::texture::Kind::CubeArray(size / 4, 32), gfx::texture::Kind::/*CubeArray*/Cube(size / 4 /* size * 2*//*, 32 */),
1 as gfx::texture::Level, 1 as gfx::texture::Level,
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL, gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
gfx::memory::Usage::Data, gfx::memory::Usage::Data,
@ -436,7 +436,12 @@ impl Renderer {
sampler_info.comparison = Some(Comparison::LessEqual); sampler_info.comparison = Some(Comparison::LessEqual);
sampler_info.border = [1.0; 4].into(); sampler_info.border = [1.0; 4].into();
let shadow_tex_sampler = factory.create_sampler(sampler_info); 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_view = factory.view_texture_as_depth_stencil_trivial(&shadow_tex)?;
/* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>( /* let tgt_shadow_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
&tgt_color_tex, &tgt_color_tex,
@ -454,7 +459,24 @@ impl Renderer {
gfx::format::Swizzle::new(), 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. /// 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 /// Queue the clearing of the depth target ready for a new frame to be
/// rendered. /// rendered.
pub fn clear(&mut self) { pub fn clear(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() { if let Some(shadow_map) = self.shadow_map.as_mut() {
shadow_map let encoder = &mut shadow_map.encoder;
.encoder encoder.clear_depth(&shadow_map.depth_stencil_view, 1.0);
.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_depth(&self.tgt_depth_stencil_view, 1.0);
self.encoder.clear_stencil(&self.tgt_depth_stencil_view, 0); self.encoder.clear_stencil(&self.tgt_depth_stencil_view, 0);
@ -481,7 +513,8 @@ impl Renderer {
/// Perform all queued draw calls for shadows. /// Perform all queued draw calls for shadows.
pub fn flush_shadows(&mut self) { pub fn flush_shadows(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() { 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. /// items.
pub fn flush(&mut self) { pub fn flush(&mut self) {
if let Some(shadow_map) = self.shadow_map.as_mut() { 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.encoder.flush(&mut self.device);
self.device.cleanup(); self.device.cleanup();
@ -902,7 +936,8 @@ impl Renderer {
} else { } else {
return; return;
}; };
shadow_map.encoder.draw( let encoder = &mut shadow_map.encoder;
encoder.draw(
&gfx::Slice { &gfx::Slice {
start: model.vertex_range().start, start: model.vertex_range().start,
end: model.vertex_range().end, 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 // Second-depth shadow mapping: should help reduce z-fighting provided all objects
// are "watertight" (every triangle edge is shared with at most one other // are "watertight" (every triangle edge is shared with at most one other
// triangle); this *should* be true for Veloren. // 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::Front => gfx::state::CullFace::Back,
gfx::state::CullFace::Back => gfx::state::CullFace::Front, gfx::state::CullFace::Back => gfx::state::CullFace::Front,
gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing, gfx::state::CullFace::Nothing => gfx::state::CullFace::Nothing,
}, },
method: gfx::state::RasterMethod::Fill, method: gfx::state::RasterMethod::Fill,
offset: Some(gfx::state::Offset(4, /*10*/10)), offset: None,//Some(gfx::state::Offset(4, /*10*/-10)),
samples: None,//Some(gfx::state::MultiSample), samples:None,//Some(gfx::state::MultiSample),
}, },
pipe, pipe,
)?, )?,

View File

@ -35,6 +35,7 @@ const CURSOR_PAN_SCALE: f32 = 0.005;
const MAX_LIGHT_COUNT: usize = 32; const MAX_LIGHT_COUNT: usize = 32;
const MAX_SHADOW_COUNT: usize = 24; 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 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_DIST_RADIUS: f32 = 8.0;
const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not be visible 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 NEAR_PLANE: f32 = 0.5;
// const FAR_PLANE: f32 = 100000.0; // const FAR_PLANE: f32 = 100000.0;
const SHADOW_NEAR: f32 = 0.5; //0.5;//1.0; // Near 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 = 512.0; //100000.0;//25.0; // Far 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 /// Above this speed is considered running
/// Used for first person camera effects /// Used for first person camera effects
@ -110,7 +111,7 @@ impl Scene {
.create_consts(&[Shadow::default(); MAX_SHADOW_COUNT]) .create_consts(&[Shadow::default(); MAX_SHADOW_COUNT])
.unwrap(), .unwrap(),
shadow_mats: renderer shadow_mats: renderer
.create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6]) .create_consts(&[ShadowLocals::default(); MAX_LIGHT_COUNT * 6 + 2])
.unwrap(), .unwrap(),
camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson), camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson),
camera_input_state: Vec2::zero(), camera_input_state: Vec2::zero(),
@ -358,9 +359,36 @@ impl Scene {
.expect("Failed to update light constants"); .expect("Failed to update light constants");
// Update light projection matrices for the shadow map. // 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 // NOTE: The aspect ratio is currently always 1 for our cube maps, since they
// are equal on all sides. // 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 // 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 = 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)), (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 // 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. // lights, but then we'd have to sort them both, which wastes time. Plus, we
let shadow_mats = lights // want to prepend our directed lights.
.iter() shadow_mats.extend(lights.iter().flat_map(|light| {
.flat_map(|light| { // Now, construct the full projection matrix by making the light look at each
// Now, construct the full projection matrix by making the light look at each // cube face.
// cube face. let eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]);
let eye = Vec3::new(light.pos[0], light.pos[1], light.pos[2]); orientations.iter().map(move |&(forward, up)| {
orientations.iter().map(move |&(forward, up)| { ShadowLocals::new(shadow_proj * Mat4::look_at_rh(eye, eye + 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 renderer
.update_consts(&mut self.shadow_mats, &shadow_mats) .update_consts(&mut self.shadow_mats, &shadow_mats)
.expect("Failed to update light constants"); .expect("Failed to update light constants");
@ -402,12 +434,13 @@ impl Scene {
self.loaded_distance, self.loaded_distance,
self.lod.get_data().tgt_detail as f32, self.lod.get_data().tgt_detail as f32,
self.map_bounds, self.map_bounds,
scene_data.state.get_time_of_day(), time_of_day,
scene_data.state.get_time(), scene_data.state.get_time(),
renderer.get_resolution(), renderer.get_resolution(),
Vec2::new(SHADOW_NEAR, SHADOW_FAR), Vec2::new(SHADOW_NEAR, SHADOW_FAR),
lights.len(), lights.len(),
shadows.len(), shadows.len(),
NUM_DIRECTED_LIGHTS,
scene_data scene_data
.state .state
.terrain() .terrain()
@ -422,8 +455,7 @@ impl Scene {
.expect("Failed to update global constants"); .expect("Failed to update global constants");
// Maintain LoD. // Maintain LoD.
self.lod self.lod.maintain(renderer, time_of_day);
.maintain(renderer, scene_data.state.get_time_of_day());
// Maintain the terrain. // Maintain the terrain.
self.terrain.maintain( self.terrain.maintain(

View File

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