WIP -- lighting changes and soft shadows.

This commit is contained in:
Joshua Yanovski 2020-04-09 02:38:40 +02:00
parent 9cd2b3fb0d
commit 8414987e58
19 changed files with 439 additions and 190 deletions

1
Cargo.lock generated
View File

@ -4908,6 +4908,7 @@ dependencies = [
"log 0.4.8",
"num 0.2.1",
"num_cpus",
"rayon",
"specs",
"uvth",
"vek 0.10.0",

View File

@ -29,21 +29,25 @@ out vec4 tgt_color;
void main() {
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
vec3 view_dir = normalize(-vec3(vert_pos4) / vert_pos4.w);
vec3 surf_color = /*srgb_to_linear*/(model_col.rgb * f_col);
vec3 k_a = surf_color;
vec3 k_d = 0.5 * surf_color;
vec3 k_s = 0.5 * surf_color;
vec3 k_a = vec3(0.5);
vec3 k_d = vec3(0.5);
vec3 k_s = vec3(0.5);
float alpha = 2.0;
vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm);
vec3 light_frac = light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), 2.0);
// vec3 point_light = light_at(f_pos, f_norm);
// vec3 light, diffuse_light, ambient_light;
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, k_a * point_shadow, k_d * point_shadow, k_s * point_shadow, alpha, emitted_light, reflected_light);
get_sun_diffuse(f_norm, time_of_day.x, view_dir, k_a * (0.5 * point_shadow + 0.5 * light_frac), k_d * point_shadow, k_s * point_shadow, alpha, emitted_light, reflected_light);
lights_at(f_pos, f_norm, cam_to_frag, k_a * point_shadow, k_d * point_shadow, k_s * point_shadow, alpha, emitted_light, reflected_light);
lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
// get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, surf_color * f_light * point_shadow, 0.5 * surf_color * f_light * point_shadow, 0.5 * surf_color * f_light * point_shadow, 2.0, emitted_light, reflected_light);
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
@ -54,7 +58,7 @@ void main() {
// diffuse_light += point_light;
// reflected_light += point_light;
// vec3 surf_color = illuminate(srgb_to_linear(model_col.rgb * f_col), light, diffuse_light, ambient_light);
surf_color = illuminate(emitted_light, reflected_light);
surf_color = illuminate(surf_color * emitted_light, surf_color * reflected_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;

View File

@ -1,5 +1,7 @@
#version 330 core
// https://www.shadertoy.com/view/XdsyWf
#include <globals.glsl>
#include <random.glsl>
@ -66,6 +68,8 @@ void main() {
vec3 f_norm = normals[norm_axis + norm_dir];
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
vec3 view_dir = normalize(-vec3(vert_pos4) / vert_pos4.w);
float frag_dist = length(f_pos - cam_pos.xyz);
vec3 b_norm;
@ -95,22 +99,31 @@ void main() {
vec4 _clouds;
vec3 reflect_ray_dir = reflect(cam_to_frag, norm);
vec3 reflect_ray_dir = reflect(cam_to_frag/*-view_dir*/, norm);
/* vec4 reflect_ray_dir4 = view_mat * vec4(reflect_ray_dir, 1.0);
reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, false, _clouds) * f_light;
vec3 surf_color = /*srgb_to_linear*/(vec3(0.2, 0.5, 1.0));
vec3 k_a = surf_color;
vec3 k_d = vec3(1.0);
vec3 k_s = reflect_color;
vec3 k_a = vec3(1.0);
vec3 k_d = surf_color;
vec3 k_s = 2.0 * reflect_color;
float alpha = 0.255;
vec3 emitted_light, reflected_light;
// vec3 light, diffuse_light, ambient_light;
float point_shadow = shadow_at(f_pos, f_norm);
// 0 = 100% reflection, 1 = translucent water
float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag), 0.5);
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, k_a * f_light * point_shadow, vec3(0.0), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
lights_at(f_pos, f_norm, cam_to_frag, k_a * f_light * point_shadow, k_d * f_light * point_shadow, k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag/*-view_dir*/), -cam_to_frag/*view_dir*/), 0.5);
vec3 diffuse_light_point = vec3(0.0);
get_sun_diffuse(norm, time_of_day.x, view_dir, k_a * f_light * point_shadow, vec3(0.0), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
lights_at(f_pos, norm, view_dir, k_a, vec3(1.0), vec3(0.0), alpha, emitted_light, diffuse_light_point);
vec3 dump_light = vec3(0.0);
vec3 specular_light_point = vec3(0.0);
lights_at(f_pos, norm, view_dir, vec3(0.0), vec3(0.0), vec3(1.0), alpha, dump_light, specular_light_point);
float reflected_light_point = diffuse_light_point.r + f_light * point_shadow;
reflected_light += k_d * (diffuse_light_point + f_light * point_shadow) + k_s * specular_light_point;
// get_sun_diffuse(norm, time_of_day.x, light, diffuse_light, ambient_light, 0.0);
// diffuse_light *= f_light * point_shadow;
// ambient_light *= f_light * point_shadow;
@ -119,7 +132,7 @@ void main() {
// diffuse_light += point_light;
// reflected_light += point_light;
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)) * light * diffuse_light * ambient_light;
surf_color = illuminate(emitted_light, reflected_light);
surf_color = illuminate(surf_color * emitted_light, reflected_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
@ -134,10 +147,11 @@ void main() {
// Tint
// reflect_color = mix(reflect_color, surf_color, 0.6);
// vec4 color = mix(vec4(reflect_color * 2.0, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(f_light * point_shadow + point_light) * 0.25)), passthrough);
vec4 color = vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(/*f_light * point_shadow + point_light*/reflected_light) * 0.25));
// vec4 color = surf_color;
// vec4 color = mix(vec4(reflect_color * 2.0, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(/*f_light * point_shadow*/f_light * point_shadow + reflected_light_point/* + point_light*//*reflected_light*/) * 0.25)), passthrough);
// vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 0.0), passthrough);
//vec4 color = vec4(surf_color, 1.0);
vec4 color = vec4(surf_color, mix(1.0, 1.0 / (1.0 + 0.25 * /*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point)), passthrough));
tgt_color = color; // mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a);
}

View File

@ -1,6 +1,19 @@
#include <random.glsl>
#include <sky.glsl>
uniform sampler2D t_map;
uniform sampler2D t_horizon;
vec3 linear_to_srgb(vec3 col) {
vec3 s1 = vec3(sqrt(col.r), sqrt(col.g), sqrt(col.b));
vec3 s2 = vec3(sqrt(s1.r), sqrt(s1.g), sqrt(s1.b));
vec3 s3 = vec3(sqrt(s2.r), sqrt(s2.g), sqrt(s2.b));
return vec3(
mix(11.500726 * col.r, (0.585122381 * s1.r + 0.783140355 * s2.r - 0.368262736 * s3.r), clamp((col.r - 0.0060) * 10000.0, 0.0, 1.0)),
mix(11.500726 * col.g, (0.585122381 * s1.g + 0.783140355 * s2.g - 0.368262736 * s3.g), clamp((col.g - 0.0060) * 10000.0, 0.0, 1.0)),
mix(11.500726 * col.b, (0.585122381 * s1.b + 0.783140355 * s2.b - 0.368262736 * s3.b), clamp((col.b - 0.0060) * 10000.0, 0.0, 1.0))
);
}
vec2 pos_to_uv(vec2 pos) {
vec2 uv_pos = (pos + 16) / 32768.0;
@ -52,7 +65,7 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
}
float alt_at(vec2 pos) {
return texture(t_map, pos_to_uv(pos)).a * (1300.0) + 140.0;
return texture/*textureBicubic*/(t_map, pos_to_uv(pos)).a * (1300.0) + 140.0;
//+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
return 0.0
@ -61,6 +74,79 @@ float alt_at(vec2 pos) {
+ texture(t_noise, pos * 0.003).x * 30.0;
}
float horizon_at(vec3 pos, /*float time_of_day*/vec3 light_dir) {
// vec3 sun_dir = get_sun_dir(time_of_day);
const float PI_2 = 3.1415926535897932384626433832795 / 2.0;
const float MIN_LIGHT = 0.115;
/*
let shade_frac = horizon_map
.and_then(|(angles, heights)| {
chunk_idx
.and_then(|chunk_idx| angles.get(chunk_idx))
.map(|&e| (e as f64, heights))
})
.and_then(|(e, heights)| {
chunk_idx
.and_then(|chunk_idx| heights.get(chunk_idx))
.map(|&f| (e, f as f64))
})
.map(|(angle, height)| {
let w = 0.1;
if angle != 0.0 && light_direction.x != 0.0 {
let deltax = height / angle;
let lighty = (light_direction.y / light_direction.x * deltax).abs();
let deltay = lighty - height;
let s = (deltay / deltax / w).min(1.0).max(0.0);
// Smoothstep
s * s * (3.0 - 2.0 * s)
} else {
1.0
}
})
.unwrap_or(1.0);
*/
float alt = alt_at(pos.xy);
vec4 f_horizons = textureBicubic(t_horizon, pos_to_uv(pos.xy));
f_horizons.xyz = linear_to_srgb(f_horizons.xyz);
vec2 f_horizon;
if (light_dir.z >= 0) {
return MIN_LIGHT;
}
if (light_dir.x >= 0) {
f_horizon = f_horizons.rg;
} else {
f_horizon = f_horizons.ba;
}
float angle = tan(f_horizon.x * PI_2);
float height = f_horizon.y * /*1300.0*/1278.7266845703125 + 140.0;
const float w = 0.1;
float deltah = height - alt;
if (deltah < 0.0001 || angle < 0.0001 || abs(light_dir.x) < 0.0001) {
return 1.0;
} else {
float lighta = abs(light_dir.z / light_dir.x);
float deltax = deltah / angle;
float lighty = lighta * deltax;
float deltay = lighty - (deltah + max(pos.z - alt, 0.0));
float s = max(min(max(deltay, 0.0) / deltax / w, 1.0), 0.0);
return max(/*0.2 + 0.8 * */(s * s * (3.0 - 2.0 * s)), MIN_LIGHT);
/* if (lighta >= angle) {
return 1.0;
} else {
return MIN_LIGHT;
} */
// float deltah = height - alt;
// float deltah = max(height - alt, 0.0);
// float lighty = abs(sun_dir.z / sun_dir.x * deltax);
// float lighty = abs(sun_dir.z / sun_dir.x * deltax);
// float deltay = lighty - /*pos.z*//*deltah*/(deltah + max(pos.z - alt, 0.0))/*deltah*/;
// float s = max(min(max(deltay, 0.0) / deltax / w, 1.0), 0.0);
// Smoothstep
return max(/*0.2 + 0.8 * */(s * s * (3.0 - 2.0 * s)), MIN_LIGHT);
}
}
vec2 splay(vec2 pos) {
return pos * pow(length(pos) * 0.5, 3.0);
}
@ -96,6 +182,6 @@ vec3 lod_pos(vec2 v_pos, vec2 focus_pos) {
vec3 lod_col(vec2 pos) {
//return vec3(0, 0.5, 0);
return textureBicubic(t_map, pos_to_uv(pos)).rgb;
return linear_to_srgb(textureBicubic(t_map, pos_to_uv(pos)).rgb);
//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1;
}

View File

@ -37,7 +37,7 @@ vec3 get_moon_dir(float time_of_day) {
return normalize(-vec3(sin(moon_angle_rad), 0.0, cos(moon_angle_rad) - 0.5));
}
const float PERSISTENT_AMBIANCE = 0.025; // 0.1;
const float PERSISTENT_AMBIANCE = 0.1; // 0.025; // 0.1;
float get_sun_brightness(vec3 sun_dir) {
return max(-sun_dir.z + 0.6, 0.0) * 0.9;
@ -95,13 +95,13 @@ void get_sun_diffuse(vec3 norm, float time_of_day, vec3 dir, vec3 k_a, vec3 k_d,
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-norm, sun_dir)) * 10000.0), 0.0, 0.5);
float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-norm, sun_dir)) * mix(0.0, 1.0, abs(sun_dir.z) * 10000.0) * 10000.0), 0.0, 0.5);
emitted_light = k_a * (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light)) + PERSISTENT_AMBIANCE;
// TODO: Add shadows.
reflected_light =
sun_chroma * light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha) +
moon_chroma * 0.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha);
moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha);
/* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
diffuse_light =

View File

@ -11,9 +11,9 @@ vec3 srgb_to_linear(vec3 srgb) {
//
// Note: norm, dir, light_dir must all be normalizd.
vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 k_s, float alpha) {
float ndotL = max(dot(-norm, light_dir), 0.0);
if (ndotL > 0.0) {
vec3 H = normalize(-light_dir + dir);
float ndotL = max(dot(norm, -light_dir), 0.0);
if (ndotL > 0.0/* && dot(s_norm, -light_dir) > 0.0*/) {
vec3 H = normalize(light_dir + dir);
// (k_d * (L ⋅ N) + k_s * (R ⋅ V)^α)
return k_d * ndotL + k_s * pow(max(dot(norm, H), 0.0), alpha * 4.0);
}

