mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fixing various things about shadows.
* Correcting optimal LISPSM parameter. * Figure shadows are cast when they're not visible. * Chunk shadows stay cast until you look away. * Seamless cubemaps for point lights. * Etc.
This commit is contained in:
parent
6c31e6b562
commit
2e2ab3dc1e
@ -59,7 +59,7 @@ float attenuation_strength(vec3 rpos) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
vec3 light_at(vec3 wpos, vec3 wnorm) {
|
||||||
const float LIGHT_AMBIENCE = 0.025;
|
const float LIGHT_AMBIANCE = 0.025;
|
||||||
|
|
||||||
vec3 light = vec3(0);
|
vec3 light = vec3(0);
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) {
|
|||||||
// Multiply the vec3 only once
|
// Multiply the vec3 only once
|
||||||
vec3 color = srgb_to_linear(L.light_col.rgb) * (strength * L.light_col.a);
|
vec3 color = srgb_to_linear(L.light_col.rgb) * (strength * L.light_col.a);
|
||||||
|
|
||||||
light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIENCE);
|
light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIANCE);
|
||||||
}
|
}
|
||||||
return light;
|
return light;
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
|
|||||||
vec3 directed_light = vec3(0.0);
|
vec3 directed_light = vec3(0.0);
|
||||||
vec3 max_light = vec3(0.0);
|
vec3 max_light = vec3(0.0);
|
||||||
|
|
||||||
const float LIGHT_AMBIENCE = 0.0;//0.015625;
|
const float LIGHT_AMBIANCE = 0.015625;
|
||||||
|
|
||||||
for (uint i = 0u; i < /*light_shadow_count.x*//*0u*/light_shadow_count.x/*32u*/; i ++) {
|
for (uint i = 0u; i < /*light_shadow_count.x*//*0u*/light_shadow_count.x/*32u*/; i ++) {
|
||||||
|
|
||||||
@ -183,10 +183,12 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
|
|||||||
#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_norm, 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_norm, voxel_lighting);
|
||||||
float computed_shadow = ShadowCalculationPoint(i, -difference, wnorm, wpos/*, light_distance*/);
|
float computed_shadow = ShadowCalculationPoint(i, -difference, wnorm, 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_AMBIANCE*/0.0) * direct_light * square_factor : vec3(0.0);
|
||||||
directed_light += is_direct ? mix(LIGHT_AMBIENCE, 1.0, computed_shadow) * direct_light * square_factor : vec3(0.0);
|
// directed_light += is_direct ? mix(LIGHT_AMBIANCE, 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;
|
directed_light += (is_direct ? 1.0 : LIGHT_AMBIANCE) * max(computed_shadow, /*LIGHT_AMBIANCE*/0.0) * direct_light * square_factor;// : vec3(0.0);
|
||||||
// ambient_light += is_direct ? direct_light * (1.0 - square_factor * LIGHT_AMBIENCE) : vec3(0.0);
|
// directed_light += mix(LIGHT_AMBIANCE, 1.0, computed_shadow) * direct_light * square_factor;
|
||||||
|
// ambient_light += is_direct ? vec3(0.0) : vec3(0.0); // direct_light * square_factor * LIGHT_AMBIANCE;
|
||||||
|
// ambient_light += is_direct ? direct_light * (1.0 - square_factor * LIGHT_AMBIANCE) : vec3(0.0);
|
||||||
|
|
||||||
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;
|
||||||
@ -209,12 +211,12 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve
|
|||||||
// float both_strength = mix(cam_strength, strength, cam_distance_2 / sqrt(cam_distance_2 + distance_2));
|
// float both_strength = mix(cam_strength, strength, cam_distance_2 / sqrt(cam_distance_2 + distance_2));
|
||||||
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*/computed_shadow * both_strength * square_factor * square_factor * PI * color;
|
max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*//*max(both_strength, 1.0) * *//*cam_strength*/computed_shadow * both_strength * square_factor * square_factor * PI * color;
|
||||||
// max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*/max(cam_strength, 1.0/*, strength*//*1.0*/) * square_factor * square_factor * PI * color;
|
// max_light += /*max(1.0, cam_strength)*//*min(cam_strength, 1.0)*//*max*/max(cam_strength, 1.0/*, strength*//*1.0*/) * square_factor * square_factor * PI * color;
|
||||||
// light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIENCE);
|
// light += color * (max(0, max(dot(normalize(difference), wnorm), 0.15)) + LIGHT_AMBIANCE);
|
||||||
// Compute emiittance.
|
// Compute emiittance.
|
||||||
// float ambient_sides = clamp(mix(0.15, 0.0, abs(dot(wnorm, light_dir)) * 10000.0), 0.0, 0.15);
|
// float ambient_sides = clamp(mix(0.15, 0.0, abs(dot(wnorm, light_dir)) * 10000.0), 0.0, 0.15);
|
||||||
// float ambient_sides = 0.0;// max(dot(wnorm, light_dir) - 0.15, 0.15);
|
// float ambient_sides = 0.0;// max(dot(wnorm, light_dir) - 0.15, 0.15);
|
||||||
// // float ambient_sides = 0.0;
|
// // float ambient_sides = 0.0;
|
||||||
// ambient_light += color * (ambient_sides + LIGHT_AMBIENCE);
|
// ambient_light += color * (ambient_sides + LIGHT_AMBIANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shadow = shadow_at(wpos, wnorm);
|
// shadow = shadow_at(wpos, wnorm);
|
||||||
|
@ -23,6 +23,7 @@ uniform samplerCubeShadow t_point_shadow_maps;
|
|||||||
|
|
||||||
float VectorToDepth (vec3 Vec)
|
float VectorToDepth (vec3 Vec)
|
||||||
{
|
{
|
||||||
|
// return length(Vec) / screen_res.w;
|
||||||
vec3 AbsVec = abs(Vec);
|
vec3 AbsVec = abs(Vec);
|
||||||
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
|
float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));
|
||||||
// float LocalZcomp = length(Vec);
|
// float LocalZcomp = length(Vec);
|
||||||
@ -60,14 +61,6 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, /
|
|||||||
return 1.0;
|
return 1.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
float shadow = 0.0;
|
|
||||||
float bias = 0.0;//0.003;//-0.003;//-0.005;//0.001;//-1.0;//-0.001;//0.001;//0.003;//-0.05;//-0.1;//0.0;//0.1
|
|
||||||
float viewDistance = length(cam_pos.xyz - fragPos);
|
|
||||||
vec3 firstDelta = vec3(0.0);///*min(viewDistance, 5.0) * *//**normalize(cam_pos - fragPos)*/fragNorm * 0.5;
|
|
||||||
fragToLight += firstDelta;
|
|
||||||
// viewDistance -= length(firstDelta);
|
|
||||||
fragPos -= firstDelta;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
float currentDepth = VectorToDepth(fragToLight);// + bias;
|
float currentDepth = VectorToDepth(fragToLight);// + bias;
|
||||||
|
|
||||||
@ -84,55 +77,68 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, /
|
|||||||
/* if (visibility < 1.0) {
|
/* if (visibility < 1.0) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
} */
|
} */
|
||||||
return visibility == 1.0 ? 1.0 : 0.0;
|
// return visibility;
|
||||||
|
/* if (visibility == 1.0) {
|
||||||
|
return visibility;
|
||||||
|
} */
|
||||||
|
return visibility;
|
||||||
|
// return visibility == 1.0 ? 1.0 : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int samples = 20;
|
// float shadow = 0.0;
|
||||||
// float lightDistance = length(fragToLight);
|
// float bias = 0.0;//0.003;//-0.003;//-0.005;//0.001;//-1.0;//-0.001;//0.001;//0.003;//-0.05;//-0.1;//0.0;//0.1
|
||||||
// float diskRadius = 0.00001;
|
// float viewDistance = length(cam_pos.xyz - fragPos);
|
||||||
// float diskRadius = 1.0;
|
// vec3 firstDelta = vec3(0.0);///*min(viewDistance, 5.0) * *//**normalize(cam_pos - fragPos)*/fragNorm * 0.5;
|
||||||
// float diskRadius = 0.05;
|
// fragToLight += firstDelta;
|
||||||
float diskRadius = (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 25.0;
|
// // viewDistance -= length(firstDelta);
|
||||||
// float diskRadius = lightDistance;
|
// fragPos -= firstDelta;
|
||||||
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_point_shadow_maps, vec4(fragToLight, currentDepth)/*, -2.5*/);
|
|
||||||
shadow += visibility;
|
|
||||||
// float closestDepth = texture(t_shadow_maps, vec3(fragToLight)/*, -2.5*/).r;
|
|
||||||
// shadow += closestDepth > currentDepth ? 1.0 : 0.0;
|
|
||||||
}
|
|
||||||
shadow /= float(samples);
|
|
||||||
// shadow = shadow * shadow * (3.0 - 2.0 * shadow);
|
|
||||||
|
|
||||||
// use the light to fragment vector to sample from the depth map
|
// int samples = 20;
|
||||||
// float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
|
// // float lightDistance = length(fragToLight);
|
||||||
// float closestDepth = texture(t_shadow_maps, /*vec4*/vec3(fragToLight/*, (lightIndex + 1)*//* * 6*/)/*, 0.0*//*, 0.0*//*, bias*/).r;
|
// // float diskRadius = 0.00001;
|
||||||
// // // float closestDepth = texture(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
|
// // float diskRadius = 1.0;
|
||||||
// // // it is currently in linear range between [0,1]. Re-transform back to original value
|
// // float diskRadius = 0.05;
|
||||||
// closestDepth = (closestDepth + 0.0) * screen_res.w; // far plane
|
// float diskRadius = 5.0 / screen_res.w;// (1.0 + (/*viewDistance*/viewDistance / screen_res.w)) / 25.0;
|
||||||
// // // now test for shadows
|
// // float diskRadius = lightDistance;
|
||||||
// // // float shadow = /*currentDepth*/(screen_res.w - bias) > closestDepth ? 1.0 : 0.0;
|
// for(int i = 0; i < samples; ++i)
|
||||||
// float shadow = currentDepth - bias < closestDepth ? 1.0 : 0.0;
|
// {
|
||||||
// float visibility = textureProj(t_shadow_maps, vec4(fragToLight, lightIndex), bias);
|
// float currentDepth = VectorToDepth(fragToLight + sampleOffsetDirections[i] * diskRadius) + bias;
|
||||||
// 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*/);
|
// // float closestDepth = texture(depthMap, fragToLight).r;
|
||||||
// currentDepth += bias;
|
// // closestDepth *= far_plane; // Undo mapping [0;1]
|
||||||
// currentDepth = -1000.0 / (currentDepth + 10000.0);
|
// /* if(currentDepth - bias > closestDepth)
|
||||||
// currentDepth /= screen_res.w;
|
// shadow += 1.0;*/
|
||||||
// float currentDepth = VectorToDepth(fragToLight) + bias;
|
// float visibility = texture(t_point_shadow_maps, vec4(fragToLight, currentDepth)/*, -2.5*/);
|
||||||
|
// shadow += visibility;
|
||||||
|
// // float closestDepth = texture(t_shadow_maps, vec3(fragToLight)/*, -2.5*/).r;
|
||||||
|
// // shadow += closestDepth > currentDepth ? 1.0 : 0.0;
|
||||||
|
// }
|
||||||
|
// shadow /= float(samples);
|
||||||
|
// // shadow = shadow * shadow * (3.0 - 2.0 * shadow);
|
||||||
|
|
||||||
// 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*/);
|
// // use the light to fragment vector to sample from the depth map
|
||||||
// return visibility == 1.0 ? 1.0 : 0.0;
|
// // float bias = 0.0;///*0.05*/0.01;//0.05;// 0.05;
|
||||||
return shadow;
|
// // 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 + 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;
|
||||||
|
|
||||||
|
// // 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 == 1.0 ? 1.0 : 0.0;
|
||||||
|
// return shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_pos, vec3 fragPos)
|
float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_pos, vec3 fragPos)
|
||||||
{
|
{
|
||||||
float bias = 0.000;//0.0005;//-0.0001;// 0.05 / (2.0 * view_distance.x);
|
float bias = 0.001;//0.0005;//-0.0001;// 0.05 / (2.0 * view_distance.x);
|
||||||
float diskRadius = 0.01;
|
float diskRadius = 0.01;
|
||||||
const vec3 sampleOffsetDirections[20] = vec3[]
|
const vec3 sampleOffsetDirections[20] = vec3[]
|
||||||
(
|
(
|
||||||
@ -150,16 +156,20 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po
|
|||||||
// sun_pos.z += sun_pos.w * bias;
|
// sun_pos.z += sun_pos.w * bias;
|
||||||
ShadowLocals sun_shadow = shadowMats[0];
|
ShadowLocals sun_shadow = shadowMats[0];
|
||||||
vec4 sun_pos = sun_shadow.texture_mat * vec4(fragPos, 1.0);
|
vec4 sun_pos = sun_shadow.texture_mat * vec4(fragPos, 1.0);
|
||||||
|
// sun_pos.z -= sun_pos.w * bias;
|
||||||
float visibility = textureProj(t_directed_shadow_maps, sun_pos);
|
float visibility = textureProj(t_directed_shadow_maps, sun_pos);
|
||||||
/* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0));
|
/* float visibilityLeft = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, -diskRadius, 0.0), 1.0));
|
||||||
float visibilityRight = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, diskRadius, 0.0), 1.0)); */
|
float visibilityRight = textureProj(t_directed_shadow_maps, sun_shadow.texture_mat * vec4(fragPos + vec3(0.0, diskRadius, 0.0), 1.0)); */
|
||||||
// float nearVisibility = textureProj(t_directed_shadow_maps + vec3(0.001, sun_pos));
|
// float nearVisibility = textureProj(t_directed_shadow_maps + vec3(0.001, sun_pos));
|
||||||
// float visibility = textureProj(t_directed_shadow_maps, vec4(fragPos.xy, /*lightIndex, */fragPos.z + bias, sun_pos.w));
|
// float visibility = textureProj(t_directed_shadow_maps, vec4(fragPos.xy, /*lightIndex, */fragPos.z + bias, sun_pos.w));
|
||||||
return visibility;
|
// return visibility;
|
||||||
// return min(visibility, min(visibilityLeft, visibilityRight));
|
// return min(visibility, min(visibilityLeft, visibilityRight));
|
||||||
// return mix(visibility, 0.0, sun_pos.z < -1.0);
|
// return mix(visibility, 0.0, sun_pos.z < -1.0);
|
||||||
// return mix(mix(0.0, 1.0, visibility == 1.0), 1.0, sign(sun_pos.w) * sun_pos.z > /*1.0*/abs(sun_pos.w));
|
// return mix(mix(0.0, 1.0, visibility == 1.0), 1.0, sign(sun_pos.w) * sun_pos.z > /*1.0*/abs(sun_pos.w));
|
||||||
|
// return (visibility - 0.5) * (visibility - 0.5) * 2.0 * sign(visibility - 0.5) + 0.5;// visibility > 0.75 ? visibility : 0.0;// visibility > 0.9 ? 1.0 : 0.0;
|
||||||
|
return visibility;
|
||||||
// return visibility == 1.0 ? 1.0 : 0.0;
|
// return visibility == 1.0 ? 1.0 : 0.0;
|
||||||
|
// return abs(fragPos.y - round(fragPos.y)) <= 0.1 || abs(fragPos.x - round(fragPos.x)) <= 0.1 ? ( visibility == 1.0 ? 1.0 : 0.0) : visibility;
|
||||||
/* if (visibility == 1.0) {
|
/* if (visibility == 1.0) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
} */
|
} */
|
||||||
@ -167,32 +177,32 @@ float ShadowCalculationDirected(in vec3 fragPos)//in vec4 /*light_pos[2]*/sun_po
|
|||||||
/* if (fragPos.z > 1.0) {
|
/* if (fragPos.z > 1.0) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
} */
|
} */
|
||||||
vec3 snapToZ = abs(fragPos - vec3(ivec3(fragPos))); // fract(abs(fragPos));
|
// vec3 snapToZ = abs(fragPos - vec3(ivec3(fragPos))); // fract(abs(fragPos));
|
||||||
// snapToZ = min(snapToZ, 1.0 - snapToZ);
|
// // snapToZ = min(snapToZ, 1.0 - snapToZ);
|
||||||
const float EDGE_DIST = 0.01;
|
// const float EDGE_DIST = 0.01;
|
||||||
snapToZ = mix(vec3(0.0), vec3(1.0), lessThanEqual(snapToZ, vec3(EDGE_DIST)));
|
// snapToZ = mix(vec3(0.0), vec3(1.0), lessThanEqual(snapToZ, vec3(EDGE_DIST)));
|
||||||
// float snapToZDist = dot(snapToZ, snapToZ);
|
// // float snapToZDist = dot(snapToZ, snapToZ);
|
||||||
if (visibility <= 0.75 && /*fract(abs(fragPos.xy)), vec2(0.1)))*/ /*snapToZDist <= 0.25*//*all(lessThan(snapToZ, vec3(0.1)))(*/
|
// if (visibility <= 0.75 && /*fract(abs(fragPos.xy)), vec2(0.1)))*/ /*snapToZDist <= 0.25*//*all(lessThan(snapToZ, vec3(0.1)))(*/
|
||||||
snapToZ.x + snapToZ.y + snapToZ.z >= 2.0) {
|
// snapToZ.x + snapToZ.y + snapToZ.z >= 2.0) {
|
||||||
return 0.0;
|
// return 0.0;
|
||||||
}
|
// }
|
||||||
int samples = 20;
|
// int samples = 20;
|
||||||
float shadow = 0.0;
|
// float shadow = 0.0;
|
||||||
// float bias = 0.0001;
|
// // float bias = 0.0001;
|
||||||
// float viewDistance = length(cam_pos.xyz - fragPos);
|
// // float viewDistance = length(cam_pos.xyz - fragPos);
|
||||||
// float diskRadius = 0.2 * (1.0 + (viewDistance / screen_res.w)) / 25.0;
|
// // float diskRadius = 0.2 * (1.0 + (viewDistance / screen_res.w)) / 25.0;
|
||||||
// float diskRadius = 0.0003;//0.005;// / (2.0 * view_distance.x);//(1.0 + (viewDistance / screen_res.w)) / 25.0;
|
// // float diskRadius = 0.0003;//0.005;// / (2.0 * view_distance.x);//(1.0 + (viewDistance / screen_res.w)) / 25.0;
|
||||||
fragPos = sun_pos.xyz / sun_pos.w;
|
// fragPos = sun_pos.xyz / sun_pos.w;
|
||||||
for(int i = 0; i < samples; ++i)
|
// for(int i = 0; i < samples; ++i)
|
||||||
{
|
// {
|
||||||
vec3 currentDepth = fragPos + vec3(sampleOffsetDirections[i].xyz) * diskRadius + bias;
|
// vec3 currentDepth = fragPos + vec3(sampleOffsetDirections[i].xyz) * diskRadius + bias;
|
||||||
visibility = texture(t_directed_shadow_maps, currentDepth);//vec4(currentDepth.xy, lightIndex, currentDepth.z)/*, -2.5*/);
|
// visibility = texture(t_directed_shadow_maps, currentDepth);//vec4(currentDepth.xy, lightIndex, currentDepth.z)/*, -2.5*/);
|
||||||
// visibility = texture(t_directed_shadow_maps, vec4(currentDepth.xy, lightIndex, currentDepth.z)/*, -2.5*/);
|
// // visibility = texture(t_directed_shadow_maps, vec4(currentDepth.xy, lightIndex, currentDepth.z)/*, -2.5*/);
|
||||||
shadow += visibility;
|
// shadow += visibility;
|
||||||
// mix(visibility, 1.0, visibility >= 0.5);
|
// // mix(visibility, 1.0, visibility >= 0.5);
|
||||||
}
|
// }
|
||||||
shadow /= float(samples);
|
// shadow /= float(samples);
|
||||||
return shadow;
|
// return shadow;
|
||||||
}
|
}
|
||||||
#elif (SHADOW_MODE == SHADOW_MODE_NONE || SHADOW_MODE == SHADOW_MODE_CHEAP)
|
#elif (SHADOW_MODE == SHADOW_MODE_NONE || SHADOW_MODE == SHADOW_MODE_CHEAP)
|
||||||
float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, /*float currentDepth*/vec3 fragPos)
|
float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, /*float currentDepth*/vec3 fragPos)
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
||||||
|
|
||||||
// // Currently, we only need globals for the far plane.
|
// Currently, we only need globals for the far plane.
|
||||||
// #include <globals.glsl>
|
#include <globals.glsl>
|
||||||
// // Currently, we only need lights for the light position
|
// // Currently, we only need lights for the light position
|
||||||
// #include <light.glsl>
|
// #include <light.glsl>
|
||||||
|
|
||||||
@ -33,16 +33,17 @@ void main()
|
|||||||
{
|
{
|
||||||
// Only need to do anything with point lights, since sun and moon should already have nonlinear
|
// Only need to do anything with point lights, since sun and moon should already have nonlinear
|
||||||
// distance.
|
// distance.
|
||||||
/*if (FragLayer > 0) */{
|
///*if (FragLayer > 0) */{
|
||||||
// get distance between fragment and light source
|
// // get distance between fragment and light source
|
||||||
// float lightDistance = length(FragPos - lights[((/*FragLayer*/1 - 1) & 31)].light_pos.xyz);
|
// float lightDistance = length(FragPos);
|
||||||
|
// // float lightDistance = length(FragPos - lights[((/*FragLayer*/1 - 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 / screen_res.w;//FragPos.w;//screen_res.w;
|
// lightDistance = lightDistance / screen_res.w;//FragPos.w;//screen_res.w;
|
||||||
|
|
||||||
// // write this as modified depth
|
// // // write this as modified depth
|
||||||
// // lightDistance = -1000.0 / (lightDistance + 10000.0);
|
// // // lightDistance = -1000.0 / (lightDistance + 10000.0);
|
||||||
// // lightDistance /= screen_res.w;
|
// // // lightDistance /= screen_res.w;
|
||||||
// gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance
|
// gl_FragDepth = lightDistance;// / /*FragPos.w;*/screen_res.w;//-1000.0 / (lightDistance + 1000.0);//lightDistance
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,17 @@
|
|||||||
// // Currently, we only need lights for the light position
|
// // Currently, we only need lights for the light position
|
||||||
// #include <light.glsl>
|
// #include <light.glsl>
|
||||||
|
|
||||||
|
/* struct Light {
|
||||||
|
vec4 light_pos;
|
||||||
|
vec4 light_col;
|
||||||
|
// mat4 light_proj;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std140)
|
||||||
|
uniform u_lights {
|
||||||
|
Light lights[31];
|
||||||
|
}; */
|
||||||
|
|
||||||
// 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.
|
||||||
#define VERTICES_PER_FACE 3
|
#define VERTICES_PER_FACE 3
|
||||||
@ -236,8 +247,8 @@ void main() {
|
|||||||
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.
|
||||||
vec3 FragPos = gl_in[i].gl_Position.xyz;
|
vec3 fragPos = gl_in[i].gl_Position.xyz;
|
||||||
// FragPos = gl_in[i].gl_Position.xyz;
|
// FragPos = fragPos - (lights[((/*FragLayer*/layer - 1u) & 31u)].light_pos.xyz - focus_off.xyz);
|
||||||
// FragLayer = layer;
|
// FragLayer = layer;
|
||||||
// float lightDistance = length(FragPos - lights[((layer - 1) & 31)].light_pos.xyz);
|
// float lightDistance = length(FragPos - lights[((layer - 1) & 31)].light_pos.xyz);
|
||||||
// lightDistance /= screen_res.w;
|
// lightDistance /= screen_res.w;
|
||||||
@ -250,7 +261,7 @@ void main() {
|
|||||||
// int face = int(((floatBitsToUint(gl_Position.w) >> 29) & 0x7u) ^ 0x1u);
|
// int face = int(((floatBitsToUint(gl_Position.w) >> 29) & 0x7u) ^ 0x1u);
|
||||||
int layer_face = layer_base + face;
|
int layer_face = layer_base + face;
|
||||||
gl_Layer = face;//layer_face; // built-in variable that specifies to which face we render.
|
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);
|
gl_Position = shadowMats[layer_face].shadowMatrices * vec4(fragPos, 1.0);
|
||||||
// gl_Position.z = -((gl_Position.z + screen_res.z) / (screen_res.w - screen_res.z)) * lightDistance;
|
// gl_Position.z = -((gl_Position.z + screen_res.z) / (screen_res.w - screen_res.z)) * lightDistance;
|
||||||
// gl_Position.z = gl_Position.z / screen_res.w;
|
// gl_Position.z = gl_Position.z / screen_res.w;
|
||||||
// gl_Position.z = gl_Position.z / gl_Position.w;
|
// gl_Position.z = gl_Position.z / gl_Position.w;
|
||||||
|
@ -226,6 +226,7 @@ pub struct DebugInfo {
|
|||||||
pub ori: Option<comp::Ori>,
|
pub ori: Option<comp::Ori>,
|
||||||
pub num_chunks: u32,
|
pub num_chunks: u32,
|
||||||
pub num_visible_chunks: u32,
|
pub num_visible_chunks: u32,
|
||||||
|
pub num_shadow_chunks: u32,
|
||||||
pub num_figures: u32,
|
pub num_figures: u32,
|
||||||
pub num_figures_visible: u32,
|
pub num_figures_visible: u32,
|
||||||
}
|
}
|
||||||
@ -594,7 +595,7 @@ impl Hud {
|
|||||||
&mut self,
|
&mut self,
|
||||||
client: &Client,
|
client: &Client,
|
||||||
global_state: &GlobalState,
|
global_state: &GlobalState,
|
||||||
debug_info: DebugInfo,
|
debug_info: &Option<DebugInfo>,
|
||||||
dt: Duration,
|
dt: Duration,
|
||||||
info: HudInfo,
|
info: HudInfo,
|
||||||
) -> Vec<Event> {
|
) -> Vec<Event> {
|
||||||
@ -602,10 +603,6 @@ impl Hud {
|
|||||||
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
||||||
// pulse time for pulsating elements
|
// pulse time for pulsating elements
|
||||||
self.pulse = self.pulse + dt.as_secs_f32();
|
self.pulse = self.pulse + dt.as_secs_f32();
|
||||||
self.velocity = match debug_info.velocity {
|
|
||||||
Some(velocity) => velocity.0.magnitude(),
|
|
||||||
None => 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let version = format!(
|
let version = format!(
|
||||||
"{}-{}",
|
"{}-{}",
|
||||||
@ -1239,7 +1236,11 @@ impl Hud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display debug window.
|
// Display debug window.
|
||||||
if global_state.settings.gameplay.toggle_debug {
|
if let Some(debug_info) = debug_info {
|
||||||
|
self.velocity = match debug_info.velocity {
|
||||||
|
Some(velocity) => velocity.0.magnitude(),
|
||||||
|
None => 0.0,
|
||||||
|
};
|
||||||
// Alpha Version
|
// Alpha Version
|
||||||
Text::new(&version)
|
Text::new(&version)
|
||||||
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
||||||
@ -1345,8 +1346,8 @@ impl Hud {
|
|||||||
|
|
||||||
// Number of chunks
|
// Number of chunks
|
||||||
Text::new(&format!(
|
Text::new(&format!(
|
||||||
"Chunks: {} ({} visible)",
|
"Chunks: {} ({} visible) & {} (shadow)",
|
||||||
debug_info.num_chunks, debug_info.num_visible_chunks,
|
debug_info.num_chunks, debug_info.num_visible_chunks, debug_info.num_shadow_chunks,
|
||||||
))
|
))
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.down_from(self.ids.entity_count, 5.0)
|
.down_from(self.ids.entity_count, 5.0)
|
||||||
@ -2213,7 +2214,7 @@ impl Hud {
|
|||||||
&mut self,
|
&mut self,
|
||||||
client: &Client,
|
client: &Client,
|
||||||
global_state: &mut GlobalState,
|
global_state: &mut GlobalState,
|
||||||
debug_info: DebugInfo,
|
debug_info: &Option<DebugInfo>,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
dt: Duration,
|
dt: Duration,
|
||||||
info: HudInfo,
|
info: HudInfo,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{
|
use super::{
|
||||||
super::{
|
super::{
|
||||||
ColLightFmt, ColLightInfo, Pipeline, RenderError, Renderer, ShadowDepthStencilFmt,
|
ColLightFmt, ColLightInfo, Light, Pipeline, RenderError, Renderer, ShadowDepthStencilFmt,
|
||||||
TerrainLocals, Texture,
|
TerrainLocals, Texture,
|
||||||
},
|
},
|
||||||
figure, terrain, Globals,
|
figure, terrain, Globals,
|
||||||
@ -30,7 +30,7 @@ gfx_defines! {
|
|||||||
|
|
||||||
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
|
locals: gfx::ConstantBuffer<TerrainLocals> = "u_locals",
|
||||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||||
// lights: gfx::ConstantBuffer<Light> = "u_lights",
|
lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||||
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||||
|
|
||||||
// map: gfx::TextureSampler<[f32; 4]> = "t_map",
|
// map: gfx::TextureSampler<[f32; 4]> = "t_map",
|
||||||
@ -42,7 +42,7 @@ gfx_defines! {
|
|||||||
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
||||||
|
|
||||||
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
|
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
|
||||||
fun: gfx::state::Comparison::Less,
|
fun: gfx::state::Comparison::LessEqual,
|
||||||
write: true,
|
write: true,
|
||||||
},
|
},
|
||||||
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,//,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))),
|
||||||
@ -67,7 +67,7 @@ gfx_defines! {
|
|||||||
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
light_shadows: gfx::ConstantBuffer<Locals> = "u_light_shadows",
|
||||||
|
|
||||||
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
|
tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::state::Depth {
|
||||||
fun: gfx::state::Comparison::Less,
|
fun: gfx::state::Comparison::LessEqual,
|
||||||
write: true,
|
write: true,
|
||||||
},
|
},
|
||||||
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
// tgt_depth_stencil: gfx::DepthTarget<ShadowDepthStencilFmt> = gfx::preset::depth::LESS_WRITE,//,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Keep))),
|
||||||
|
@ -1388,8 +1388,8 @@ impl Renderer {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
terrain_locals: &Consts<terrain::Locals>,
|
terrain_locals: &Consts<terrain::Locals>,
|
||||||
locals: &Consts<shadow::Locals>,
|
locals: &Consts<shadow::Locals>,
|
||||||
/* lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
* shadows: &Consts<Shadow>,
|
/* shadows: &Consts<Shadow>,
|
||||||
* map: &Texture<LodColorFmt>,
|
* map: &Texture<LodColorFmt>,
|
||||||
* horizon: &Texture<LodTextureFmt>, */
|
* horizon: &Texture<LodTextureFmt>, */
|
||||||
) {
|
) {
|
||||||
@ -1419,7 +1419,7 @@ impl Renderer {
|
|||||||
vbuf: model.vbuf.clone(),
|
vbuf: model.vbuf.clone(),
|
||||||
locals: terrain_locals.buf.clone(),
|
locals: terrain_locals.buf.clone(),
|
||||||
globals: globals.buf.clone(),
|
globals: globals.buf.clone(),
|
||||||
// lights: lights.buf.clone(),
|
lights: lights.buf.clone(),
|
||||||
// shadows: shadows.buf.clone(),
|
// shadows: shadows.buf.clone(),
|
||||||
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||||
// map: (map.srv.clone(), map.sampler.clone()),
|
// map: (map.srv.clone(), map.sampler.clone()),
|
||||||
@ -1443,8 +1443,8 @@ impl Renderer {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
terrain_locals: &Consts<terrain::Locals>,
|
terrain_locals: &Consts<terrain::Locals>,
|
||||||
locals: &Consts<shadow::Locals>,
|
locals: &Consts<shadow::Locals>,
|
||||||
/* lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
* shadows: &Consts<Shadow>,
|
/* shadows: &Consts<Shadow>,
|
||||||
* map: &Texture<LodColorFmt>,
|
* map: &Texture<LodColorFmt>,
|
||||||
* horizon: &Texture<LodTextureFmt>, */
|
* horizon: &Texture<LodTextureFmt>, */
|
||||||
) {
|
) {
|
||||||
@ -1474,7 +1474,7 @@ impl Renderer {
|
|||||||
vbuf: model.vbuf.clone(),
|
vbuf: model.vbuf.clone(),
|
||||||
locals: terrain_locals.buf.clone(),
|
locals: terrain_locals.buf.clone(),
|
||||||
globals: globals.buf.clone(),
|
globals: globals.buf.clone(),
|
||||||
// lights: lights.buf.clone(),
|
lights: lights.buf.clone(),
|
||||||
// shadows: shadows.buf.clone(),
|
// shadows: shadows.buf.clone(),
|
||||||
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
// noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||||
// map: (map.srv.clone(), map.sampler.clone()),
|
// map: (map.srv.clone(), map.sampler.clone()),
|
||||||
@ -2089,8 +2089,8 @@ fn create_pipelines(
|
|||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
&include_ctx,
|
&include_ctx,
|
||||||
gfx::state::CullFace::Back,
|
gfx::state::CullFace::Front,
|
||||||
None, //Some(gfx::state::Offset(2, 10)),
|
Some(gfx::state::Offset(2, /* 10 */ 0)),
|
||||||
) {
|
) {
|
||||||
Ok(pipe) => Some(pipe),
|
Ok(pipe) => Some(pipe),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -2108,9 +2108,10 @@ fn create_pipelines(
|
|||||||
&directed_shadow_frag,
|
&directed_shadow_frag,
|
||||||
&include_ctx,
|
&include_ctx,
|
||||||
gfx::state::CullFace::Back,
|
gfx::state::CullFace::Back,
|
||||||
|
/* None, */
|
||||||
|
/* Some(gfx::state::Offset(4, 10)), */
|
||||||
None,
|
None,
|
||||||
/* Some(gfx::state::Offset(4, 10)),
|
// Some(gfx::state::Offset(2, /*10*/1)),
|
||||||
* Some(gfx::state::Offset(2, 10)), */
|
|
||||||
) {
|
) {
|
||||||
Ok(pipe) => Some(pipe),
|
Ok(pipe) => Some(pipe),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -2131,9 +2132,10 @@ fn create_pipelines(
|
|||||||
&directed_shadow_frag,
|
&directed_shadow_frag,
|
||||||
&include_ctx,
|
&include_ctx,
|
||||||
gfx::state::CullFace::Back,
|
gfx::state::CullFace::Back,
|
||||||
None,
|
/* None, */
|
||||||
/* Some(gfx::state::Offset(4, 10)),
|
/* Some(gfx::state::Offset(4, 10)), */
|
||||||
* Some(gfx::state::Offset(2, 10)), */
|
/*Some(gfx::state::Offset(2, 1))*/None,
|
||||||
|
/* Some(gfx::state::Offset(2, 10)), */
|
||||||
) {
|
) {
|
||||||
Ok(pipe) => Some(pipe),
|
Ok(pipe) => Some(pipe),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -12,8 +12,8 @@ use crate::{
|
|||||||
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, Texture,
|
RenderError, Renderer, Shadow, ShadowLocals, ShadowPipeline, Texture,
|
||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{Camera, CameraMode},
|
camera::{Camera, CameraMode, Dependents},
|
||||||
LodData, SceneData,
|
math, LodData, SceneData,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use anim::{
|
use anim::{
|
||||||
@ -221,56 +221,68 @@ impl FigureMgrStates {
|
|||||||
fn count_visible(&self) -> usize {
|
fn count_visible(&self) -> usize {
|
||||||
self.character_states
|
self.character_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.quadruped_small_states
|
.quadruped_small_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.quadruped_medium_states
|
.quadruped_medium_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.quadruped_low_states
|
.quadruped_low_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.bird_medium_states
|
.bird_medium_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.critter_states
|
.critter_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
|
.count()
|
||||||
|
+ self
|
||||||
|
.dragon_states
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self.dragon_states.iter().filter(|(_, c)| c.visible).count()
|
|
||||||
+ self
|
+ self
|
||||||
.fish_medium_states
|
.fish_medium_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.bird_small_states
|
.bird_small_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.fish_small_states
|
.fish_small_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self
|
+ self
|
||||||
.biped_large_states
|
.biped_large_states
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, c)| c.visible)
|
.filter(|(_, c)| c.visible())
|
||||||
|
.count()
|
||||||
|
+ self
|
||||||
|
.golem_states
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, c)| c.visible())
|
||||||
|
.count()
|
||||||
|
+ self
|
||||||
|
.object_states
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, c)| c.visible())
|
||||||
.count()
|
.count()
|
||||||
+ self.golem_states.iter().filter(|(_, c)| c.visible).count()
|
|
||||||
+ self.object_states.iter().filter(|(_, c)| c.visible).count()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,6 +416,8 @@ impl FigureMgr {
|
|||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
scene_data: &SceneData,
|
scene_data: &SceneData,
|
||||||
|
// Visible chunk data.
|
||||||
|
visible_psr_bounds: math::Aabr<f32>,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
) -> Aabb<f32> {
|
) -> Aabb<f32> {
|
||||||
let state = scene_data.state;
|
let state = scene_data.state;
|
||||||
@ -413,6 +427,81 @@ impl FigureMgr {
|
|||||||
let view_distance = scene_data.view_distance;
|
let view_distance = scene_data.view_distance;
|
||||||
let dt = state.get_delta_time();
|
let dt = state.get_delta_time();
|
||||||
let frustum = camera.frustum();
|
let frustum = camera.frustum();
|
||||||
|
|
||||||
|
// Sun shadows--find the bounding box of the shadow map plane (i.e. the bounds
|
||||||
|
// of the image rendered from the light). If the position projected
|
||||||
|
// with the ray_mat matrix is valid, and shadows are otherwise enabled,
|
||||||
|
// we mark can_shadow.
|
||||||
|
let can_shadow_sun = {
|
||||||
|
let ray_direction = scene_data.get_sun_dir();
|
||||||
|
let is_daylight = ray_direction.z < 0.0/*0.6*/;
|
||||||
|
// Are shadows enabled at all?
|
||||||
|
let can_shadow_sun = renderer.render_mode().shadow.is_map() && is_daylight;
|
||||||
|
let Dependents {
|
||||||
|
proj_mat,
|
||||||
|
view_mat,
|
||||||
|
cam_pos,
|
||||||
|
} = camera.dependents();
|
||||||
|
let cam_pos = math::Vec3::from(cam_pos);
|
||||||
|
let ray_direction = math::Vec3::from(ray_direction);
|
||||||
|
|
||||||
|
// Transform (semi) world space to light space.
|
||||||
|
let ray_mat: math::Mat4<f32> =
|
||||||
|
math::Mat4::look_at_rh(cam_pos, cam_pos + ray_direction, math::Vec3::up());
|
||||||
|
let focus_off = math::Vec3::from(camera.get_focus_pos().map(f32::trunc));
|
||||||
|
/* let visible_bounding_box = Aabb {
|
||||||
|
min: visible_bounding_box.min - focus_off,
|
||||||
|
max: visible_bounding_box.max - focus_off,
|
||||||
|
};
|
||||||
|
let visible_bounds_fine = math::Aabb::<f64> {
|
||||||
|
min: math::Vec3::from(visible_bounding_box.min.map(f64::from)),
|
||||||
|
max: math::Vec3::from(visible_bounding_box.max.map(f64::from)),
|
||||||
|
};
|
||||||
|
let inv_proj_view = math::Mat4::from_col_arrays(
|
||||||
|
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(),
|
||||||
|
)
|
||||||
|
.map(f64::from)
|
||||||
|
.inverted();
|
||||||
|
let visible_light_volume = math::calc_focused_light_volume_points(
|
||||||
|
inv_proj_view,
|
||||||
|
ray_direction.map(f64::from),
|
||||||
|
visible_bounds_fine,
|
||||||
|
1e-6,
|
||||||
|
)
|
||||||
|
.map(|v| v.map(|e| e as f32));
|
||||||
|
// Now that the work that requires high accuracy is done, switch from focus-relative
|
||||||
|
// to proper world space coordinates.
|
||||||
|
let visible_bounds = math::Aabr::from(math::fit_psr(
|
||||||
|
ray_mat,
|
||||||
|
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
|
||||||
|
visible_light_volume,
|
||||||
|
|p| p, //math::Vec3::from(p), /* / p.w */
|
||||||
|
)); */
|
||||||
|
let ray_mat = ray_mat * math::Mat4::translation_3d(-focus_off);
|
||||||
|
|
||||||
|
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| {
|
||||||
|
a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
|
||||||
|
};
|
||||||
|
// println!("Aabr: {:?}", visible_bounds);
|
||||||
|
move |pos: Pos, radius: f32| {
|
||||||
|
// Short circuit when there are no shadows to cast.
|
||||||
|
if !can_shadow_sun {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// First project center onto shadow map.
|
||||||
|
let center = (ray_mat * math::Vec4::new(pos.0.x, pos.0.y, pos.0.z, 1.0)).xy();
|
||||||
|
// Then, create an approximate bounding box (± radius).
|
||||||
|
let figure_box = math::Aabr {
|
||||||
|
min: center - radius,
|
||||||
|
max: center + radius,
|
||||||
|
};
|
||||||
|
// println!("center: {:?}, radius: {:?}", center, figure_box);
|
||||||
|
// Quick intersection test for membership in the PSC (potential shader caster)
|
||||||
|
// list.
|
||||||
|
collides_with_aabr(figure_box, visible_psr_bounds)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Get player position.
|
// Get player position.
|
||||||
let player_pos = ecs
|
let player_pos = ecs
|
||||||
.read_storage::<Pos>()
|
.read_storage::<Pos>()
|
||||||
@ -467,6 +556,7 @@ impl FigureMgr {
|
|||||||
// TODO: Investigate passing the velocity into the shader so we can at least
|
// TODO: Investigate passing the velocity into the shader so we can at least
|
||||||
// interpolate motion
|
// interpolate motion
|
||||||
const MIN_PERFECT_RATE_DIST: f32 = 50.0;
|
const MIN_PERFECT_RATE_DIST: f32 = 50.0;
|
||||||
|
|
||||||
if (i as u64 + tick)
|
if (i as u64 + tick)
|
||||||
% (1 + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25)
|
% (1 + ((pos.0.distance_squared(camera.get_focus_pos()).powf(0.25)
|
||||||
- MIN_PERFECT_RATE_DIST.powf(0.5))
|
- MIN_PERFECT_RATE_DIST.powf(0.5))
|
||||||
@ -477,6 +567,13 @@ impl FigureMgr {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether we could have been shadowing last frame.
|
||||||
|
let mut state = self.states.get_mut(body, &entity);
|
||||||
|
let can_shadow_prev = state
|
||||||
|
.as_mut()
|
||||||
|
.map(|state| state.can_shadow_sun())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
// Don't process figures outside the vd
|
// Don't process figures outside the vd
|
||||||
let vd_frac = Vec2::from(pos.0 - player_pos)
|
let vd_frac = Vec2::from(pos.0 - player_pos)
|
||||||
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| {
|
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| {
|
||||||
@ -484,15 +581,17 @@ impl FigureMgr {
|
|||||||
})
|
})
|
||||||
.magnitude()
|
.magnitude()
|
||||||
/ view_distance as f32;
|
/ view_distance as f32;
|
||||||
|
|
||||||
// Keep from re-adding/removing entities on the border of the vd
|
// Keep from re-adding/removing entities on the border of the vd
|
||||||
if vd_frac > 1.2 {
|
if vd_frac > 1.2 {
|
||||||
self.states.remove(body, &entity);
|
self.states.remove(body, &entity);
|
||||||
continue;
|
continue;
|
||||||
} else if vd_frac > 1.0 {
|
} else if vd_frac > 1.0 {
|
||||||
self.states
|
state.as_mut().map(|state| state.visible = false);
|
||||||
.get_mut(body, &entity)
|
// Keep processing if this might be a shadow caster.
|
||||||
.map(|state| state.visible = false);
|
if !can_shadow_prev {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't display figures outside the frustum spectrum (this is important to do
|
// Don't display figures outside the frustum spectrum (this is important to do
|
||||||
@ -502,22 +601,25 @@ impl FigureMgr {
|
|||||||
// shadow correctly until their next update. For now, we treat this
|
// shadow correctly until their next update. For now, we treat this
|
||||||
// as an acceptable tradeoff.
|
// as an acceptable tradeoff.
|
||||||
let radius = scale.unwrap_or(&Scale(1.0)).0 * 2.0;
|
let radius = scale.unwrap_or(&Scale(1.0)).0 * 2.0;
|
||||||
let (in_frustum, lpindex) = if let Some(mut meta) = self.states.get_mut(body, &entity) {
|
let (in_frustum, lpindex) = if let Some(mut meta) = state {
|
||||||
let (in_frustum, lpindex) = BoundingSphere::new(pos.0.into_array(), radius)
|
let (in_frustum, lpindex) = BoundingSphere::new(pos.0.into_array(), radius)
|
||||||
.coherent_test_against_frustum(frustum, meta.lpindex);
|
.coherent_test_against_frustum(frustum, meta.lpindex);
|
||||||
meta.visible = in_frustum;
|
meta.visible = in_frustum;
|
||||||
meta.lpindex = lpindex;
|
meta.lpindex = lpindex;
|
||||||
|
if in_frustum {
|
||||||
|
// Update visible bounds.
|
||||||
|
visible_aabb.expand_to_contain(Aabb {
|
||||||
|
min: pos.0 - radius,
|
||||||
|
max: pos.0 + radius,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Check whether we can shadow.
|
||||||
|
meta.can_shadow_sun = can_shadow_sun(pos, radius);
|
||||||
|
}
|
||||||
(in_frustum, lpindex)
|
(in_frustum, lpindex)
|
||||||
} else {
|
} else {
|
||||||
(true, 0)
|
(true, 0)
|
||||||
};
|
};
|
||||||
if in_frustum {
|
|
||||||
// Update visible bounds.
|
|
||||||
visible_aabb.expand_to_contain(Aabb {
|
|
||||||
min: pos.0 - radius,
|
|
||||||
max: pos.0 + radius,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change in health as color!
|
// Change in health as color!
|
||||||
let col = stats
|
let col = stats
|
||||||
@ -1839,7 +1941,7 @@ impl FigureMgr {
|
|||||||
false,
|
false,
|
||||||
pos.0,
|
pos.0,
|
||||||
figure_lod_render_distance,
|
figure_lod_render_distance,
|
||||||
|state| state.visible,
|
|state| state.can_shadow_sun(),
|
||||||
) {
|
) {
|
||||||
renderer.render_figure_shadow_directed(
|
renderer.render_figure_shadow_directed(
|
||||||
model,
|
model,
|
||||||
@ -1900,7 +2002,7 @@ impl FigureMgr {
|
|||||||
false,
|
false,
|
||||||
pos.0,
|
pos.0,
|
||||||
figure_lod_render_distance,
|
figure_lod_render_distance,
|
||||||
|state| state.visible,
|
|state| state.visible(),
|
||||||
) {
|
) {
|
||||||
renderer.render_figure(
|
renderer.render_figure(
|
||||||
model,
|
model,
|
||||||
@ -1964,7 +2066,7 @@ impl FigureMgr {
|
|||||||
true,
|
true,
|
||||||
pos.0,
|
pos.0,
|
||||||
figure_lod_render_distance,
|
figure_lod_render_distance,
|
||||||
|state| state.visible,
|
|state| state.visible(),
|
||||||
) {
|
) {
|
||||||
renderer.render_player(
|
renderer.render_player(
|
||||||
model,
|
model,
|
||||||
@ -2160,40 +2262,46 @@ impl FigureMgr {
|
|||||||
.0,
|
.0,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
Body::BirdMedium(_) => bird_medium_states.get(&entity).map(move |state| {
|
Body::BirdMedium(_) => bird_medium_states
|
||||||
(
|
.get(&entity)
|
||||||
state.locals(),
|
.filter(|state| filter_state(&*state))
|
||||||
state.bone_consts(),
|
.map(move |state| {
|
||||||
&bird_medium_model_cache
|
(
|
||||||
.get_or_create_model(
|
state.locals(),
|
||||||
renderer,
|
state.bone_consts(),
|
||||||
col_lights,
|
&bird_medium_model_cache
|
||||||
*body,
|
.get_or_create_model(
|
||||||
loadout,
|
renderer,
|
||||||
tick,
|
col_lights,
|
||||||
player_camera_mode,
|
*body,
|
||||||
character_state,
|
loadout,
|
||||||
)
|
tick,
|
||||||
.0,
|
player_camera_mode,
|
||||||
)
|
character_state,
|
||||||
}),
|
)
|
||||||
Body::FishMedium(_) => fish_medium_states.get(&entity).map(move |state| {
|
.0,
|
||||||
(
|
)
|
||||||
state.locals(),
|
}),
|
||||||
state.bone_consts(),
|
Body::FishMedium(_) => fish_medium_states
|
||||||
&fish_medium_model_cache
|
.get(&entity)
|
||||||
.get_or_create_model(
|
.filter(|state| filter_state(&*state))
|
||||||
renderer,
|
.map(move |state| {
|
||||||
col_lights,
|
(
|
||||||
*body,
|
state.locals(),
|
||||||
loadout,
|
state.bone_consts(),
|
||||||
tick,
|
&fish_medium_model_cache
|
||||||
player_camera_mode,
|
.get_or_create_model(
|
||||||
character_state,
|
renderer,
|
||||||
)
|
col_lights,
|
||||||
.0,
|
*body,
|
||||||
)
|
loadout,
|
||||||
}),
|
tick,
|
||||||
|
player_camera_mode,
|
||||||
|
character_state,
|
||||||
|
)
|
||||||
|
.0,
|
||||||
|
)
|
||||||
|
}),
|
||||||
Body::Critter(_) => critter_states
|
Body::Critter(_) => critter_states
|
||||||
.get(&entity)
|
.get(&entity)
|
||||||
.filter(|state| filter_state(&*state))
|
.filter(|state| filter_state(&*state))
|
||||||
@ -2490,11 +2598,21 @@ pub struct FigureStateMeta {
|
|||||||
state_time: f64,
|
state_time: f64,
|
||||||
last_ori: Vec3<f32>,
|
last_ori: Vec3<f32>,
|
||||||
lpindex: u8,
|
lpindex: u8,
|
||||||
|
can_shadow_sun: bool,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
last_pos: Option<Vec3<f32>>,
|
last_pos: Option<Vec3<f32>>,
|
||||||
avg_vel: Vec3<f32>,
|
avg_vel: Vec3<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FigureStateMeta {
|
||||||
|
pub fn visible(&self) -> bool { self.visible }
|
||||||
|
|
||||||
|
pub fn can_shadow_sun(&self) -> bool {
|
||||||
|
// Either visible, or explicitly a shadow caster.
|
||||||
|
self.visible || self.can_shadow_sun
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FigureState<S> {
|
pub struct FigureState<S> {
|
||||||
meta: FigureStateMeta,
|
meta: FigureStateMeta,
|
||||||
skeleton: S,
|
skeleton: S,
|
||||||
@ -2525,6 +2643,7 @@ impl<S: Skeleton> FigureState<S> {
|
|||||||
last_ori: Vec3::zero(),
|
last_ori: Vec3::zero(),
|
||||||
lpindex: 0,
|
lpindex: 0,
|
||||||
visible: false,
|
visible: false,
|
||||||
|
can_shadow_sun: false,
|
||||||
last_pos: None,
|
last_pos: None,
|
||||||
avg_vel: Vec3::zero(),
|
avg_vel: Vec3::zero(),
|
||||||
},
|
},
|
||||||
|
@ -41,8 +41,8 @@ const NUM_DIRECTED_LIGHTS: usize = 1;
|
|||||||
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
|
||||||
/* /// The minimum sin γ we will use before switching to uniform mapping.
|
/// The minimum sin γ we will use before switching to uniform mapping.
|
||||||
const EPSILON_GAMMA: f64 = 0.25; */
|
const EPSILON_UPSILON: f64 = -1.0;
|
||||||
|
|
||||||
// const NEAR_PLANE: f32 = 0.5;
|
// const NEAR_PLANE: f32 = 0.5;
|
||||||
// const FAR_PLANE: f32 = 100000.0;
|
// const FAR_PLANE: f32 = 100000.0;
|
||||||
@ -178,15 +178,37 @@ fn compute_scalar_fov<F: Float>(_near_plane: F, fov: F, aspect: F) -> F {
|
|||||||
/// -1 + (η_b + 1)(1 + cos(90 (γ - γ_a)/(γ_b - γ_a))) γ_a ≤ γ < γ_b
|
/// -1 + (η_b + 1)(1 + cos(90 (γ - γ_a)/(γ_b - γ_a))) γ_a ≤ γ < γ_b
|
||||||
/// η_b + (η_c - η_b) sin(90 (γ - γ_b)/(γ_c - γ_b)) γ_b ≤ γ < γ_c
|
/// η_b + (η_c - η_b) sin(90 (γ - γ_b)/(γ_c - γ_b)) γ_b ≤ γ < γ_c
|
||||||
/// η_c γ_c ≤ γ
|
/// η_c γ_c ≤ γ
|
||||||
|
///
|
||||||
|
/// NOTE: Equation's described behavior is *wrong!* I have pieced together a
|
||||||
|
/// slightly different function that seems to more closely satisfy the author's
|
||||||
|
/// intent:
|
||||||
|
///
|
||||||
|
/// η =
|
||||||
|
/// -1 γ < γ_a
|
||||||
|
/// -1 + (η_b + 1) (γ - γ_a)/(γ_b - γ_a) γ_a ≤ γ < γ_b
|
||||||
|
/// η_b + (η_c - η_b) sin(90 (γ - γ_b)/(γ_c - γ_b)) γ_b ≤ γ < γ_c
|
||||||
|
/// η_c γ_c ≤ γ
|
||||||
|
///
|
||||||
|
/// There are other alternatives that may have more desirable properties, such
|
||||||
|
/// as:
|
||||||
|
///
|
||||||
|
/// η =
|
||||||
|
/// -1 γ < γ_a
|
||||||
|
/// -1 + (η_b + 1)(1 - cos(90 (γ - γ_a)/(γ_b - γ_a))) γ_a ≤ γ < γ_b
|
||||||
|
/// η_b + (η_c - η_b) sin(90 (γ - γ_b)/(γ_c - γ_b)) γ_b ≤ γ < γ_c
|
||||||
|
/// η_c γ_c ≤ γ
|
||||||
fn compute_warping_parameter<F: Float + FloatConst>(
|
fn compute_warping_parameter<F: Float + FloatConst>(
|
||||||
gamma: F,
|
gamma: F,
|
||||||
(gamma_a, gamma_b, gamma_c): (F, F, F),
|
(gamma_a, gamma_b, gamma_c): (F, F, F),
|
||||||
(eta_b, eta_c): (F, F),
|
(eta_b, eta_c): (F, F),
|
||||||
) -> F {
|
) -> F {
|
||||||
if gamma < gamma_a {
|
if gamma < gamma_a {
|
||||||
F::zero()
|
-F::one()
|
||||||
|
/* F::zero() */
|
||||||
} else if gamma_a <= gamma && gamma < gamma_b {
|
} else if gamma_a <= gamma && gamma < gamma_b {
|
||||||
-F::one() + (eta_b + F::one()) * (F::one() + (F::FRAC_PI_2() * (gamma - gamma_a) / (gamma_b - gamma_a)).cos())
|
/* -F::one() + (eta_b + F::one()) * (F::one() + (F::FRAC_PI_2() * (gamma - gamma_a) / (gamma_b - gamma_a)).cos()) */
|
||||||
|
-F::one() + (eta_b + F::one()) * (F::one() - (F::FRAC_PI_2() * (gamma - gamma_a) / (gamma_b - gamma_a)).cos())
|
||||||
|
// -F::one() + (eta_b + F::one()) * ((gamma - gamma_a) / (gamma_b - gamma_a))
|
||||||
} else if gamma_b <= gamma && gamma < gamma_c {
|
} else if gamma_b <= gamma && gamma < gamma_c {
|
||||||
eta_b + (eta_c - eta_b) * (F::FRAC_PI_2() * (gamma - gamma_b) / (gamma_c - gamma_b)).sin()
|
eta_b + (eta_c - eta_b) * (F::FRAC_PI_2() * (gamma - gamma_b) / (gamma_c - gamma_b)).sin()
|
||||||
} else {
|
} else {
|
||||||
@ -227,7 +249,7 @@ fn compute_warping_parameter_perspective<F: Float + FloatConst>(
|
|||||||
theta,
|
theta,
|
||||||
theta + (three / ten) * (F::FRAC_PI_2() - theta),
|
theta + (three / ten) * (F::FRAC_PI_2() - theta),
|
||||||
),
|
),
|
||||||
(-two / ten, F::zero()),
|
(-two/*F::one()*/ / ten, F::zero()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,7 +568,11 @@ impl Scene {
|
|||||||
self.lod.maintain(renderer, time_of_day);
|
self.lod.maintain(renderer, time_of_day);
|
||||||
|
|
||||||
// Maintain the terrain.
|
// Maintain the terrain.
|
||||||
let (_scene_bounds, visible_bounds, _psc_bounds) = self.terrain.maintain(
|
let (
|
||||||
|
/* _scene_bounds, visible_bounds, _psc_bounds */ visible_bounds,
|
||||||
|
visible_light_volume,
|
||||||
|
visible_psr_bounds,
|
||||||
|
) = self.terrain.maintain(
|
||||||
renderer,
|
renderer,
|
||||||
&scene_data,
|
&scene_data,
|
||||||
focus_pos,
|
focus_pos,
|
||||||
@ -556,7 +582,9 @@ impl Scene {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Maintain the figures.
|
// Maintain the figures.
|
||||||
let _figure_bounds = self.figure_mgr.maintain(renderer, scene_data, &self.camera);
|
let _figure_bounds =
|
||||||
|
self.figure_mgr
|
||||||
|
.maintain(renderer, scene_data, visible_psr_bounds, &self.camera);
|
||||||
|
|
||||||
let sun_dir = scene_data.get_sun_dir();
|
let sun_dir = scene_data.get_sun_dir();
|
||||||
let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
||||||
@ -570,7 +598,7 @@ impl Scene {
|
|||||||
}; */
|
}; */
|
||||||
|
|
||||||
// let focus_frac = focus_pos.map(|e| e.fract());
|
// let focus_frac = focus_pos.map(|e| e.fract());
|
||||||
let visible_bounds = math::Aabb::<f32> {
|
/* let visible_bounds = math::Aabb::<f32> {
|
||||||
min: math::Vec3::from(visible_bounds.min - focus_off),
|
min: math::Vec3::from(visible_bounds.min - focus_off),
|
||||||
max: math::Vec3::from(visible_bounds.max - focus_off),
|
max: math::Vec3::from(visible_bounds.max - focus_off),
|
||||||
};
|
};
|
||||||
@ -598,7 +626,7 @@ impl Scene {
|
|||||||
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(),
|
(proj_mat * view_mat/* * Mat4::translation_3d(-focus_off)*/).into_col_arrays(),
|
||||||
)
|
)
|
||||||
.map(f64::from)
|
.map(f64::from)
|
||||||
.inverted();
|
.inverted(); */
|
||||||
|
|
||||||
let fov = self.camera.get_fov();
|
let fov = self.camera.get_fov();
|
||||||
let aspect_ratio = self.camera.get_aspect_ratio();
|
let aspect_ratio = self.camera.get_aspect_ratio();
|
||||||
@ -620,11 +648,11 @@ impl Scene {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
// println!("light_volume: {:?}", light_volume); */
|
// println!("light_volume: {:?}", light_volume); */
|
||||||
// let visible_light_volume = light_volume.clone();
|
// let visible_light_volume = light_volume.clone();
|
||||||
let visible_light_volume = math::calc_focused_light_volume_points(inv_proj_view, directed_light_dir.map(f64::from), visible_bounds_fine, 1e-6)
|
/* let visible_light_volume = math::calc_focused_light_volume_points(inv_proj_view, directed_light_dir.map(f64::from), visible_bounds_fine, 1e-6)
|
||||||
// .map(|e| e - focus_off)
|
// .map(|e| e - focus_off)
|
||||||
// NOTE: Hopefully not out of bounds.
|
// NOTE: Hopefully not out of bounds.
|
||||||
.map(|v| v.map(|e| e as f32))
|
.map(|v| v.map(|e| e as f32))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>(); */
|
||||||
// println!("visible_light_volume: {:?}", visible_light_volume);
|
// println!("visible_light_volume: {:?}", visible_light_volume);
|
||||||
// let bounds0 = fit_psr(Mat4::identity()/* * inverse_visible*/,
|
// let bounds0 = fit_psr(Mat4::identity()/* * inverse_visible*/,
|
||||||
// light_volume.iter().copied(), |p| Vec3::from(p) / p.w);
|
// light_volume.iter().copied(), |p| Vec3::from(p) / p.w);
|
||||||
@ -695,19 +723,20 @@ impl Scene {
|
|||||||
// let look_at = bounds0.center();//Vec3::zero();//
|
// let look_at = bounds0.center();//Vec3::zero();//
|
||||||
// scene_bounds.center();//Vec3::zero(); let look_at =
|
// scene_bounds.center();//Vec3::zero(); let look_at =
|
||||||
// bounds0.center();
|
// bounds0.center();
|
||||||
let look_at = math::Vec3::from(cam_pos); // /*Vec3::zero()*/scene_bounds.center()/*cam_pos*/;// - focus_off;// focus_off;
|
let look_at = /*Vec3::zero()*/math::Vec3::from(cam_pos); // /*Vec3::zero()*/scene_bounds.center()/*cam_pos*/;// - focus_off;// focus_off;
|
||||||
let _light_scale = 1.5 * /*(directed_near + directed_far) / 2.0*/radius;
|
let _light_scale = 1.5 * /*(directed_near + directed_far) / 2.0*/radius;
|
||||||
// We upload view matrices as well, to assist in linearizing vertex positions.
|
// We upload view matrices as well, to assist in linearizing vertex positions.
|
||||||
// (only for directional lights, so far).
|
// (only for directional lights, so far).
|
||||||
let mut directed_shadow_mats = Vec::with_capacity(6);
|
let mut directed_shadow_mats = Vec::with_capacity(6);
|
||||||
let new_dir = math::Vec3::from(view_dir);
|
let new_dir = math::Vec3::from(view_dir);
|
||||||
// let new_dir: Vec3<f32> = light_volume/*visible_light_volume*/.iter().map(|p|
|
// let new_dir: math::Vec3::<_> =
|
||||||
// p - cam_pos).sum();
|
// /*light_volume*/visible_light_volume.iter().copied().map(math::Vec3::from).
|
||||||
|
// map(|p| p - look_at).sum();
|
||||||
let new_dir = new_dir.normalized();
|
let new_dir = new_dir.normalized();
|
||||||
/* let dot_prod = f64::from(directed_light_dir.dot(new_dir));
|
/* let cos_gamma = f64::from(directed_light_dir.dot(new_dir));
|
||||||
let sin_gamma = (1.0 - dot_prod * dot_prod).sqrt();
|
let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt();
|
||||||
// let sin_gamma = 0.0;
|
// let sin_gamma = 0.0;
|
||||||
let new_dir = if /*sin_gamma > EPISLON_GAMMA*/factor != -1.0 {
|
let new_dir = if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON {
|
||||||
new_dir
|
new_dir
|
||||||
} else {
|
} else {
|
||||||
// For uniform mapping, align shadow map t axis with viewer's y axis to maximize
|
// For uniform mapping, align shadow map t axis with viewer's y axis to maximize
|
||||||
@ -746,9 +775,12 @@ impl Scene {
|
|||||||
.scaled_3d(Vec3::new(proj_mat[(0, 0)], proj_mat[(1, 1)], 1.0));
|
.scaled_3d(Vec3::new(proj_mat[(0, 0)], proj_mat[(1, 1)], 1.0));
|
||||||
let focus_off = focus_pos.map(|e| e.trunc()); */
|
let focus_off = focus_pos.map(|e| e.trunc()); */
|
||||||
let z_n = 1.0; //f64::from(camera::NEAR_PLANE);
|
let z_n = 1.0; //f64::from(camera::NEAR_PLANE);
|
||||||
let _z_f = f64::from(camera::FAR_PLANE);
|
let z_f = f64::from(camera::FAR_PLANE);
|
||||||
let _scalar_fov = f64::from(fov / 2.0); // compute_scalar_fov(z_n, f64::from(fov), f64::from(aspect_ratio));
|
let scalar_fov = /*f64::from(fov / 2.0)*/compute_scalar_fov(z_n, f64::from(fov), f64::from(aspect_ratio));
|
||||||
shadow_mats.extend(directed_shadow_mats.iter().map(move |&light_view_mat| {
|
shadow_mats.extend(directed_shadow_mats.iter().enumerate().map(move |(idx, &light_view_mat)| {
|
||||||
|
if idx >= NUM_DIRECTED_LIGHTS {
|
||||||
|
return ShadowLocals::new(Mat4::identity(), Mat4::identity());
|
||||||
|
}
|
||||||
/* let visible_light_volume = {
|
/* let visible_light_volume = {
|
||||||
let light_view_mat = light_view_mat.map(f64::from);
|
let light_view_mat = light_view_mat.map(f64::from);
|
||||||
// (See http://www.songho.ca/opengl/gl_normaltransform.html)
|
// (See http://www.songho.ca/opengl/gl_normaltransform.html)
|
||||||
@ -873,13 +905,22 @@ impl Scene {
|
|||||||
//
|
//
|
||||||
let mut e_p: Vec3<f32> = Vec3::zero();
|
let mut e_p: Vec3<f32> = Vec3::zero();
|
||||||
v_p.z = 0.0; */
|
v_p.z = 0.0; */
|
||||||
let mut v_p = math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir));
|
let v_p_orig = math::Vec3::from(light_view_mat * math::Vec4::from_direction(new_dir));
|
||||||
v_p.normalize();
|
let mut v_p = v_p_orig.normalized();
|
||||||
// let dot_prod = f64::from(v_p.z);
|
// let cos_gamma = f64::from(v_p.z);
|
||||||
let dot_prod = new_dir.map(f64::from).dot(directed_light_dir.map(f64::from));
|
let cos_gamma = new_dir.map(f64::from).dot(directed_light_dir.map(f64::from));
|
||||||
let sin_gamma = (1.0 - dot_prod * dot_prod).sqrt();
|
let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt();
|
||||||
let gamma = sin_gamma.asin();
|
let gamma = sin_gamma.asin()/*cos_gamma.acos()*/;
|
||||||
let factor = compute_warping_parameter_perspective(gamma, f64::from(camera::NEAR_PLANE), f64::from(fov), f64::from(aspect_ratio));
|
let bounds1 = math::fit_psr(view_mat, visible_light_volume.iter().copied(), math::Vec4::homogenized);
|
||||||
|
let n_e = f64::from(-bounds1.max.z);
|
||||||
|
// let f_e = f64::from(-bounds1.min.z);
|
||||||
|
// let fov = 2.0 * aspect_ratio * (fov / 2.0).tan();
|
||||||
|
let factor = compute_warping_parameter_perspective(gamma, /*f64::from(camera::NEAR_PLANE)*/n_e, f64::from(/*fov*//*50.0.to_radians()*/fov/* / 2.0*/), f64::from(aspect_ratio));
|
||||||
|
/* if v_p.z > 0.5 {
|
||||||
|
-1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}; */
|
||||||
/* let factor = if factor > 0.0 {
|
/* let factor = if factor > 0.0 {
|
||||||
-1.0
|
-1.0
|
||||||
} else {
|
} else {
|
||||||
@ -888,7 +929,7 @@ impl Scene {
|
|||||||
|
|
||||||
v_p.z = 0.0;
|
v_p.z = 0.0;
|
||||||
v_p.normalize();
|
v_p.normalize();
|
||||||
let l_r: math::Mat4<f32> = if /*v_p.magnitude_squared() > 1e-3*//*sin_gamma > EPISLON_GAMMA*/factor != -1.0 {
|
let l_r: math::Mat4<f32> = if /*v_p.magnitude_squared() > 1e-3*//*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON {
|
||||||
math::Mat4::look_at_rh(math::Vec3::zero(), math::Vec3::forward_rh(), v_p)
|
math::Mat4::look_at_rh(math::Vec3::zero(), math::Vec3::forward_rh(), v_p)
|
||||||
} else {
|
} else {
|
||||||
math::Mat4::identity()
|
math::Mat4::identity()
|
||||||
@ -902,8 +943,8 @@ impl Scene {
|
|||||||
// let l_r: Mat4<f32> = Mat4::look_at_rh(/*Vec3::from(e_p) - Vec3::from(v_p)*/Vec3::zero(), /*Vec3::from(e_p)*/-Vec3::forward_rh(), /*Vec3::up()*/-Vec3::from(v_p));
|
// let l_r: Mat4<f32> = Mat4::look_at_rh(/*Vec3::from(e_p) - Vec3::from(v_p)*/Vec3::zero(), /*Vec3::from(e_p)*/-Vec3::forward_rh(), /*Vec3::up()*/-Vec3::from(v_p));
|
||||||
// let l_r: Mat4<f32> = Mat4::look_at_rh(/*Vec3::from(e_p) - Vec3::from(v_p)*/Vec3::back_rh(), /*Vec3::from(e_p)*/Vec3::zero(), /*Vec3::up()*/Vec3::from(v_p));
|
// let l_r: Mat4<f32> = Mat4::look_at_rh(/*Vec3::from(e_p) - Vec3::from(v_p)*/Vec3::back_rh(), /*Vec3::from(e_p)*/Vec3::zero(), /*Vec3::up()*/Vec3::from(v_p));
|
||||||
// let l_r: Mat4<f32> = Mat4::identity();
|
// let l_r: Mat4<f32> = Mat4::identity();
|
||||||
let bounds0 = math::fit_psr(light_view_mat, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/math::Vec4::homogenized);
|
/* let bounds0 = math::fit_psr(light_view_mat, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/math::Vec4::homogenized); */
|
||||||
let directed_proj_mat = math::Mat4::orthographic_rh_no(FrustumPlanes {
|
let directed_proj_mat = /*math::Mat4::orthographic_rh_no(FrustumPlanes {
|
||||||
// TODO: Consider adjusting resolution based on view distance.
|
// TODO: Consider adjusting resolution based on view distance.
|
||||||
left: bounds0.min.x,
|
left: bounds0.min.x,
|
||||||
right: bounds0.max.x,
|
right: bounds0.max.x,
|
||||||
@ -911,25 +952,76 @@ impl Scene {
|
|||||||
top: bounds0.max.y,
|
top: bounds0.max.y,
|
||||||
near: bounds0.min.z,
|
near: bounds0.min.z,
|
||||||
far: bounds0.max.z,
|
far: bounds0.max.z,
|
||||||
})/* /Mat4::identity() */;
|
})*//* /Mat4::identity() */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 light_all_mat = l_r * directed_proj_mat * light_view_mat;
|
||||||
// let bounds1 = fit_psr(light_all_mat/* * inverse_visible*/, light_volume.iter().copied(), |p| Vec3::from(p) / p.w);
|
// let bounds1 = fit_psr(light_all_mat/* * inverse_visible*/, light_volume.iter().copied(), |p| Vec3::from(p) / p.w);
|
||||||
let bounds0 = math::fit_psr(/*l_r*/light_all_mat/* * inverse_visible*/, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/math::Vec4::homogenized);
|
let bounds0 = math::fit_psr(/*l_r*/light_all_mat/* * inverse_visible*/, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/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;
|
||||||
|
// println!("p_x (light near plane, s-axis) = {:?}, p_y (light xy plane, t-axis) = {:?}, p_z (near plane, z-axis) = {:?}", p_x, p_y, p_z);
|
||||||
|
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 w_p_arr = solve_p0.cols.iter().map(|e| (e.x, e.y, e.z, e.w)).collect::<Vec<_>>();
|
||||||
|
// println!("mat4 solve_p0 = mat4(vec4{:?}, vec4{:?}, vec4{:?}, vec4{:?});", w_p_arr[0], w_p_arr[1], w_p_arr[2], w_p_arr[3]);
|
||||||
|
|
||||||
|
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;
|
||||||
|
// println!("p0 = {:?}, p1 = {:?}", p0, p1);
|
||||||
|
|
||||||
|
let view_from_light_mat = view_mat * light_all_inv;
|
||||||
|
let z0 = view_from_light_mat * p0;
|
||||||
|
let z1 = view_from_light_mat * p1;
|
||||||
|
// println!("z0 = {:?}, z1 = {:?}", z0, z1);
|
||||||
|
|
||||||
|
(f64::from(z0.z), f64::from(z1.z))
|
||||||
|
};
|
||||||
|
|
||||||
// let bounds1 = fit_psr(light_all_mat/* * inverse_visible*/, aabb_to_points(visible_bounds).iter().copied(), |p| Vec3::from(p) / p.w);
|
// let bounds1 = fit_psr(light_all_mat/* * inverse_visible*/, aabb_to_points(visible_bounds).iter().copied(), |p| Vec3::from(p) / p.w);
|
||||||
// let mut light_focus_pos: Vec3<f32> = Vec3::from(light_all_mat * Vec4::from_point(focus_pos.map(f32::fract)));
|
// let mut light_focus_pos: Vec3<f32> = Vec3::from(light_all_mat * Vec4::from_point(focus_pos.map(f32::fract)));
|
||||||
let mut light_focus_pos: math::Vec3<f32> = math::Vec3::zero();//bounds0.center();// l_r * directed_proj_mat * light_view_mat * Vec4::from_point(focus_pos.map(|e| e.fract()));
|
let mut light_focus_pos: math::Vec3<f32> = math::Vec3::zero()/*bounds0.center()*/;// l_r * directed_proj_mat * light_view_mat * Vec4::from_point(focus_pos.map(|e| e.fract()));
|
||||||
|
light_focus_pos.x = bounds0.center().x;
|
||||||
|
light_focus_pos.y = bounds0.min.y/*z_0 as f32*/;
|
||||||
|
light_focus_pos.z = bounds0.center().z;
|
||||||
// let mut light_focus_pos: Vec3<f32> = bounds0.center();// l_r * directed_proj_mat * light_view_mat * Vec4::from_point(focus_pos.map(|e| e.fract()));
|
// let mut light_focus_pos: Vec3<f32> = bounds0.center();// l_r * directed_proj_mat * light_view_mat * Vec4::from_point(focus_pos.map(|e| e.fract()));
|
||||||
// println!("cam_pos: {:?}, focus_pos: {:?}, light_focus_pos: {:?}, v_p: {:?} bounds: {:?}, l_r: {:?}, light_view_mat: {:?}, light_all_mat: {:?}", cam_pos, focus_pos - focus_off, light_focus_pos, v_p, /*bounds1*/bounds0, l_r, light_view_mat, light_all_mat);
|
// println!("cam_pos: {:?}, focus_pos: {:?}, light_focus_pos: {:?}, v_p: {:?} bounds: {:?}, l_r: {:?}, light_view_mat: {:?}, light_all_mat: {:?}", cam_pos, focus_pos - focus_off, light_focus_pos, v_p, /*bounds1*/bounds0, l_r, light_view_mat, light_all_mat);
|
||||||
// let w_v = Mat4::translation_3d(-Vec3::new(xmax + xmin, ymax + ymin, /*zmax + zmin*/0.0) / 2.0);
|
// let w_v = Mat4::translation_3d(-Vec3::new(xmax + xmin, ymax + ymin, /*zmax + zmin*/0.0) / 2.0);
|
||||||
|
|
||||||
// let dot_prod = /*new_dir*//*up_dir*/view_dir.map(f64::from).dot(directed_light_dir.map(f64::from));
|
// let cos_gamma = /*new_dir*//*up_dir*/view_dir.map(f64::from).dot(directed_light_dir.map(f64::from));
|
||||||
// let sin_gamma = (1.0 - dot_prod * dot_prod).sqrt();//.clamped(1e-1, 1.0);
|
// let sin_gamma = (1.0 - cos_gamma * cos_gamma).sqrt();//.clamped(1e-1, 1.0);
|
||||||
// let sin_gamma = 0.0;
|
// let sin_gamma = 0.0;
|
||||||
// let factor = -1.0;//1.0 / sin_gamma;
|
// let factor = -1.0;//1.0 / sin_gamma;
|
||||||
// println!("Warp factor for γ (sin γ = {:?}, γ = {:?}, near_plane = {:?}, fov = {:?}, scalar fov = {:?}, aspect ratio = {:?}): η = {:?}", sin_gamma, gamma.to_degrees(), camera::NEAR_PLANE, fov.to_degrees(), scalar_fov.to_degrees(), aspect_ratio, factor);
|
// println!("Warp factor for γ (sin γ = {:?}, γ = {:?}, near_plane = {:?}, fov = {:?}, scalar fov = {:?}, aspect ratio = {:?}): η = {:?}", sin_gamma, gamma.to_degrees(), camera::NEAR_PLANE, fov.to_degrees(), scalar_fov.to_degrees(), aspect_ratio, factor);
|
||||||
/* v ---l
|
/* v ---l
|
||||||
\ Θ|
|
\ Θ|
|
||||||
\| */
|
\| */
|
||||||
|
|
||||||
// let directed_near = /*0.5*//*0.25*/f64::from(camera::NEAR_PLANE);/*1.0*/;//bounds0.min.y.max(1.0);
|
// let directed_near = /*0.5*//*0.25*/f64::from(camera::NEAR_PLANE);/*1.0*/;//bounds0.min.y.max(1.0);
|
||||||
@ -938,13 +1030,53 @@ impl Scene {
|
|||||||
// let z_f = z_n + d * camera::FAR_PLANE/* / scalar_fov.cos()*/;
|
// let z_f = z_n + d * camera::FAR_PLANE/* / scalar_fov.cos()*/;
|
||||||
// let z_0 = f64::from(bounds0.min.y);
|
// let z_0 = f64::from(bounds0.min.y);
|
||||||
|
|
||||||
// Vague idea: project z_n from the camera view to the light view (where it's
|
/* let v_p_orig: math::Vec3::<f32> = math::Vec3::from(light_all_mat * math::Vec4::from_direction(new_dir));
|
||||||
// tilted by γ).
|
let n_e: f64 = /*bounds0.y.min() * scalar_fov.cos() *//*bounds0.min.y / scalar_fov.cos();*/f64::from(camera::NEAR_PLANE) * f64::from(v_p_orig.y);
|
||||||
let z_0 = z_n;// / sin_gamma;// / sin_gamma;
|
let f_e = /*bounds0.size().y / scalar_fov.cos();*//*f64::from(camera::FAR_PLANE);*//*f64::from(camera::FAR_PLANE) * v_p_orig*/
|
||||||
|
d
|
||||||
|
/*d * scalar_fov.cos()*/;
|
||||||
|
|
||||||
|
// See Lloyd's thesis, section 5.2 (p. 104-105).
|
||||||
|
let w_e = 2.0 * n_e * scalar_fov.tan();
|
||||||
|
|
||||||
|
let w_n = w_e;
|
||||||
|
// let w_f = w_n * f_e / n_e;
|
||||||
|
let w_s = (f_e - n_e) / scalar_fov.cos();
|
||||||
|
|
||||||
|
let w_n_ = w_n * gamma.cos();
|
||||||
|
let w_s_1_ = w_s * (1.0 - (scalar_fov - gamma).cos());
|
||||||
|
let w_s_2_ = w_s * (scalar_fov - gamma).sin();
|
||||||
|
|
||||||
|
/* let w_l_y = w_n_ + w_s_2_ + if gamma < scalar_fov {
|
||||||
|
w_s_1_
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}; */
|
||||||
|
let v_s_1 = if gamma < scalar_fov {
|
||||||
|
w_s_1_ / w_l_y
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
let v_s_2 = v_s_1 + w_n_ / w_l_y;
|
||||||
|
let d_e = |v: f64| n_e + (f_e - n_e) *
|
||||||
|
(w_l_y * (v_s_1 - v) / w_s_1_)
|
||||||
|
.max(0.0)
|
||||||
|
.max(w_l_y * (1.0 - v) / w_s_2_); */
|
||||||
|
|
||||||
|
/* let w_l_x = (n_ + w_l_y) * if gamma < scalar_fov {
|
||||||
|
w_f / n_
|
||||||
|
} else {
|
||||||
|
w_f / (n_ + w_s_1_)
|
||||||
|
}; */
|
||||||
|
|
||||||
|
/* let z_0 = /*z_n*//*z_n*/n_e/* / sin_gamma*/;// / sin_gamma;// / sin_gamma;
|
||||||
// let z_1 = z_0 + d;
|
// let z_1 = z_0 + d;
|
||||||
// Vague idea: project d from the light view back to the camera view (undoing the
|
// Vague idea: project d from the light view back to the camera view (undoing the
|
||||||
// tilt by γ).
|
// tilt by γ).
|
||||||
let z_1 = /*z_n*/z_0 + d * sin_gamma;
|
let z_1 = /*z_n*/z_0/*n_e*/ + d * /*sin_gamma*/f64::from(v_p_orig.y)/* * sin_gamma*/;
|
||||||
|
// 1/φ' (zn + √(zn(zn + (f - n)φ')))
|
||||||
|
// (f-n)/φ' (zn + √(zn(zn + (f - n)φ')))
|
||||||
|
// zn/φ' (1 + zn√(1 + (f - n)φ' / zn)) */
|
||||||
let w_l_y = /* z_f - z_n */d;/*/*f64::from(camera::FAR_PLANE - camera::NEAR_PLANE)*//*(z_f - z_n)*/d * scalar_fov.cos();*/
|
let w_l_y = /* z_f - z_n */d;/*/*f64::from(camera::FAR_PLANE - camera::NEAR_PLANE)*//*(z_f - z_n)*/d * scalar_fov.cos();*/
|
||||||
// let z_f = z_n + d;
|
// let z_f = z_n + d;
|
||||||
// let near_dist = directed_near;
|
// let near_dist = directed_near;
|
||||||
@ -962,6 +1094,10 @@ impl Scene {
|
|||||||
// Standard shadow map to LiSPSM
|
// Standard shadow map to LiSPSM
|
||||||
(1.0 + alpha_sqrt - factor * (alpha - 1.0)) / ((alpha - 1.0) * (factor + 1.0))
|
(1.0 + alpha_sqrt - factor * (alpha - 1.0)) / ((alpha - 1.0) * (factor + 1.0))
|
||||||
// 1+sqrt(z_f/z_n)/((z_f/z_n - 1)*2)
|
// 1+sqrt(z_f/z_n)/((z_f/z_n - 1)*2)
|
||||||
|
//
|
||||||
|
// η = 0:
|
||||||
|
// (1 + √(z₁/z₀)) / (z₁ / z₀ - 1)
|
||||||
|
// (z₀ + √(z₀z₁)) / (z₁ - z₀)
|
||||||
} else {
|
} else {
|
||||||
// LiSPSM to PSM
|
// LiSPSM to PSM
|
||||||
((alpha_sqrt - 1.0) * (factor * alpha_sqrt + 1.0)).recip()
|
((alpha_sqrt - 1.0) * (factor * alpha_sqrt + 1.0)).recip()
|
||||||
@ -969,18 +1105,40 @@ impl Scene {
|
|||||||
// = 1 / ((√α - 1)(1))
|
// = 1 / ((√α - 1)(1))
|
||||||
// = 1 / (√α - 1)
|
// = 1 / (√α - 1)
|
||||||
// = (1 + √α) / (α - 1)
|
// = (1 + √α) / (α - 1)
|
||||||
// = (a + √(z_f/z_n)) / (z_f/z_n - 1)
|
// = (1 + √(z₁/z₀)) / (z₁ / z₀ - 1)
|
||||||
};
|
};
|
||||||
// let factor = -1.0;
|
// let factor = -1.0;
|
||||||
|
// (f - n) * (1 + √(z₁/z₀) - sin γ * (z₁/z₀ - 1)) / ((z₁/z₀ - 1) * (sin γ + 1))
|
||||||
|
//
|
||||||
|
// (f - n) * (1 + √(z_f/z_n) - (-1 / sin γ) * (z_f/z_n - 1)) / ((z_f/z_n - 1) * ((-1 / sin γ) + 1))
|
||||||
|
// (f - n) * (1 + √(z_f/z_n) + 1 / sin γ * (z_f/z_n - 1)) / ((z_f/z_n - 1) * (1 - 1 / sin γ))
|
||||||
|
// (f - n) * (1 + √(z_f/z_n) + 1 / sin γ * (z_f/z_n - 1)) / ((1 / sin γ)((z_f/z_n - 1) * (sin γ - 1)))
|
||||||
|
// (f - n)sin γ * (1 + √(z_f/z_n) + 1 / sin γ * (z_f/z_n - 1)) / ((z_f/z_n - 1) * (sin γ - 1))
|
||||||
|
// (f - n)sin γ / sin γ * (sin γ + √(z_f/z_n)sin γ + (z_f/z_n - 1)) / ((z_f/z_n - 1) * (sin γ - 1))
|
||||||
|
// (f - n) * (sin γ + √(z_f/z_n)sin γ + (z_f/z_n - 1)) / ((z_f/z_n - 1) * (sin γ - 1))
|
||||||
|
// (f - n) * (sin γ + √(z_f/z_n)sin γ + (z_f/z_n - 1)) / ((1 / z_n)(z_f - z_n) * (sin γ - 1))
|
||||||
|
// (f - n)z_n * (sin γ + √(z_f/z_n)sin γ + (z_f/z_n - 1)) / ((z_f - z_n) * (sin γ - 1))
|
||||||
|
// (f - n)z_n / z_n * (z_n sin γ + √(z_f z_n)sin γ + (z_f - z_n)) / ((z_f - z_n) * (sin γ - 1))
|
||||||
|
// (f - n) (z_n sin γ + √(z_f z_n)sin γ + (z_f - z_n)) / ((z_f - z_n) * (sin γ - 1))
|
||||||
|
//
|
||||||
|
// (f - n) * (1 + √(f_e/n_e) - F * (f_e/n_e - 1)) / ((f_e/n_e - 1) * (F + 1))
|
||||||
|
// (f - n) * n_e / n_e (n_e + √(n_e * f_e) - F * (f_e - n_e)) / ((f_e - n_e) * (F + 1))
|
||||||
|
// (f - n) (n_e + √(n_e * f_e) - F * (f_e - n_e)) / ((f_e - n_e) * (F + 1))
|
||||||
|
//
|
||||||
|
// (f - n) (n_e + √(n_e * f_e) - (sin γ - 1) * (f_e - n_e)) / ((f_e - n_e) * ((sin γ - 1) + 1))
|
||||||
|
// (f - n) (n_e + √(n_e * f_e) - (f_e - n_e) sin γ + f_e - n_e) / ((f_e - n_e) * sin γ)
|
||||||
|
// (f - n) (√(n_e * f_e) - (f_e - n_e) sin γ + f_e) / ((f_e - n_e) * sin γ)
|
||||||
|
|
||||||
// Equation 5.14 - 5.16
|
// Equation 5.14 - 5.16
|
||||||
// let directed_near_normal = 1.0 / d * (z_0 + (z_0 * z_1).sqrt());
|
// let directed_near_normal = 1.0 / d * (z_0 + (z_0 * z_1).sqrt());
|
||||||
// let directed_near = w_l_y / d * (z_0 + (z_0 * z_1).sqrt());
|
// let directed_near = w_l_y / d * (z_0 + (z_0 * z_1).sqrt());
|
||||||
/* let directed_near = directed_near_normal as f32;
|
/* let directed_near = directed_near_normal as f32;
|
||||||
let directed_far = (directed_near_normal + d) as f32; */
|
let directed_far = (directed_near_normal + d) as f32; */
|
||||||
let directed_near = (w_l_y * directed_near_normal).abs() as f32;
|
let y_ = |v: f64| w_l_y * (v + directed_near_normal).abs();
|
||||||
let directed_far = (w_l_y * (directed_near_normal + 1.0)).abs() as f32;
|
let directed_near = y_(0.0) as f32;// (w_l_y * directed_near_normal).abs() as f32;
|
||||||
let (directed_near, directed_far) = (directed_near.min(directed_far), directed_near.max(directed_far));
|
let directed_far = y_(1.0) as f32;// (w_l_y * (directed_near_normal + 1.0)).abs() as f32;
|
||||||
|
/* let directed_far = (w_l_y * (directed_near_normal + 1.0)).abs() as f32;
|
||||||
|
let (directed_near, directed_far) = (directed_near.min(directed_far), directed_near.max(directed_far)); */
|
||||||
// let directed_near = w_l_y / d * (z_0 + (z_0 * z_1).sqrt());
|
// let directed_near = w_l_y / d * (z_0 + (z_0 * z_1).sqrt());
|
||||||
// println!("θ = {:?} η = {:?} z_n = {:?} z_f = {:?} γ = {:?} d = {:?} z_0 = {:?} z_1 = {:?} w_l_y: {:?} α = {:?} √α = {:?} n'₀ = {:?} n' = {:?} f' = {:?}", scalar_fov.to_degrees(), factor, z_n, z_f, gamma.to_degrees(), d, z_0, z_1, w_l_y, alpha, alpha_sqrt, directed_near_normal, directed_near, directed_far);
|
// println!("θ = {:?} η = {:?} z_n = {:?} z_f = {:?} γ = {:?} d = {:?} z_0 = {:?} z_1 = {:?} w_l_y: {:?} α = {:?} √α = {:?} n'₀ = {:?} n' = {:?} f' = {:?}", scalar_fov.to_degrees(), factor, z_n, z_f, gamma.to_degrees(), d, z_0, z_1, w_l_y, alpha, alpha_sqrt, directed_near_normal, directed_near, directed_far);
|
||||||
|
|
||||||
@ -990,7 +1148,7 @@ impl Scene {
|
|||||||
/* // let directed_near = 1.0;
|
/* // let directed_near = 1.0;
|
||||||
let directed_near = ((z_n + (z_f * z_n).sqrt()) / /*sin_gamma*/factor) as f32; //1.0; */
|
let directed_near = ((z_n + (z_f * z_n).sqrt()) / /*sin_gamma*/factor) as f32; //1.0; */
|
||||||
// let directed_far = directed_near + d as f32;
|
// let directed_far = directed_near + d as f32;
|
||||||
// println!("view_dir: {:?}, new_dir: {:?}, directed_light_dir: {:?}, dot_prod: {:?}, sin_gamma: {:?}, near_dist: {:?}, d: {:?}, z_n: {:?}, z_f: {:?}, directed_near: {:?}, directed_far: {:?}", view_dir, new_dir, directed_light_dir, dot_prod, sin_gamma, near_dist, d, z_n, z_f, directed_near, directed_far);
|
// println!("view_dir: {:?}, new_dir: {:?}, directed_light_dir: {:?}, cos_gamma: {:?}, sin_gamma: {:?}, near_dist: {:?}, d: {:?}, z_n: {:?}, z_f: {:?}, directed_near: {:?}, directed_far: {:?}", view_dir, new_dir, directed_light_dir, cos_gamma, sin_gamma, near_dist, d, z_n, z_f, directed_near, directed_far);
|
||||||
/* let size1 = bounds1.half_size();
|
/* let size1 = bounds1.half_size();
|
||||||
let center1 = bounds1.center(); */
|
let center1 = bounds1.center(); */
|
||||||
/* let look_at = cam_pos - (directed_near - near_dist) * up;
|
/* let look_at = cam_pos - (directed_near - near_dist) * up;
|
||||||
@ -1001,9 +1159,9 @@ impl Scene {
|
|||||||
// let w_v: Mat4<f32> = Mat4::translation_3d(/*-bounds1.center()*/-center1);
|
// let w_v: Mat4<f32> = Mat4::translation_3d(/*-bounds1.center()*/-center1);
|
||||||
//new observer point n-1 behind eye position
|
//new observer point n-1 behind eye position
|
||||||
//pos = eyePos-up*(n-nearDist)
|
//pos = eyePos-up*(n-nearDist)
|
||||||
// let directed_near = if /*sin_gamma > EPISLON_GAMMA*/factor != -1.0 { directed_near } else { near_dist/*0.0*//*-(near_dist *//*- light_focus_pos.y)*/ };
|
// let directed_near = if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON { directed_near } else { near_dist/*0.0*//*-(near_dist *//*- light_focus_pos.y)*/ };
|
||||||
light_focus_pos.y = if factor != -1.0 {
|
light_focus_pos.y = if factor > EPSILON_UPSILON {
|
||||||
/*near_dist*/z_n as f32 - directed_near
|
light_focus_pos.y/* - directed_near*/+ (/*near_dist*//*z_0 as f32*/ - directed_near)
|
||||||
} else {
|
} else {
|
||||||
light_focus_pos.y
|
light_focus_pos.y
|
||||||
};
|
};
|
||||||
@ -1029,7 +1187,7 @@ impl Scene {
|
|||||||
let _bounds0 = math::fit_psr(/*l_r*/shadow_view_mat/* * inverse_visible*/, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/math::Vec4::homogenized);
|
let _bounds0 = math::fit_psr(/*l_r*/shadow_view_mat/* * inverse_visible*/, visible_light_volume.iter().copied(), /*|p| math::Vec3::from(p) / p.w*/math::Vec4::homogenized);
|
||||||
// let factor = -1.0;
|
// let factor = -1.0;
|
||||||
let w_p: math::Mat4<f32> = {
|
let w_p: math::Mat4<f32> = {
|
||||||
if /*sin_gamma > EPISLON_GAMMA*/factor != -1.0 {
|
if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON {
|
||||||
// Projection for y
|
// Projection for y
|
||||||
let n = directed_near;// - near_dist;
|
let n = directed_near;// - near_dist;
|
||||||
let f = directed_far;
|
let f = directed_far;
|
||||||
@ -1153,7 +1311,7 @@ impl Scene {
|
|||||||
near: zmin,//directed_near,
|
near: zmin,//directed_near,
|
||||||
far: zmax,//directed_far,
|
far: zmax,//directed_far,
|
||||||
}); */
|
}); */
|
||||||
let shadow_all_mat: math::Mat4<f32> = w_p * shadow_view_mat/*w_v * light_all_mat*/;
|
let shadow_all_mat: math::Mat4<f32> = /*(w_v * l_r).inverted() * */w_p * shadow_view_mat/*w_v * light_all_mat*/;
|
||||||
let _w_p_arr = shadow_all_mat.cols.iter().map(|e| (e.x, e.y, e.z, e.w)).collect::<Vec<_>>();
|
let _w_p_arr = shadow_all_mat.cols.iter().map(|e| (e.x, e.y, e.z, e.w)).collect::<Vec<_>>();
|
||||||
// println!("mat4 shadow_all_mat = mat4(vec4{:?}, vec4{:?}, vec4{:?}, vec4{:?});", w_p_arr[0], w_p_arr[1], w_p_arr[2], w_p_arr[3]);
|
// println!("mat4 shadow_all_mat = mat4(vec4{:?}, vec4{:?}, vec4{:?}, vec4{:?});", w_p_arr[0], w_p_arr[1], w_p_arr[2], w_p_arr[3]);
|
||||||
let math::Aabb::<f32> { min: math::Vec3 { x: xmin, y: ymin, z: zmin }, max: math::Vec3 { x: xmax, y: ymax, z: zmax } } =
|
let math::Aabb::<f32> { min: math::Vec3 { x: xmin, y: ymin, z: zmin }, max: math::Vec3 { x: xmax, y: ymax, z: zmax } } =
|
||||||
@ -1173,7 +1331,7 @@ impl Scene {
|
|||||||
let o_x = -(xmax + xmin) / (xmax - xmin);
|
let o_x = -(xmax + xmin) / (xmax - xmin);
|
||||||
let o_y = -(ymax + ymin) / (ymax - ymin);
|
let o_y = -(ymax + ymin) / (ymax - ymin);
|
||||||
let o_z = -(zmax + zmin) / (zmax - zmin);
|
let o_z = -(zmax + zmin) / (zmax - zmin);
|
||||||
let directed_proj_mat = if /*sin_gamma > EPISLON_GAMMA*/factor != -1.0 {
|
let directed_proj_mat = if /*sin_gamma > EPISLON_GAMMA*/factor > EPSILON_UPSILON {
|
||||||
// Mat4::identity()
|
// Mat4::identity()
|
||||||
Mat4::new(
|
Mat4::new(
|
||||||
s_x, 0.0, 0.0, o_x,
|
s_x, 0.0, 0.0, o_x,
|
||||||
@ -1283,6 +1441,7 @@ impl Scene {
|
|||||||
self.terrain.render_shadows(
|
self.terrain.render_shadows(
|
||||||
renderer,
|
renderer,
|
||||||
&self.globals,
|
&self.globals,
|
||||||
|
&self.lights,
|
||||||
&self.shadow_mats,
|
&self.shadow_mats,
|
||||||
&self.light_data,
|
&self.light_data,
|
||||||
is_daylight,
|
is_daylight,
|
||||||
|
@ -455,6 +455,15 @@ struct SpriteData {
|
|||||||
pub struct Terrain<V: RectRasterableVol> {
|
pub struct Terrain<V: RectRasterableVol> {
|
||||||
atlas: AtlasAllocator,
|
atlas: AtlasAllocator,
|
||||||
chunks: HashMap<Vec2<i32>, TerrainChunkData>,
|
chunks: HashMap<Vec2<i32>, TerrainChunkData>,
|
||||||
|
/// Temporary storage for dead chunks that might still be shadowing chunks
|
||||||
|
/// in view. We wait until either the chunk definitely cannot be
|
||||||
|
/// shadowing anything the player can see, the chunk comes back into
|
||||||
|
/// view, or for daylight to end, before removing it (whichever comes
|
||||||
|
/// first).
|
||||||
|
///
|
||||||
|
/// Note that these chunks are not complete; for example, they are missing
|
||||||
|
/// texture data.
|
||||||
|
shadow_chunks: Vec<(Vec2<i32>, TerrainChunkData)>,
|
||||||
/* /// Secondary index into the terrain chunk table, used to sort through chunks by z index from
|
/* /// Secondary index into the terrain chunk table, used to sort through chunks by z index from
|
||||||
/// the top down.
|
/// the top down.
|
||||||
z_index_down: BTreeSet<Vec3<i32>>,
|
z_index_down: BTreeSet<Vec3<i32>>,
|
||||||
@ -2239,6 +2248,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
Self {
|
Self {
|
||||||
atlas,
|
atlas,
|
||||||
chunks: HashMap::default(),
|
chunks: HashMap::default(),
|
||||||
|
shadow_chunks: Vec::default(),
|
||||||
mesh_send_tmp: send,
|
mesh_send_tmp: send,
|
||||||
mesh_recv: recv,
|
mesh_recv: recv,
|
||||||
mesh_todo: HashMap::default(),
|
mesh_todo: HashMap::default(),
|
||||||
@ -2328,7 +2338,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
Ok((atlas, texture))
|
Ok((atlas, texture))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: TerrainChunkData) {
|
fn remove_chunk_meta(&mut self, _pos: Vec2<i32>, chunk: &TerrainChunkData) {
|
||||||
/* println!("Terrain chunk already existed: {:?}", pos); */
|
/* println!("Terrain chunk already existed: {:?}", pos); */
|
||||||
self.atlas.deallocate(chunk.col_lights);
|
self.atlas.deallocate(chunk.col_lights);
|
||||||
/* let (zmin, zmax) = chunk.z_bounds;
|
/* let (zmin, zmax) = chunk.z_bounds;
|
||||||
@ -2338,7 +2348,7 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
|
|
||||||
fn insert_chunk(&mut self, pos: Vec2<i32>, chunk: TerrainChunkData) {
|
fn insert_chunk(&mut self, pos: Vec2<i32>, chunk: TerrainChunkData) {
|
||||||
if let Some(old) = self.chunks.insert(pos, chunk) {
|
if let Some(old) = self.chunks.insert(pos, chunk) {
|
||||||
self.remove_chunk_meta(pos, old);
|
self.remove_chunk_meta(pos, &old);
|
||||||
}
|
}
|
||||||
/* let (zmin, zmax) = chunk.z_bounds;
|
/* let (zmin, zmax) = chunk.z_bounds;
|
||||||
self.z_index_up.insert(Vec3::from(zmin, pos.x, pos.y));
|
self.z_index_up.insert(Vec3::from(zmin, pos.x, pos.y));
|
||||||
@ -2348,7 +2358,9 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
fn remove_chunk(&mut self, pos: Vec2<i32>) {
|
fn remove_chunk(&mut self, pos: Vec2<i32>) {
|
||||||
// println!("Terrain chunk removed: {:?}", pos);
|
// println!("Terrain chunk removed: {:?}", pos);
|
||||||
if let Some(chunk) = self.chunks.remove(&pos) {
|
if let Some(chunk) = self.chunks.remove(&pos) {
|
||||||
self.remove_chunk_meta(pos, chunk);
|
self.remove_chunk_meta(pos, &chunk);
|
||||||
|
// Temporarily remember dead chunks for shadowing purposes.
|
||||||
|
self.shadow_chunks.push((pos, chunk));
|
||||||
}
|
}
|
||||||
if let Some(_todo) = self.mesh_todo.remove(&pos) {
|
if let Some(_todo) = self.mesh_todo.remove(&pos) {
|
||||||
/* println!("Terrain chunk was being meshed: {:?}",
|
/* println!("Terrain chunk was being meshed: {:?}",
|
||||||
@ -2367,7 +2379,11 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
loaded_distance: f32,
|
loaded_distance: f32,
|
||||||
view_mat: Mat4<f32>,
|
view_mat: Mat4<f32>,
|
||||||
proj_mat: Mat4<f32>,
|
proj_mat: Mat4<f32>,
|
||||||
) -> (Aabb<f32>, Aabb<f32>, Aabb<f32>) {
|
) -> (
|
||||||
|
Aabb<f32>,
|
||||||
|
/* Aabb<f32>, Aabb<f32> */ Vec<math::Vec3<f32>>,
|
||||||
|
math::Aabr<f32>,
|
||||||
|
) {
|
||||||
let current_tick = scene_data.tick;
|
let current_tick = scene_data.tick;
|
||||||
let current_time = scene_data.state.get_time();
|
let current_time = scene_data.state.get_time();
|
||||||
let mut visible_bounding_box: Option<Aabb<f32>> = None;
|
let mut visible_bounding_box: Option<Aabb<f32>> = None;
|
||||||
@ -2855,7 +2871,9 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| {
|
let collides_with_aabr = |a: math::Aabr<f32>, b: math::Aabr<f32>| {
|
||||||
a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
|
a.min.partial_cmple(&b.max).reduce_and() && a.max.partial_cmpge(&b.min).reduce_and()
|
||||||
};
|
};
|
||||||
if ray_direction.z < 0.0 && renderer.render_mode().shadow.is_map() {
|
let (visible_light_volume, visible_psr_bounds) = if ray_direction.z < 0.0
|
||||||
|
&& renderer.render_mode().shadow.is_map()
|
||||||
|
{
|
||||||
let visible_bounding_box = Aabb {
|
let visible_bounding_box = Aabb {
|
||||||
min: visible_bounding_box.min - focus_off,
|
min: visible_bounding_box.min - focus_off,
|
||||||
max: visible_bounding_box.max - focus_off,
|
max: visible_bounding_box.max - focus_off,
|
||||||
@ -2912,47 +2930,81 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
let visible_bounds = math::Aabr::from(math::fit_psr(
|
let visible_bounds = math::Aabr::from(math::fit_psr(
|
||||||
ray_mat,
|
ray_mat,
|
||||||
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
|
/* super::aabb_to_points(visible_bounding_box).iter().copied() */
|
||||||
visible_light_volume.into_iter(),
|
visible_light_volume.iter().copied(),
|
||||||
|p| p, //math::Vec3::from(p), /* / p.w */
|
|p| p, //math::Vec3::from(p), /* / p.w */
|
||||||
));
|
));
|
||||||
|
let ray_mat = ray_mat * math::Mat4::translation_3d(-focus_off);
|
||||||
/* let visible_bounds_old = Aabr::from(super::fit_psr(ray_mat, super::aabb_to_points(visible_bounding_box).iter().copied(), |p| Vec3::from(p) / p.w));
|
/* let visible_bounds_old = Aabr::from(super::fit_psr(ray_mat, super::aabb_to_points(visible_bounding_box).iter().copied(), |p| Vec3::from(p) / p.w));
|
||||||
println!("old: {:?} new: {:?}", visible_bounds_old, visible_bounds); */
|
println!("old: {:?} new: {:?}", visible_bounds_old, visible_bounds); */
|
||||||
|
|
||||||
self.chunks.iter_mut()
|
let can_shadow_sun = |pos: Vec2<i32>, chunk: &TerrainChunkData| {
|
||||||
// NOTE: We deliberately avoid doing this computation for chunks we already know
|
|
||||||
// are visible, since by definition they'll always intersect the visible view
|
|
||||||
// frustum.
|
|
||||||
.filter(|chunk| chunk.1.visible == Visibility::InRange)
|
|
||||||
.for_each(|(pos, chunk)| {
|
|
||||||
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
|
let chunk_pos = pos.map(|e| e as f32 * chunk_sz);
|
||||||
|
|
||||||
// Ensure the chunk is within the view frustum
|
// Ensure the chunk is within the PSR set.
|
||||||
let chunk_min = [chunk_pos.x, chunk_pos.y, chunk.z_bounds.0];
|
|
||||||
let chunk_max = [
|
|
||||||
chunk_pos.x + chunk_sz,
|
|
||||||
chunk_pos.y + chunk_sz,
|
|
||||||
chunk.z_bounds.1,
|
|
||||||
];
|
|
||||||
let chunk_box = math::Aabb {
|
let chunk_box = math::Aabb {
|
||||||
min: math::Vec3::from(chunk_min) - focus_off,
|
min: math::Vec3::new(chunk_pos.x, chunk_pos.y, chunk.z_bounds.0),
|
||||||
max: math::Vec3::from(chunk_max) - focus_off,
|
max: math::Vec3::new(
|
||||||
|
chunk_pos.x + chunk_sz,
|
||||||
|
chunk_pos.y + chunk_sz,
|
||||||
|
chunk.z_bounds.1,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let chunk_from_light = math::Aabr::from(math::fit_psr(ray_mat, math::aabb_to_points(chunk_box).iter().copied(), |p| p/*math::Vec3::from(p)/* / p.w*/*/));
|
let chunk_from_light = math::Aabr::from(math::fit_psr(
|
||||||
|
ray_mat,
|
||||||
|
math::aabb_to_points(chunk_box).iter().copied(),
|
||||||
|
|p| p, /* math::Vec3::from(p)/* / p.w*/ */
|
||||||
|
));
|
||||||
/* let chunk_from_light = Aabr {
|
/* let chunk_from_light = Aabr {
|
||||||
min: (ray_mat * Vec4::from_point(chunk_box.min)).xy(),
|
min: (ray_mat * Vec4::from_point(chunk_box.min)).xy(),
|
||||||
max: (ray_mat * Vec4::from_point(chunk_box.max)).xy(),
|
max: (ray_mat * Vec4::from_point(chunk_box.max)).xy(),
|
||||||
}.made_valid(); */
|
}.made_valid(); */
|
||||||
let can_shadow_sun = collides_with_aabr(chunk_from_light, visible_bounds);
|
/* let can_shadow_sun = */
|
||||||
|
collides_with_aabr(chunk_from_light, visible_bounds)
|
||||||
/* let can_shadow_sun_old = collides_with_aabr(chunk_from_light, visible_bounds_old);
|
/* let can_shadow_sun_old = collides_with_aabr(chunk_from_light, visible_bounds_old);
|
||||||
if can_shadow_sun != can_shadow_sun_old {
|
if can_shadow_sun != can_shadow_sun_old {
|
||||||
println!("Different results for chunk {:?} (from light = {:?}):\n\
|
println!("Different results for chunk {:?} (from light = {:?}):\n\
|
||||||
old = {:?} new = {:?}",
|
old = {:?} new = {:?}",
|
||||||
chunk_box, chunk_from_light, can_shadow_sun_old, can_shadow_sun);
|
chunk_box, chunk_from_light, can_shadow_sun_old, can_shadow_sun);
|
||||||
} */
|
} */
|
||||||
chunk.can_shadow_sun = can_shadow_sun;
|
};
|
||||||
});
|
|
||||||
}
|
// Handle potential shadow casters (chunks that aren't visible, but are still in
|
||||||
|
// range) to see if they could cast shadows.
|
||||||
|
self.chunks.iter_mut()
|
||||||
|
// NOTE: We deliberately avoid doing this computation for chunks we already know
|
||||||
|
// are visible, since by definition they'll always intersect the visible view
|
||||||
|
// frustum.
|
||||||
|
.filter(|chunk| chunk.1.visible <= Visibility::InRange)
|
||||||
|
.for_each(|(&pos, chunk)| {
|
||||||
|
chunk.can_shadow_sun = can_shadow_sun(pos, chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle dead chunks that we kept around only to make sure shadows don't blink
|
||||||
|
// out when a chunk disappears.
|
||||||
|
//
|
||||||
|
// If the sun can currently cast shadows, we retain only those shadow chunks
|
||||||
|
// that both: 1. have not been replaced by a real chunk instance,
|
||||||
|
// and 2. are currently potential shadow casters (as witnessed by
|
||||||
|
// `can_shadow_sun` returning true).
|
||||||
|
//
|
||||||
|
// NOTE: Please make sure this runs *after* any code that could insert a chunk!
|
||||||
|
// Otherwise we may end up with multiple instances of the chunk trying to cast
|
||||||
|
// shadows at the same time.
|
||||||
|
let chunks = &self.chunks;
|
||||||
|
self.shadow_chunks
|
||||||
|
.retain(|(pos, chunk)| !chunks.contains_key(pos) && can_shadow_sun(*pos, chunk));
|
||||||
|
|
||||||
|
(visible_light_volume, visible_bounds)
|
||||||
|
} else {
|
||||||
|
// There's no daylight or no shadows, so there's no reason to keep any
|
||||||
|
// shadow chunks around.
|
||||||
|
self.shadow_chunks.clear();
|
||||||
|
(Vec::new(), math::Aabr {
|
||||||
|
min: math::Vec2::zero(),
|
||||||
|
max: math::Vec2::zero(),
|
||||||
|
})
|
||||||
|
};
|
||||||
/* let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w()) + focus_off; let look_at = visible_box.center();
|
/* let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w()) + focus_off; let look_at = visible_box.center();
|
||||||
let view_dir = (focus_pos - cam_pos).normalized();
|
let view_dir = (focus_pos - cam_pos).normalized();
|
||||||
let up_vec = ray_direction.cross(view_dir).cross(light_dir).normalized();
|
let up_vec = ray_direction.cross(view_dir).cross(light_dir).normalized();
|
||||||
@ -3008,7 +3060,12 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
(scene_bounding_box, visible_bounding_box, psc_bounding_box)
|
(
|
||||||
|
/* scene_bounding_box, visible_bounding_box, psc_bounding_box */
|
||||||
|
visible_bounding_box,
|
||||||
|
visible_light_volume,
|
||||||
|
visible_psr_bounds,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chunk_count(&self) -> usize { self.chunks.len() }
|
pub fn chunk_count(&self) -> usize { self.chunks.len() }
|
||||||
@ -3020,10 +3077,13 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shadow_chunk_count(&self) -> usize { self.shadow_chunks.len() }
|
||||||
|
|
||||||
pub fn render_shadows(
|
pub fn render_shadows(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
|
lights: &Consts<Light>,
|
||||||
shadow_mats: &Consts<ShadowLocals>,
|
shadow_mats: &Consts<ShadowLocals>,
|
||||||
light_data: &[Light],
|
light_data: &[Light],
|
||||||
is_daylight: bool,
|
is_daylight: bool,
|
||||||
@ -3040,16 +3100,23 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
let chunk_iter = Spiral2d::new()
|
let chunk_iter = Spiral2d::new()
|
||||||
.filter_map(|rpos| {
|
.filter_map(|rpos| {
|
||||||
let pos = focus_chunk + rpos;
|
let pos = focus_chunk + rpos;
|
||||||
self.chunks.get(&pos).map(|c| (pos, c))
|
self.chunks.get(&pos)
|
||||||
})
|
})
|
||||||
.take(self.chunks.len());
|
.take(self.chunks.len());
|
||||||
|
|
||||||
// let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
// let is_daylight = sun_dir.z < 0.0/*0.6*/;
|
||||||
|
|
||||||
// Directed shadows
|
// Directed shadows
|
||||||
|
//
|
||||||
|
// NOTE: We also render shadows for dead chunks that were found to still be
|
||||||
|
// potential shadow casters, to avoid shadows suddenly disappearing at
|
||||||
|
// very steep sun angles (e.g. sunrise / sunset).
|
||||||
if is_daylight {
|
if is_daylight {
|
||||||
for (_, chunk) in chunk_iter.clone() {
|
chunk_iter
|
||||||
if chunk.can_shadow_sun() {
|
.clone()
|
||||||
|
.filter(|chunk| chunk.can_shadow_sun())
|
||||||
|
.chain(self.shadow_chunks.iter().map(|(_, chunk)| chunk))
|
||||||
|
.for_each(|chunk| {
|
||||||
// Directed light shadows.
|
// Directed light shadows.
|
||||||
renderer.render_terrain_shadow_directed(
|
renderer.render_terrain_shadow_directed(
|
||||||
// &chunk.shadow_model,
|
// &chunk.shadow_model,
|
||||||
@ -3057,18 +3124,20 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
globals,
|
globals,
|
||||||
&chunk.locals,
|
&chunk.locals,
|
||||||
shadow_mats,
|
shadow_mats,
|
||||||
/* lights,
|
lights,
|
||||||
* shadows,
|
/* shadows,
|
||||||
* &lod.map,
|
* &lod.map,
|
||||||
* &lod.horizon, */
|
* &lod.horizon, */
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Point shadows
|
// Point shadows
|
||||||
for _light in light_data.iter().take(1) {
|
//
|
||||||
for (_, chunk) in chunk_iter.clone() {
|
// NOTE: We don't bother retaining chunks unless they cast sun shadows, so we
|
||||||
|
// don't use `shadow_chunks` here.
|
||||||
|
light_data.iter().take(1).for_each(|_light| {
|
||||||
|
chunk_iter.clone().for_each(|chunk| {
|
||||||
if chunk.can_shadow_point {
|
if chunk.can_shadow_point {
|
||||||
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
|
// shadow_vertex_count += chunk.shadow_model.vertex_range.len();
|
||||||
renderer.render_shadow_point(
|
renderer.render_shadow_point(
|
||||||
@ -3077,14 +3146,14 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
globals,
|
globals,
|
||||||
&chunk.locals,
|
&chunk.locals,
|
||||||
shadow_mats,
|
shadow_mats,
|
||||||
/* lights,
|
lights,
|
||||||
* shadows,
|
/* shadows,
|
||||||
* &lod.map,
|
* &lod.map,
|
||||||
* &lod.horizon, */
|
* &lod.horizon, */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
|
@ -644,11 +644,11 @@ impl PlayState for SessionState {
|
|||||||
self.scene
|
self.scene
|
||||||
.camera_mut()
|
.camera_mut()
|
||||||
.compute_dependents(&*self.client.borrow().state().terrain());
|
.compute_dependents(&*self.client.borrow().state().terrain());
|
||||||
// Extract HUD events ensuring the client borrow gets dropped.
|
|
||||||
let mut hud_events = self.hud.maintain(
|
// Generate debug info, if needed (it iterates through enough data that we might
|
||||||
&self.client.borrow(),
|
// as well avoid it unless we need it).
|
||||||
global_state,
|
let debug_info = if global_state.settings.gameplay.toggle_debug {
|
||||||
DebugInfo {
|
Some(DebugInfo {
|
||||||
tps: clock.get_tps(),
|
tps: clock.get_tps(),
|
||||||
ping_ms: self.client.borrow().get_ping_ms_rolling_avg(),
|
ping_ms: self.client.borrow().get_ping_ms_rolling_avg(),
|
||||||
coordinates: self
|
coordinates: self
|
||||||
@ -677,9 +677,19 @@ impl PlayState for SessionState {
|
|||||||
.cloned(),
|
.cloned(),
|
||||||
num_chunks: self.scene.terrain().chunk_count() as u32,
|
num_chunks: self.scene.terrain().chunk_count() as u32,
|
||||||
num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32,
|
num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32,
|
||||||
|
num_shadow_chunks: self.scene.terrain().shadow_chunk_count() as u32,
|
||||||
num_figures: self.scene.figure_mgr().figure_count() as u32,
|
num_figures: self.scene.figure_mgr().figure_count() as u32,
|
||||||
num_figures_visible: self.scene.figure_mgr().figure_count_visible() as u32,
|
num_figures_visible: self.scene.figure_mgr().figure_count_visible() as u32,
|
||||||
},
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract HUD events ensuring the client borrow gets dropped.
|
||||||
|
let mut hud_events = self.hud.maintain(
|
||||||
|
&self.client.borrow(),
|
||||||
|
global_state,
|
||||||
|
&debug_info,
|
||||||
&self.scene.camera(),
|
&self.scene.camera(),
|
||||||
clock.get_last_delta(),
|
clock.get_last_delta(),
|
||||||
HudInfo {
|
HudInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user