View File

@ -17,23 +17,76 @@ void main() {
vec3 f_col = lod_col(f_pos.xy);
vec3 emitted_light, reflected_light;
vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
vec3 view_dir = normalize(-vec3(vert_pos4) / vert_pos4.w);
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
// Note: because voxels, we reduce the normal for reflections to just its z component, dpendng on distance to camera.
// Idea: the closer we are to facing top-down, the more the norm should tend towards up-z.
vec3 l_norm = vec3(0.0, 0.0, 1.0);
// vec3 l_norm = normalize(vec3(f_norm.x / max(abs(f_norm.x), 0.001), f_norm.y / max(abs(f_norm.y), 0.001), f_norm.z / max(abs(f_norm.z), 0.001)));
// vec3 l_factor = 1.0 / (1.0 + max(abs(/*f_pos - cam_pos.xyz*//*-vec3(vert_pos4) / vert_pos4.w*/vec3(f_pos.xy, 0.0) - vec3(/*cam_pos*/focus_pos.xy, cam_to_frag)) - vec3(view_distance.x, view_distance.x, 0.0), 0.0) / vec3(32.0 * 2.0, 32.0 * 2.0, 1.0));
// l_factor.z =
// vec4 focus_pos4 = view_mat * vec4(focus_pos.xyz, 1.0);
// vec3 focus_dir = normalize(-vec3(focus_pos4) / focus_pos4.w);
float l_factor = 1.0 - pow(clamp(0.5 + 0.5 * dot(/*-view_dir*/-cam_to_frag, l_norm), 0.0, 1.0), 2.0);//1.0 / (1.0 + 0.5 * pow(max(distance(/*focus_pos.xy*/vec3(focus_pos.xy, /*vert_pos4.z / vert_pos4.w*/f_pos.z), vec3(f_pos.xy, f_pos.z))/* - view_distance.x*/ - 32.0, 0.0) / (32.0 * 1.0), /*0.5*/1.0));
l_factor = 1.0;
l_norm = normalize(mix(l_norm, f_norm, l_factor));
/* l_norm = normalize(vec3(
mix(l_norm.x, f_norm.x, clamp(pow(f_norm.x * 0.5, 64), 0, 1)),
mix(-1.0, 1.0, clamp(pow(f_norm.y * 0.5, 64), 0, 1)),
mix(-1.0, 1.0, clamp(pow(f_norm.z * 0.5, 64), 0, 1))
)); */
// f_norm = mix(l_norm, f_norm, min(1.0 / max(cam_to_frag, 0.001), 1.0));
/* vec3 l_norm = normalize(vec3(
mix(-1.0, 1.0, clamp(pow(f_norm.x * 0.5, 64), 0, 1)),
mix(-1.0, 1.0, clamp(pow(f_norm.y * 0.5, 64), 0, 1)),
mix(-1.0, 1.0, clamp(pow(f_norm.z * 0.5, 64), 0, 1))
)); */
// Use f_norm here for better shadows.
vec3 light_frac = light_reflection_factor(l_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), 4.0);
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
// float sun_light = get_sun_brightness(sun_dir);
// float moon_light = get_moon_brightness(moon_dir);
float sun_shade_frac = horizon_at(f_pos, sun_dir);
float moon_shade_frac = horizon_at(f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = sun_shade_frac + moon_shade_frac;
// float brightness_denominator = (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light);
// vec3 light, diffuse_light, ambient_light;
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, f_col, 0.5 * f_col, 0.5 * vec3(1.0), 2.0, emitted_light, reflected_light);
// get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, (0.25 * shade_frac + 0.25 * light_frac) * f_col, 0.5 * shade_frac * f_col, 0.5 * shade_frac * /*vec3(1.0)*/f_col, 2.0, emitted_light, reflected_light);
get_sun_diffuse(l_norm, time_of_day.x, view_dir, 1.0 * (0.5 * light_frac + vec3(0.5 * shade_frac)), vec3(shade_frac * 0.5), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(shade_frac * 0.5), 4.0, emitted_light, reflected_light);
// emitted_light += 0.5 * vec3(SUN_AMBIANCE * sun_shade_frac * sun_light + moon_shade_frac * moon_light) * f_col * (ambient_sides + 1.0);
// Ambient lighting attempt: vertical light.
// reflected_light += /*0.0125*/0.15 * 0.25 * _col * light_reflection_factor(f_norm, cam_to_frag, vec3(0, 0, -1.0), 0.5 * f_col, 0.5 * f_col, 2.0);
// emitted_light += /*0.0125*/0.25 * f_col * ;
// vec3 light, diffuse_light, ambient_light;
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
// vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light);
vec3 surf_color = illuminate(emitted_light, reflected_light);
vec3 surf_color = /*illuminate(emitted_light, reflected_light)*/illuminate(f_col * emitted_light, f_col * reflected_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
vec3 fog_color = get_sky_color(cam_to_frag, time_of_day.x, cam_pos.xyz, f_pos, 1.0, true, clouds);
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
// vec3 color = surf_color;
float mist_factor = max(1 - (f_pos.z + (texture(t_noise, f_pos.xy * 0.0005 + time_of_day.x * 0.0003).x - 0.5) * 128.0) / 400.0, 0.0);
// float mist_factor = max(1 - (f_pos.z + (texture(t_noise, f_pos.xy * 0.0005 + time_of_day.x * 0.0003).x - 0.5) * 128.0) / 400.0, 0.0);
//float mist_factor = f_norm.z * 2.0;
color = mix(color, vec3(1.0) * /*diffuse_light*/reflected_light, clamp(mist_factor * 0.00005 * distance(f_pos.xy, focus_pos.xy), 0, 0.3));
// color = mix(color, vec3(1.0) * /*diffuse_light*/reflected_light, clamp(mist_factor * 0.00005 * distance(f_pos.xy, focus_pos.xy), 0, 0.3));
// color = surf_color;
tgt_color = vec4(color, 1.0);
}

View File

@ -17,16 +17,19 @@ const float FADE_DIST = 32.0;
void main() {
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
vec3 view_dir = normalize(-vec3(vert_pos4) / vert_pos4.w);
vec3 surf_color = /*srgb_to_linear*/(f_col);
vec3 k_a = surf_color;
vec3 k_d = 0.5 * surf_color;
vec3 k_s = 0.5 * surf_color;
vec3 k_a = vec3(1.0);
vec3 k_d = vec3(0.5);
vec3 k_s = vec3(0.5);
float alpha = 2.0;
vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm);
vec3 light_frac = light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), 2.0);
// vec3 light, diffuse_light, ambient_light;
// vec3 emitted_light, reflected_light;
@ -34,7 +37,7 @@ void main() {
// vec3 point_light = light_at(f_pos, f_norm);
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, k_a * f_light * point_shadow, k_d * f_light * point_shadow, k_s * f_light * point_shadow, 2.0, emitted_light, reflected_light);
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, k_a * (0.5 * f_light * point_shadow + 0.5 * light_frac), k_d * f_light * point_shadow, k_s * f_light * point_shadow, 2.0, emitted_light, reflected_light);
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0);
// float point_shadow = shadow_at(f_pos, f_norm);
// diffuse_light *= f_light * point_shadow;
@ -42,8 +45,8 @@ void main() {
// light += point_light;
// diffuse_light += point_light;
// reflected_light += point_light;
lights_at(f_pos, f_norm, cam_to_frag, k_a * f_light * point_shadow, k_d * f_light * point_shadow, k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
surf_color = illuminate(emitted_light, reflected_light);
lights_at(f_pos, f_norm, cam_to_frag, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
surf_color = illuminate(surf_color * emitted_light, surf_color * reflected_light);
// vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);

View File

@ -11,6 +11,7 @@ out vec4 tgt_color;
#include <sky.glsl>
#include <light.glsl>
#include <lod.glsl>
void main() {
// First 3 normals are negative, next 3 are positive
@ -24,19 +25,36 @@ void main() {
vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
vec4 vert_pos4 = view_mat * vec4(f_pos, 1.0);
vec3 view_dir = normalize(-vec3(vert_pos4) / vert_pos4.w);
vec3 sun_dir = get_sun_dir(time_of_day.x);
vec3 moon_dir = get_moon_dir(time_of_day.x);
// float sun_light = get_sun_brightness(sun_dir);
// float moon_light = get_moon_brightness(moon_dir);
float sun_shade_frac = horizon_at(f_pos, sun_dir);
float moon_shade_frac = horizon_at(f_pos, moon_dir);
// Globbal illumination "estimate" used to light the faces of voxels which are parallel to the sun or moon (which is a very common occurrence).
// Will be attenuated by k_d, which is assumed to carry any additional ambient occlusion information (e.g. about shadowing).
// float ambient_sides = clamp(mix(0.5, 0.0, abs(dot(-f_norm, sun_dir)) * 10000.0), 0.0, 0.5);
// NOTE: current assumption is that moon and sun shouldn't be out at the sae time.
// This assumption is (or can at least easily be) wrong, but if we pretend it's true we avoids having to explicitly pass in a separate shadow
// for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally).
float shade_frac = sun_shade_frac + moon_shade_frac;
vec3 surf_color = /*srgb_to_linear*/(f_col);
vec3 k_a = 0.5 * surf_color;
vec3 k_d = 0.5 * surf_color;
vec3 k_s = 0.5 * surf_color;
vec3 k_a = vec3(1.0);
vec3 k_d = vec3(0.5);
vec3 k_s = vec3(0.5);
float alpha = 2.0;
vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm);
vec3 light_frac = light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), 2.0);
get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, k_a * f_light * point_shadow, k_d * f_light * point_shadow, k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
get_sun_diffuse(f_norm, time_of_day.x, view_dir, k_a * f_light * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), k_d * f_light * point_shadow * shade_frac, k_s * f_light * point_shadow * shade_frac, alpha, emitted_light, reflected_light);
lights_at(f_pos, f_norm, cam_to_frag, k_a * f_light * point_shadow, k_d * f_light * point_shadow, k_s * f_light * point_shadow, alpha, emitted_light, reflected_light);
lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
// float point_shadow = shadow_at(f_pos, f_norm);
// vec3 point_light = light_at(f_pos, f_norm);
@ -56,13 +74,13 @@ void main() {
// light_reflection_factorplight_reflection_factor
// vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light);
surf_color = illuminate(emitted_light, reflected_light);
surf_color = illuminate(f_col * emitted_light, f_col * reflected_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds;
vec3 fog_color = get_sky_color(cam_to_frag, time_of_day.x, cam_pos.xyz, f_pos, 1.0, true, clouds);
vec3 color = surf_color;
// vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
// vec3 color = surf_color;
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
tgt_color = vec4(color, 1.0);
}

View File

@ -14,6 +14,7 @@ image = "0.22.3"
num = "0.2.0"
num_cpus = "1.10.1"
log = "0.4.8"
rayon = "^1.3.0"
specs = "0.15.1"
vek = { version = "0.10.0", features = ["serde"] }
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }

View File

@ -34,6 +34,7 @@ use hashbrown::HashMap;
use image::DynamicImage;
use log::{error, warn};
use num::traits::FloatConst;
use rayon::prelude::*;
use std::{
net::SocketAddr,
sync::Arc,
@ -72,6 +73,10 @@ pub struct Client {
/// shadows, rivers, and probably foliage, cities, roads, and other
/// structures.
pub lod_base: Arc<DynamicImage>,
/// The "shadow" layer for LOD. Includes east and west horizon angles and
/// an approximate max occluder height, which we use to try to
/// approximate soft and volumetric shadows.
pub lod_horizon: Arc<DynamicImage>,
/// A fully rendered map image for use with the map and minimap; note that
/// this can be constructed dynamically by combining the layers of world
/// map data (e.g. with shadow map data or river data), but at present
@ -103,7 +108,8 @@ impl Client {
let mut postbox = PostBox::to(addr)?;
// Wait for initial sync
let (state, entity, server_info, lod_base, world_map) = match postbox.next_message()? {
let (state, entity, server_info, lod_base, lod_horizon, world_map) =
match postbox.next_message()? {
ServerMsg::InitialSync {
entity_package,
server_info,
@ -144,13 +150,17 @@ impl Client {
let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt;
log::debug!("Preparing image...");
let unzip_horizons = |(angles, heights): (Vec<_>, Vec<_>)| {
let unzip_horizons = |(angles, heights): &(Vec<_>, Vec<_>)| {
(
angles.into_iter().map(scale_angle).collect::<Vec<_>>(),
heights.into_iter().map(scale_height).collect::<Vec<_>>(),
angles.iter().copied().map(scale_angle).collect::<Vec<_>>(),
heights
.iter()
.copied()
.map(scale_height)
.collect::<Vec<_>>(),
)
};
let horizons = [unzip_horizons(west), unzip_horizons(east)];
let horizons = [unzip_horizons(&west), unzip_horizons(&east)];
// Redraw map (with shadows this time).
let mut world_map = vec![0u32; rgba.len()];
@ -158,6 +168,7 @@ impl Client {
map_config.lgain = 1.0;
map_config.gain = max_height;
map_config.horizons = Some(&horizons);
// map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
map_config.focus.z = 0.0;
let rescale_height = |h: Alt| (h / max_height as Alt) as f32;
let bounds_check = |pos: Vec2<i32>| {
@ -240,9 +251,21 @@ impl Client {
};
let lod_base = make_raw(&rgba)?;
let world_map = make_raw(&world_map)?;
let horizons = (west.0, west.1, east.0, east.1)
.into_par_iter()
.map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh]))
.collect::<Vec<_>>();
let lod_horizon = make_raw(&horizons)?;
log::debug!("Done preparing image...");
(state, entity, server_info, lod_base, (world_map, map_size))
(
state,
entity,
server_info,
lod_base,
lod_horizon,
(world_map, map_size),
)
},
ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers),
_ => return Err(Error::ServerWentMad),
@ -262,6 +285,7 @@ impl Client {
server_info,
world_map,
lod_base,
lod_horizon,
player_list: HashMap::new(),
postbox,

View File

@ -23,6 +23,7 @@ gfx_defines! {
locals: gfx::ConstantBuffer<Locals> = "u_locals",
globals: gfx::ConstantBuffer<Globals> = "u_globals",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",

View File

@ -28,6 +28,9 @@ gfx_defines! {
lights: gfx::ConstantBuffer<Light> = "u_lights",
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
map: gfx::TextureSampler<[f32; 4]> = "t_map",
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
noise: gfx::TextureSampler<f32> = "t_noise",
tgt_color: gfx::RenderTarget<TgtColorFmt> = "tgt_color",

View File

@ -557,6 +557,8 @@ impl Renderer {
locals: &Consts<terrain::Locals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
map: &Texture, /* <(gfx::format::R8, gfx::format::Unorm)> */
horizon: &Texture, /* <(gfx::format::R8, gfx::format::Unorm)> */
) {
self.encoder.draw(
&gfx::Slice {
@ -574,6 +576,8 @@ impl Renderer {
lights: lights.buf.clone(),
shadows: shadows.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
},
@ -654,6 +658,7 @@ impl Renderer {
globals: &Consts<Globals>,
locals: &Consts<lod_terrain::Locals>,
map: &Texture,
horizon: &Texture,
) {
self.encoder.draw(
&gfx::Slice {
@ -670,6 +675,7 @@ impl Renderer {
globals: globals.buf.clone(),
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
map: (map.srv.clone(), map.sampler.clone()),
horizon: (horizon.srv.clone(), horizon.sampler.clone()),
tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(),
},

View File

@ -12,7 +12,8 @@ use vek::*;
pub struct Lod {
model: Option<(u32, Model<LodTerrainPipeline>)>,
locals: Consts<Locals>,
map: Texture,
pub map: Texture,
pub horizon: Texture,
tgt_detail: u32,
}
@ -24,6 +25,9 @@ impl Lod {
map: renderer
.create_texture(&client.lod_base, Some(FilterMethod::Trilinear), None)
.expect("Failed to generate map texture"),
horizon: renderer
.create_texture(&client.lod_horizon, Some(FilterMethod::Trilinear), None)
.expect("Failed to generate horizon texture"),
tgt_detail: settings.graphics.lod_detail.max(100).min(2500),
}
}
@ -48,7 +52,7 @@ impl Lod {
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
if let Some((_, model)) = self.model.as_ref() {
renderer.render_lod_terrain(&model, globals, &self.locals, &self.map);
renderer.render_lod_terrain(&model, globals, &self.locals, &self.map, &self.horizon);
}
}
}

View File

@ -395,6 +395,7 @@ impl Scene {
&self.globals,
&self.lights,
&self.shadows,
&self.lod,
self.camera.get_focus_pos(),
);
self.figure_mgr.render(

View File

@ -6,7 +6,7 @@ use crate::{
},
};
use super::SceneData;
use super::{Lod, SceneData};
use common::{
assets,
figure::Segment,
@ -1393,6 +1393,7 @@ impl<V: RectRasterableVol> Terrain<V> {
globals: &Consts<Globals>,
lights: &Consts<Light>,
shadows: &Consts<Shadow>,
lod: &Lod,
focus_pos: Vec3<f32>,
) {
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
@ -1415,6 +1416,8 @@ impl<V: RectRasterableVol> Terrain<V> {
&chunk.locals,
lights,
shadows,
&lod.map,
&lod.horizon,
);
}
}

View File

@ -36,7 +36,7 @@ impl<'a> BlockGen<'a> {
.as_ref()
}
fn get_cliff_height(
pub fn get_cliff_height(
column_gen: &ColumnGen<'a>,
cache: &mut SmallCache<Option<ColumnSample<'a>>>,
wpos: Vec2<f32>,

View File

@ -1316,6 +1316,42 @@ impl WorldSim {
|angle: Alt| (angle.atan() * <Alt as FloatConst>::FRAC_2_PI() * 255.0).floor() as u8;
let scale_height =
|height: Alt| (height as Alt * 255.0 / self.max_height as Alt).floor() as u8;
let samples_data = {
let column_sample = ColumnGen::new(self);
(0..WORLD_SIZE.product())
.into_par_iter()
.map_init(
|| Box::new(BlockGen::new(ColumnGen::new(self))),
|block_gen, posi| {
let wpos = uniform_idx_as_vec2(posi);
let mut sample = column_sample.get(
uniform_idx_as_vec2(posi) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
)?;
// let zcache = block_gen.get_z_cache();
let alt = sample.alt;
sample.alt = alt.max(BlockGen::get_cliff_height(
&mut block_gen.column_gen,
&mut block_gen.column_cache,
wpos.map(|e| e as f32),
&sample.close_cliffs,
sample.cliff_hill,
32.0,
));
sample.basement += sample.alt - alt;
Some(sample)
},
)
/* .map(|posi| {
let mut sample = column_sample.get(
uniform_idx_as_vec2(posi) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
);
}) */
.collect::<Vec<_>>()
.into_boxed_slice()
};
let horizons = get_horizon_map(
map_config.lgain,
Aabr {
@ -1325,27 +1361,18 @@ impl WorldSim {
CONFIG.sea_level as Alt,
(CONFIG.sea_level + self.max_height) as Alt,
|posi| {
let chunk = &self.chunks[posi];
chunk.alt.max(chunk.water_alt) as Alt
/* let chunk = &self.chunks[posi];
chunk.alt.max(chunk.water_alt) as Alt */
let sample = samples_data[posi].as_ref();
sample
.map(|s| s.alt.max(s.water_level))
.unwrap_or(CONFIG.sea_level) as Alt
},
|a| scale_angle(a),
|h| scale_height(h),
)
.unwrap();
let samples_data = {
let column_sample = ColumnGen::new(self);
(0..WORLD_SIZE.product())
.into_par_iter()
.map(|posi| {
column_sample.get(
uniform_idx_as_vec2(posi) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
)
})
.collect::<Vec<_>>()
.into_boxed_slice()
};
let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
// TODO: Parallelize again.
let config = MapConfig {