From 1015e60deef3c447381996277df7496707a63bd0 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Tue, 21 Apr 2020 18:25:19 +0200 Subject: [PATCH] More lighting changes. --- assets/voxygen/shaders/figure-frag.glsl | 13 +- assets/voxygen/shaders/figure-vert.glsl | 2 +- assets/voxygen/shaders/fluid-frag/cheap.glsl | 20 ++- assets/voxygen/shaders/fluid-frag/shiny.glsl | 22 +-- .../shaders/include/cloud/regular.glsl | 25 +++- assets/voxygen/shaders/include/light.glsl | 4 +- assets/voxygen/shaders/include/lod.glsl | 16 +- assets/voxygen/shaders/include/sky.glsl | 32 +++- assets/voxygen/shaders/include/srgb.glsl | 141 +++++++++++++++++- assets/voxygen/shaders/lod-terrain-frag.glsl | 14 +- assets/voxygen/shaders/sprite-frag.glsl | 13 +- assets/voxygen/shaders/terrain-frag.glsl | 17 ++- assets/voxygen/shaders/terrain-vert.glsl | 2 +- client/src/lib.rs | 14 +- voxygen/src/render/mod.rs | 4 +- voxygen/src/render/pipelines/mod.rs | 13 +- voxygen/src/render/renderer.rs | 21 ++- voxygen/src/render/texture.rs | 11 +- voxygen/src/scene/camera.rs | 2 +- voxygen/src/scene/lod.rs | 25 +++- voxygen/src/scene/mod.rs | 6 + voxygen/src/scene/simple.rs | 4 + voxygen/src/scene/terrain.rs | 1 + world/src/sim/mod.rs | 15 +- world/src/sim/util.rs | 2 +- 25 files changed, 342 insertions(+), 97 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 7f4bdac8fc..eee1c074d4 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -52,20 +52,23 @@ void main() { float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; vec3 surf_color = /*srgb_to_linear*/(model_col.rgb * f_col); + float alpha = 1.0; + const float n2 = 1.01; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); vec3 k_a = vec3(1.0); - vec3 k_d = vec3(0.5); - vec3 k_s = vec3(0.5); - float alpha = 2.0; + vec3 k_d = vec3(1.0); + vec3 k_s = vec3(R_s); vec3 emitted_light, reflected_light; float point_shadow = shadow_at(f_pos, f_norm); - vec3 light_frac = /*vec3(1.0);*//*vec3(max(dot(-f_norm, sun_dir) * 0.5 + 0.5, 0.0));*/light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), alpha); + vec3 light_frac = /*vec3(1.0);*//*vec3(max(dot(f_norm, -sun_dir) * 0.5 + 0.5, 0.0));*/light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); // vec3 point_light = light_at(f_pos, f_norm); // vec3 light, diffuse_light, ambient_light; //get_sun_diffuse(f_norm, time_of_day.x, view_dir, k_a * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), k_d * point_shadow * shade_frac, k_s * point_shadow * shade_frac, alpha, emitted_light, reflected_light); - get_sun_diffuse2(f_norm, sun_dir, moon_dir, view_dir, k_a * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), k_d * point_shadow * shade_frac, k_s * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + get_sun_diffuse2(f_norm, sun_dir, moon_dir, view_dir, k_a * (shade_frac * 0.5 + light_frac * 0.5), k_d * point_shadow * shade_frac, k_s * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + emitted_light *= point_shadow; lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); /* vec3 point_light = light_at(f_pos, f_norm); diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 4215a7f292..4d84d7df8e 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -37,7 +37,7 @@ void main() { combined_mat * vec4(v_pos, 1)).xyz; - f_col = v_col; + f_col = srgb_to_linear(v_col); // Calculate normal here rather than for each pixel in the fragment shader f_norm = normalize(( diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index bcbf46c35f..9ec2b31e29 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -38,7 +38,7 @@ void main() { // vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/); vec3 view_dir = -cam_to_frag; // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); - vec3 surf_color = /*srgb_to_linear*/(vec3(0.2, 0.5, 1.0)); + /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); @@ -46,10 +46,13 @@ void main() { float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir); float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; - vec3 k_a = vec3(0.5); - vec3 k_d = vec3(0.5) * surf_color; - vec3 k_s = vec3(0.5) * surf_color; - float alpha = 0.255; + const float alpha = 0.255 / 4.0 / sqrt(2.0); + const float n2 = 1.3325; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); + + vec3 k_a = vec3(1.0); + vec3 k_d = vec3(1.0) * water_color; + vec3 k_s = vec3(R_s) * water_color; vec3 emitted_light, reflected_light; @@ -59,10 +62,11 @@ void main() { // vec3 light, diffuse_light, ambient_light; float point_shadow = shadow_at(f_pos,f_norm); // float vert_light = f_light; - vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), alpha); + vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); - get_sun_diffuse(f_norm, time_of_day.x, /*-cam_to_frag*/view_dir, k_a * f_light * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), vec3(0.0), k_s * f_light * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/view_dir, k_a * (shade_frac * 0.5 + light_frac * 0.5), vec3(0.0), k_s * f_light * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + emitted_light *= f_light * point_shadow; // get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 0.0); // diffuse_light *= f_light * point_shadow; // ambient_light *= f_light, point_shadow; @@ -93,7 +97,7 @@ void main() { float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/), 0.5); - surf_color = illuminate(surf_color * emitted_light, /*surf_color * */reflected_light); + vec3 surf_color = illuminate(water_color * emitted_light, /*surf_color * */reflected_light); vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/reflected_light_point/* * 0.25*/)), passthrough); tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index b7ea945f5d..4ab797190f 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -106,7 +106,7 @@ void main() { 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)); + /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); @@ -114,22 +114,26 @@ void main() { float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir); float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; - vec3 k_a = vec3(0.5); - vec3 k_d = 0.5 * surf_color; - vec3 k_s = 2.0 * reflect_color; - float alpha = 0.255; + const float alpha = 0.255/* / 4.0 / sqrt(2.0)*/; + const float n2 = 1.3325; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); + + vec3 k_a = vec3(1.0); + vec3 k_d = 1.0 * water_color; + vec3 k_s = R_s * reflect_color;//2.0 * reflect_color; vec3 emitted_light, reflected_light; // vec3 light, diffuse_light, ambient_light; float point_shadow = shadow_at(f_pos, f_norm); - vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), alpha); + vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); // 0 = 100% reflection, 1 = translucent water float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/), 0.5); - get_sun_diffuse(norm, time_of_day.x, view_dir, k_a * f_light * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), vec3(0.0), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s * f_light * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, view_dir, k_a * (shade_frac * 0.5 + light_frac * 0.5), vec3(0.0), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s * f_light * point_shadow * shade_frac, alpha, emitted_light, reflected_light); + emitted_light *= f_light * point_shadow; vec3 diffuse_light_point = vec3(0.0); - lights_at(f_pos, norm, view_dir, k_a, vec3(1.0), vec3(0.0), alpha, emitted_light, diffuse_light_point); + lights_at(f_pos, norm, view_dir, k_a, vec3(1.0), /*vec3(0.0)*/k_s, alpha, emitted_light, diffuse_light_point); vec3 dump_light = vec3(0.0); vec3 specular_light_point = vec3(0.0); @@ -149,7 +153,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(surf_color * emitted_light, reflected_light); + vec3 surf_color = illuminate(water_color * emitted_light, reflected_light); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec4 clouds; diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index a28ae2c845..fa241405a9 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -1,8 +1,8 @@ #include -const float CLOUD_AVG_HEIGHT = 1025.0; -const float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 50.0; -const float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 50.0; +// float CLOUD_AVG_HEIGHT = /*1025.0*/view_distance.z + 0.7 + view_distance.w; +// float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 50.0; +// float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 50.0; const float CLOUD_THRESHOLD = 0.25; const float CLOUD_SCALE = 5.0; const float CLOUD_DENSITY = 100.0; @@ -11,7 +11,15 @@ float vsum(vec3 v) { return v.x + v.y + v.z; } +vec3 get_cloud_heights() { + float CLOUD_AVG_HEIGHT = /*1025.0*/view_distance.z + 0.7 * view_distance.w; + float CLOUD_HEIGHT_MIN = CLOUD_AVG_HEIGHT - 50.0; + float CLOUD_HEIGHT_MAX = CLOUD_AVG_HEIGHT + 50.0; + return vec3(CLOUD_AVG_HEIGHT, CLOUD_HEIGHT_MIN, CLOUD_HEIGHT_MAX); +} + vec2 cloud_at(vec3 pos) { + vec3 max_heights = get_cloud_heights(); vec2 scaled_pos = pos.xy / CLOUD_SCALE; float tick_offs = 0.0 @@ -32,10 +40,10 @@ vec2 cloud_at(vec3 pos) { + texture(t_noise, scaled_pos * 0.02 + tick_offs + time_of_day.x * 0.0004).x * 0.15 ) * value; - float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - CLOUD_AVG_HEIGHT) / 400.0, 0.0) * CLOUD_DENSITY; + float density = max((value - CLOUD_THRESHOLD) - abs(pos.z - max_heights.x) / 400.0, 0.0) * CLOUD_DENSITY; - const float SHADE_GRADIENT = 1.5 / (CLOUD_AVG_HEIGHT - CLOUD_HEIGHT_MIN); - float shade = ((pos.z - CLOUD_AVG_HEIGHT) / (CLOUD_HEIGHT_MAX - CLOUD_HEIGHT_MIN)) * 2.5 + 0.7; + float SHADE_GRADIENT = 1.5 / (max_heights.x - max_heights.y); + float shade = ((pos.z - max_heights.x) / (max_heights.z - max_heights.y)) * 2.5 + 0.7; return vec2(shade, density / (1.0 + vsum(abs(pos - cam_pos.xyz)) / 5000)); } @@ -44,8 +52,9 @@ vec4 get_cloud_color(vec3 dir, vec3 origin, float time_of_day, float max_dist, f const int ITERS = 12; const float INCR = 1.0 / ITERS; - float mind = (CLOUD_HEIGHT_MIN - origin.z) / dir.z; - float maxd = (CLOUD_HEIGHT_MAX - origin.z) / dir.z; + vec3 max_heights = get_cloud_heights(); + float mind = (max_heights.y - origin.z) / dir.z; + float maxd = (max_heights.z - origin.z) / dir.z; float start = max(min(mind, maxd), 0.0); float delta = min(abs(mind - maxd), max_dist); diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl index 8df3dbdb22..a5421654fc 100644 --- a/assets/voxygen/shaders/include/light.glsl +++ b/assets/voxygen/shaders/include/light.glsl @@ -71,7 +71,8 @@ float shadow_at(vec3 wpos, vec3 wnorm) { return min(shadow, 1.0); } -void lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) { +// Returns computed maximum intensity. +float lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light/*, out float shadow*/) { // shadow = 0.0; vec3 ambient_light = vec3(0.0); @@ -122,4 +123,5 @@ void lights_at(vec3 wpos, vec3 wnorm, vec3 cam_to_frag, vec3 k_a, vec3 k_d, vec3 // shadow = shadow_at(wpos, wnorm); // float shadow = shadow_at(wpos, wnorm); emitted_light += k_a * ambient_light/* * shadow*/;// min(shadow, 1.0); + return 1.0;//ambient_light; } diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 9ebbb04152..f698890d44 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -55,7 +55,7 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { } float alt_at(vec2 pos) { - return texture/*textureBicubic*/(t_map, pos_to_uv(pos)).a * (/*1300.0*/1278.7266845703125) + 140.0; + return texture/*textureBicubic*/(t_map, pos_to_uv(pos)).a * (/*1300.0*//*1278.7266845703125*/view_distance.w) + /*140.0*/view_distance.z; //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0; return 0.0 @@ -67,7 +67,7 @@ float alt_at(vec2 pos) { float horizon_at2(vec4 f_horizons, float alt, 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/*0.0*/; + const float MIN_LIGHT = 0.0;//0.115/*0.0*/; // return 1.0; /* @@ -116,8 +116,14 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec vec2 f_horizon = mix(f_horizons.rg, f_horizons.ba, bvec2(light_dir.x < 0.0)); // vec2 f_horizon = mix(f_horizons.ba, f_horizons.rg, clamp(light_dir.x * 10000.0, 0.0, 1.0)); // f_horizon = mix(f_horizons.ba, f_horizons.rg, bvec2(lessThan(light_dir.xx, vec2(0.0)))); + /* if (f_horizon.x <= 0) { + return 1.0; + } */ float angle = tan(f_horizon.x * PI_2); - float height = f_horizon.y * /*1300.0*/1278.7266845703125 + 140.0; + /* if (angle <= 0.0001) { + return 1.0; + } */ + float height = f_horizon.y * /*1300.0*//*1278.7266845703125*/view_distance.w + view_distance.z; const float w = 0.1; float deltah = height - alt; //if (deltah < 0.0001/* || angle < 0.0001 || abs(light_dir.x) < 0.0001*/) { @@ -125,11 +131,11 @@ float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec /*} else */{ float lighta = /*max*/(-light_dir.z/*, 0.0*/) / max(abs(light_dir.x), 0.0001); // NOTE: Ideally, deltah <= 0.0 is a sign we have an oblique horizon angle. - float deltax = max(deltah, 0.0) / max(angle, 0.0001); + float deltax = deltah / max(angle, 0.0001)/*angle*/; float lighty = lighta * deltax; float deltay = lighty - deltah + max(pos.z - alt, 0.0); // NOTE: the "real" deltah should always be >= 0, so we know we're only handling the 0 case with max. - float s = max(min(max(deltay, 0.0) / max(deltax, 0.0001) / w, 1.0), 0.0); + float s = mix(max(min(max(deltay, 0.0) / max(deltax, 0.0001) / w, 1.0), 0.0), 1.0, deltah <= 0); return max(/*0.2 + 0.8 * */(s * s * (3.0 - 2.0 * s)), MIN_LIGHT); /* if (lighta >= angle) { return 1.0; diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 8e8208d367..89cef8fddf 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -7,7 +7,7 @@ const float PI = 3.141592; const vec3 SKY_DAY_TOP = vec3(0.1, 0.2, 0.9); const vec3 SKY_DAY_MID = vec3(0.02, 0.08, 0.8); const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3); -const vec3 DAY_LIGHT = vec3(1.2, 1.0, 1.0); +const vec3 DAY_LIGHT = vec3(1.2, 1.0, 1.0) * 3.0; const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.0); const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20); @@ -96,6 +96,7 @@ 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)) * mix(0.0, 1.0, abs(sun_dir.z) * 10000.0) * 10000.0), 0.0, 0.5); + // float ambient_sides = 0.5 - 0.5 * abs(dot(-norm, sun_dir)); emitted_light = k_a * (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light)) + PERSISTENT_AMBIANCE; // TODO: Add shadows. @@ -111,7 +112,8 @@ void get_sun_diffuse(vec3 norm, float time_of_day, vec3 dir, vec3 k_a, vec3 k_d, ambient_light = vec3(SUN_AMBIANCE * sun_light + moon_light); */ } -void get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { +// Returns computed maximum intensity. +float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { const float SUN_AMBIANCE = 0.1; float sun_light = get_sun_brightness(sun_dir); @@ -129,7 +131,10 @@ void get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a // 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)) * mix(0.0, 1.0, abs(sun_dir.z) * 10000.0) * 10000.0), 0.0, 0.5); + float ambient_sides = 0.0; + // float ambient_sides = 0.5 - 0.5 * min(abs(dot(-norm, sun_dir)), abs(dot(-norm, moon_dir))); + // 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); + // 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. @@ -143,6 +148,7 @@ void get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a moon_chroma * mix(1.0, pow(dot(-norm, moon_dir) * 2.0, 2.0), diffusion) + PERSISTENT_AMBIANCE; ambient_light = vec3(SUN_AMBIANCE * sun_light + moon_light); */ + return 1.0;//sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; } @@ -276,12 +282,28 @@ float fog(vec3 f_pos, vec3 focus_pos, uint medium) { return pow(clamp((max(fog, mist) - min_fog) / (max_fog - min_fog), 0.0, 1.0), 1.7); } +float rel_luminance(vec3 rgb) +{ + // https://en.wikipedia.org/wiki/Relative_luminance + const vec3 W = vec3(0.2126, 0.7152, 0.0722); + return dot(rgb, W); +} + /* vec3 illuminate(vec3 color, vec3 light, vec3 diffuse, vec3 ambience) { float avg_col = (color.r + color.g + color.b) / 3.0; return ((color - avg_col) * light + (diffuse + ambience) * avg_col) * (diffuse + ambience); } */ -vec3 illuminate(vec3 emitted, vec3 reflected) { +vec3 illuminate(/*vec3 max_light, */vec3 emitted, vec3 reflected) { const float gamma = /*0.5*/1.0;//1.0; + /* float light = length(emitted + reflected); + float color = srgb_to_linear(emitted + reflected); + float avg_col = (color.r + color.g + color.b) / 3.0; + return ((color - avg_col) * light + reflected * avg_col) * (emitted + reflected); */ + // float max_intensity = vec3(1.0); vec3 color = emitted + reflected; - return srgb_to_linear(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma))); + float lum = rel_luminance(color); + + return color;//normalize(color) * lum / (1.0 + lum); + // float sum_col = color.r + color.g + color.b; + // return /*srgb_to_linear*/(/*0.5*//*0.125 * */vec3(pow(color.x, gamma), pow(color.y, gamma), pow(color.z, gamma))); } diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index 6f98bd2ade..50906e44a9 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -8,6 +8,8 @@ vec3 srgb_to_linear(vec3 srgb) { } vec3 linear_to_srgb(vec3 col) { + // bvec3 cutoff = lessThan(col, vec3(0.0060)); + // return mix(11.500726 * col, , cutoff); 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)); @@ -18,15 +20,140 @@ vec3 linear_to_srgb(vec3 col) { ); } +float pow5(float x) { + float x2 = x * x; + return x2 * x2 * x; +} + +// Schlick approximation +vec3 schlick_fresnel(vec3 Rs, float cosTheta) { + // auto pow5 = [](Float v) { return (v * v) * (v * v) * v; }; + // return Rs + pow5(1 - cosTheta) * (Spectrum(1.) - Rs); + return Rs + pow5(1.0 - cosTheta) * (1.0 - Rs); +} + +// Beckmann Distribution +float BeckmannDistribution_D(float NdotH, float alpha) { + const float PI = 3.1415926535897932384626433832795; + float NdotH2 = NdotH * NdotH; + float NdotH2m2 = NdotH2 * alpha * alpha; + float k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2); + return mix(k_spec, 0.0, NdotH == 0.0); +} + +float BeckmannDistribution_Lambda(vec3 norm, vec3 dir, float alpha) { + float CosTheta = /*max(dot(norm, dir), 0.0);*/dot(norm, dir); + /* if (CosTheta == 0.0) { + return 0.0; + } + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + float TanTheta = SinTheta / CosTheta; + float absTanTheta = abs(TanTheta); */ + // vec3 w = normalize(dir - dot(dir, norm) * (norm)); + // float CosTheta = w.z; + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + float TanTheta = SinTheta / CosTheta; + float absTanTheta = abs(TanTheta); + /* if (isinf(absTanTheta)) { + return 0.0; + } */ + /* float CosPhi = mix(clamp(projDirNorm.x / sinTheta, -1.0, 1.0), 0.0, sinTheta == 0.0); + float SinPhi = mix(clamp(projDirNorm.y / sinTheta, -1.0, 1.0), 0.0, sinTheta == 0.0); + float alpha = sqrt(CosPhi * CosPhi * alphax * alphax + SinPhi * SinPhi * alphay * alphay); */ + // Float absTanTheta = std::abs(TanTheta(w)); + // if (std::isinf(absTanTheta)) return 0.; + // <> + // Float alpha = std::sqrt(Cos2Phi(w) * alphax * alphax + + // Sin2Phi(w) * alphay * alphay); + float a = 1.0 / (alpha * absTanTheta); + /* if (a >= 1.6) { + return 0.0; + } + + return (1.0 - 1.259 * a + 0.396 * a * a) / (3.535 * a + 2.181 * a * a); */ + + return mix(max(0.0, (1.0 - 1.259 * a + 0.396 * a * a) / (3.535 * a + 2.181 * a * a)), 0.0, isinf(absTanTheta) || a >= 1.6); + // Float a = 1 / (alpha * absTanTheta); + // if (a >= 1.6f) + // return 0; + // return (1 - 1.259f * a + 0.396f * a * a) / + // (3.535f * a + 2.181f * a * a); + // return 1 / (1 + Lambda(wo) + Lambda(wi)); +} + +float BeckmannDistribution_G(vec3 norm, vec3 dir, vec3 light_dir, float alpha) { + // return 1 / (1 + Lambda(wo) + Lambda(wi)); + return 1.0 / (1.0 + BeckmannDistribution_Lambda(norm, dir, alpha) + BeckmannDistribution_Lambda(norm, -light_dir, alpha)); +} + +// Fresnel blending +// +// http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html#fragment-MicrofacetDistributionPublicMethods-2 +// and +// http://www.pbr-book.org/3ed-2018/Reflection_Models/Fresnel_Incidence_Effects.html +vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, float alpha) { + const float PI = 3.1415926535897932384626433832795; + alpha = alpha * sqrt(2.0); + float cos_wi = max(dot(-light_dir, norm), 0.0); + float cos_wo = max(dot(dir, norm), 0.0); + vec3 diffuse = (28.0 / (23.0 * PI)) * R_d * + (1.0 - R_s) * + (1.0 - pow5(1.0 - 0.5 * abs(cos_wi))) * + (1.0 - pow5(1.0 - 0.5 * abs(cos_wo))); + /* Spectrum diffuse = (28.f/(23.f*Pi)) * Rd * + (Spectrum(1.f) - Rs) * + (1 - pow5(1 - .5f * AbsCosTheta(wi))) * + (1 - pow5(1 - .5f * AbsCosTheta(wo))); */ + // Vector3f wh = wi + wo; + vec3 wh = -light_dir + dir; + if (cos_wi == 0.0 || cos_wo == 0.0) { + return vec3(0.0); + } + /* if (cos_wi == 0.0 || cos_wo == 0.0) { + return vec3(0.0); + } */ + /* if (wh.x == 0 && wh.y == 0 && wh.z == 0) { + return vec3(0.0); + // return Spectrum(0); + } */ + wh = normalize(wh);//mix(normalize(wh), vec3(0.0), equal(light_dir, dir)); + float dot_wi_wh = dot(-light_dir, wh); + vec3 specular = BeckmannDistribution_D(dot(wh, norm), alpha) / + (4 * abs(dot_wi_wh)) * + max(/*abs*/(cos_wi), /*abs*/(cos_wo)) * + schlick_fresnel(R_s, dot_wi_wh); + // Spectrum specular = distribution->D(wh) / + // (4 * AbsDot(wi, wh) * + // std::max(AbsCosTheta(wi), AbsCosTheta(wo))) * + // SchlickFresnel(Dot(wi, wh)); + return mix(diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir)))); +} + // Phong reflection. // // 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/* && 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 + mix(k_s * pow(max(dot(norm, H), 0.0), alpha * 4.0), vec3(0.0), bvec3(ndotL == 0.0)); - // } - // return vec3(0.0); + // Basis: plane norm = norm = (0, 0, 1), x vector = any orthgonal vector on the plane. + // vec3 w_i = + // vec3 w_i = vec3(view_mat * vec4(-light_dir, 1.0)); + // vec3 w_o = vec3(view_mat * vec4(light_dir, 1.0)); + float g = 1.0;// BeckmannDistribution_G(norm, dir, light_dir, alpha); + return FresnelBlend_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s * g, alpha); + // const float PI = 3.141592; + // alpha = alpha * sqrt(2.0); + // 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); + + // float NdotH = dot(norm, H); + // float NdotH2 = NdotH * NdotH; + // float NdotH2m2 = NdotH2 * alpha * alpha; + // float k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2); + // return mix(k_s * k_spec, vec3(0.0), bvec3(ndotL <= 0.0 || NdotH == 0.0)); + // // + // // (k_d * (L ⋅ N) + k_s * (R ⋅ V)^α) + // // return k_d * ndotL + mix(k_s * pow(max(dot(norm, H), 0.0), alpha * 4.0), vec3(0.0), bvec3(ndotL == 0.0)); + // // } + // // return vec3(0.0); } diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index d4d2082c4d..3f91fe6bf8 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -67,15 +67,17 @@ void main() { float shade_frac = sun_shade_frac + moon_shade_frac; // float brightness_denominator = (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light); - float alpha = 2.0; + float alpha = 1.0;//sqrt(2.0); + const float n2 = 1.01; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); vec3 emitted_light, reflected_light; // Use f_norm here for better shadows. - vec3 light_frac = light_reflection_factor(f_norm/*l_norm*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), alpha); + vec3 light_frac = light_reflection_factor(f_norm/*l_norm*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(/*1.0*/R_s), alpha); // vec3 light, diffuse_light, ambient_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_diffuse2(f_norm/*l_norm*/, sun_dir, moon_dir, 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), alpha, emitted_light, reflected_light); + get_sun_diffuse2(f_norm/*l_norm*/, sun_dir, moon_dir, view_dir, 1.0 * (0.5 * light_frac + vec3(0.5 * shade_frac)), vec3(shade_frac * 1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(shade_frac * R_s), alpha, emitted_light, reflected_light); // emitted_light = vec3(1.0); // reflected_light = vec3(0.0); @@ -96,9 +98,9 @@ void main() { 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 = 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)); + // 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 = surf_color; tgt_color = vec4(color, 1.0); diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 8eb6b11a3b..1748d8d7e1 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -37,17 +37,19 @@ void main() { float shade_frac = sun_shade_frac + moon_shade_frac; vec3 surf_color = /*srgb_to_linear*//*linear_to_srgb*/(f_col); + float alpha = 1.0; + const float n2 = 1.01; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); vec3 k_a = vec3(1.0); - vec3 k_d = vec3(0.5); - vec3 k_s = vec3(0.5); - float alpha = 2.0; + vec3 k_d = vec3(1.0); + vec3 k_s = vec3(R_s); vec3 emitted_light, reflected_light; float point_shadow = shadow_at(f_pos, f_norm); float vert_light = f_light; - vec3 light_frac = light_reflection_factor(/*f_norm*/vec3(0, 0, 1.0), view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(1.0), alpha); + vec3 light_frac = light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); /* light_frac += light_reflection_factor(f_norm, view_dir, vec3(1.0, 0, 0.0), vec3(1.0), vec3(1.0), 2.0); light_frac += light_reflection_factor(f_norm, view_dir, vec3(-1.0, 0, 0.0), vec3(1.0), vec3(1.0), 2.0); light_frac += light_reflection_factor(f_norm, view_dir, vec3(0.0, -1.0, 0.0), vec3(1.0), vec3(1.0), 2.0); @@ -59,7 +61,8 @@ 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*/view_dir, k_a * vert_light * point_shadow * (shade_frac * 0.5 + light_frac * 0.5), k_d * vert_light * point_shadow * shade_frac, k_s * vert_light * point_shadow * shade_frac, 2.0, emitted_light, reflected_light); + get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, /*cam_to_frag*/view_dir, k_a * (shade_frac * 0.5 + light_frac * 0.5), k_d * vert_light * point_shadow * shade_frac, k_s * vert_light * point_shadow * shade_frac, 2.0, emitted_light, reflected_light); + emitted_light *= vert_light * point_shadow; // 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; diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 71993842f5..28898db2a5 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -49,18 +49,23 @@ void main() { float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; vec3 surf_color = /*srgb_to_linear*/(f_col); + float alpha = 1.0; + const float n2 = 1.01; + const float R_s = pow((1.0 - n2) / (1.0 + n2), 2); vec3 k_a = vec3(1.0); - vec3 k_d = vec3(0.5); - vec3 k_s = vec3(0.5); - float alpha = 2.0; + vec3 k_d = vec3(1.0); + vec3 k_s = vec3(R_s); + float max_light = 0.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), alpha); + vec3 light_frac = /*vec3(1.0)*/light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); - 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); + max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, k_a * (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, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); + emitted_light *= f_light * point_shadow; + + max_light += lights_at(f_pos, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); /* vec3 point_light = light_at(f_pos, f_norm); emitted_light += point_light; reflected_light += point_light; */ diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 0407eddc7c..d79ff62c9e 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -26,7 +26,7 @@ void main() { f_pos.z *= min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0); f_pos.z -= min(32.0, pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0)); - f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0; + f_col = srgb_to_linear(vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0); f_light = float(v_col_light & 0xFFu) / 255.0; diff --git a/client/src/lib.rs b/client/src/lib.rs index fe8d946b0d..10e293cd6a 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -81,7 +81,12 @@ pub struct Client { /// 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 /// we opt not to do this. - pub world_map: (Arc, Vec2), + /// + /// The second element of the tuple is the world size (as a 2D grid, + /// in chunks), and the third element holds the minimum height for any land + /// chunk (i.e. the sea level) in its x coordinate, and the maximum land + /// height above this height (i.e. the max height) in its y coordinate. + pub world_map: (Arc, Vec2, Vec2), pub player_list: HashMap, postbox: PostBox, @@ -256,6 +261,11 @@ impl Client { .map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh])) .collect::>(); let lod_horizon = make_raw(&horizons)?; + // TODO: Get sea_level from server. + let map_bounds = Vec2::new( + /* map_config.focus.z */ world::CONFIG.sea_level, + /* map_config.gain */ max_height, + ); log::debug!("Done preparing image..."); ( @@ -264,7 +274,7 @@ impl Client { server_info, lod_base, lod_horizon, - (world_map, map_size), + (world_map, map_size, map_bounds), ) }, ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers), diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 6d90ea52e4..cab1f90770 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -31,7 +31,9 @@ pub use self::{ }, Globals, Light, Shadow, }, - renderer::{LodColorFmt, Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt}, + renderer::{ + LodColorFmt, LodTextureFmt, Renderer, TgtColorFmt, TgtDepthFmt, WinColorFmt, WinDepthFmt, + }, texture::Texture, }; pub use gfx::texture::{FilterMethod, WrapMode}; diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 974c49b7c7..67cbd39073 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -19,7 +19,14 @@ gfx_defines! { all_mat: [[f32; 4]; 4] = "all_mat", cam_pos: [f32; 4] = "cam_pos", focus_pos: [f32; 4] = "focus_pos", - // TODO: Fix whatever alignment issue requires these uniforms to be aligned. + /// NOTE: max_intensity is computed as the ratio between the brightest and least bright + /// intensities among all lights in the scene. + // hdr_ratio: [f32; 4] = "max_intensity", + /// NOTE: view_distance.x is the horizontal view distance, view_distance.z is the + /// minimum height over any land chunk (i.e. the sea level), and view_distance.w is the + /// maximum height over this minimum height. + /// + /// TODO: Fix whatever alignment issue requires these uniforms to be aligned. view_distance: [f32; 4] = "view_distance", time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64. tick: [f32; 4] = "tick", @@ -48,6 +55,7 @@ impl Globals { cam_pos: Vec3, focus_pos: Vec3, view_distance: f32, + map_bounds: Vec2, time_of_day: f64, tick: f64, screen_res: Vec2, @@ -63,7 +71,7 @@ impl Globals { all_mat: arr_to_mat((proj_mat * view_mat).into_col_array()), cam_pos: Vec4::from(cam_pos).into_array(), focus_pos: Vec4::from(focus_pos).into_array(), - view_distance: [view_distance; 4], + view_distance: [view_distance, 0.0, map_bounds.x, map_bounds.y], time_of_day: [time_of_day as f32; 4], tick: [tick as f32; 4], screen_res: Vec4::from(screen_res.map(|e| e as f32)).into_array(), @@ -86,6 +94,7 @@ impl Default for Globals { Vec3::zero(), Vec3::zero(), 0.0, + Vec2::new(140.0, 2048.0), 0.0, 0.0, Vec2::new(800, 500), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 61daab86e8..c62b9dda42 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -41,8 +41,11 @@ pub type WinColorView = gfx::handle::RenderTargetView; -/// Represents the formt of LOD map color targets. -pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4]; +/// Represents the format of LOD shadow targets. +pub type LodTextureFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Unorm); //[gfx::format::U8Norm; 4]; + +/// Represents the format of LOD map color targets. +pub type LodColorFmt = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); //[gfx::format::U8Norm; 4]; /// A handle to a render color target as a resource. pub type TgtColorRes = gfx::handle::ShaderResourceView< @@ -129,6 +132,7 @@ impl Renderer { &assets::load_expect("voxygen.texture.noise"), Some(gfx::texture::FilterMethod::Bilinear), Some(gfx::texture::WrapMode::Tile), + None, )?; Ok(Self { @@ -424,13 +428,14 @@ impl Renderer { image: &image::DynamicImage, filter_method: Option, wrap_mode: Option, + border: Option, ) -> Result, RenderError> where F::Surface: gfx::format::TextureSurface, F::Channel: gfx::format::TextureChannel, ::DataType: Copy, { - Texture::new(&mut self.factory, image, filter_method, wrap_mode) + Texture::new(&mut self.factory, image, filter_method, wrap_mode, border) } /// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the @@ -533,7 +538,7 @@ impl Renderer { lights: &Consts, shadows: &Consts, map: &Texture, - horizon: &Texture, + horizon: &Texture, ) { self.encoder.draw( &gfx::Slice { @@ -570,7 +575,7 @@ impl Renderer { lights: &Consts, shadows: &Consts, map: &Texture, - horizon: &Texture, + horizon: &Texture, ) { self.encoder.draw( &gfx::Slice { @@ -606,7 +611,7 @@ impl Renderer { lights: &Consts, shadows: &Consts, map: &Texture, - horizon: &Texture, + horizon: &Texture, waves: &Texture, ) { self.encoder.draw( @@ -644,7 +649,7 @@ impl Renderer { lights: &Consts, shadows: &Consts, map: &Texture, - horizon: &Texture, + horizon: &Texture, ) { self.encoder.draw( &gfx::Slice { @@ -678,7 +683,7 @@ impl Renderer { globals: &Consts, locals: &Consts, map: &Texture, - horizon: &Texture, + horizon: &Texture, ) { self.encoder.draw( &gfx::Slice { diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 141eeb9a25..3f83ca37c6 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -31,6 +31,7 @@ where image: &DynamicImage, filter_method: Option, wrap_mode: Option, + border: Option, ) -> Result { let (tex, srv) = factory .create_texture_immutable_u8::( @@ -44,13 +45,15 @@ where ) .map_err(|err| RenderError::CombinedError(err))?; + let mut sampler_info = gfx::texture::SamplerInfo::new( + filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), + wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), + ); + sampler_info.border = border.unwrap_or([0.0, 0.0, 0.0, 1.0].into()); Ok(Self { tex, srv, - sampler: factory.create_sampler(gfx::texture::SamplerInfo::new( - filter_method.unwrap_or(gfx::texture::FilterMethod::Scale), - wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp), - )), + sampler: factory.create_sampler(sampler_info), }) } diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index b41e1a3b50..e3f1e3cf96 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -70,7 +70,7 @@ impl Camera { /// and position of the camera. pub fn compute_dependents(&mut self, terrain: &impl ReadVol) { let dist = { - /* let (start, end) = ( + /*let (start, end) = ( self.focus + (Vec3::new( -f32::sin(self.ori.x) * f32::cos(self.ori.y), diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 4b0df1b498..dc8e01c3d5 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -1,34 +1,45 @@ use crate::{ render::{ pipelines::lod_terrain::{Locals, Vertex}, - Consts, FilterMethod, Globals, LodColorFmt, LodTerrainPipeline, Mesh, Model, Quad, - Renderer, Texture, + Consts, FilterMethod, Globals, LodColorFmt, LodTerrainPipeline, LodTextureFmt, Mesh, Model, + Quad, Renderer, Texture, WrapMode, }, settings::Settings, }; use client::Client; -use common::spiral::Spiral2d; +use common::{spiral::Spiral2d, util::srgba_to_linear}; use vek::*; pub struct Lod { model: Option<(u32, Model)>, locals: Consts, pub map: Texture, - pub horizon: Texture, + pub horizon: Texture, tgt_detail: u32, } impl Lod { pub fn new(renderer: &mut Renderer, client: &Client, settings: &Settings) -> Self { + let water_color = /*Rgba::new(0.2, 0.5, 1.0, 0.0)*/srgba_to_linear(Rgba::new(0.0, 0.25, 0.5, 0.0)/* * 0.5*/); Self { model: None, locals: renderer.create_consts(&[Locals::default()]).unwrap(), map: renderer - .create_texture(&client.lod_base, Some(FilterMethod::Bilinear), None) + .create_texture( + &client.lod_base, + Some(FilterMethod::Bilinear), + Some(WrapMode::Border), + Some([water_color.r, water_color.g, water_color.b, water_color.a].into()), + ) .expect("Failed to generate map texture"), horizon: renderer - .create_texture(&client.lod_horizon, Some(FilterMethod::Trilinear), None) - .expect("Failed to generate horizon texture"), + .create_texture( + &client.lod_horizon, + Some(FilterMethod::Trilinear), + Some(WrapMode::Border), + Some([0.0, 1.0, 0.0, 1.0].into()), + ) + .expect("Failed to generate map texture"), tgt_detail: settings.graphics.lod_detail.max(100).min(2500), } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index ce2795aab9..1d393f6757 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -65,6 +65,10 @@ pub struct Scene { terrain: Terrain, pub lod: Lod, loaded_distance: f32, + /// x coordinate is sea level (minimum height for any land chunk), and y + /// coordinate is the maximum height above the mnimimum for any land + /// chunk. + map_bounds: Vec2, select_pos: Option>, figure_mgr: FigureMgr, @@ -110,6 +114,7 @@ impl Scene { terrain: Terrain::new(renderer), lod: Lod::new(renderer, client, settings), loaded_distance: 0.0, + map_bounds: client.world_map.2, select_pos: None, figure_mgr: FigureMgr::new(), @@ -340,6 +345,7 @@ impl Scene { cam_pos, self.camera.get_focus_pos(), self.loaded_distance, + self.map_bounds, scene_data.state.get_time_of_day(), scene_data.state.get_time(), renderer.get_resolution(), diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index be39ed184b..c8837429c3 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -62,6 +62,7 @@ pub struct Scene { skybox: Skybox, postprocess: PostProcess, lod: Lod, + map_bounds: Vec2, backdrop: Option<(Model, FigureState)>, figure_model_cache: FigureModelCache, @@ -110,6 +111,7 @@ impl Scene { .unwrap(), }, lod: Lod::new(renderer, client, settings), + map_bounds: client.world_map.2, figure_model_cache: FigureModelCache::new(), figure_state: FigureState::new(renderer, CharacterSkeleton::new()), @@ -166,6 +168,7 @@ impl Scene { cam_pos, } = self.camera.dependents(); const VD: f32 = 115.0; // View Distance + // const MAP_BOUNDS: Vec2 = Vec2::new(140.0, 2048.0); const TIME: f64 = 43200.0; // 12 hours*3600 seconds if let Err(err) = renderer.update_consts(&mut self.globals, &[Globals::new( view_mat, @@ -173,6 +176,7 @@ impl Scene { cam_pos, self.camera.get_focus_pos(), VD, + self.map_bounds, //MAP_BOUNDS, TIME, scene_data.time, renderer.get_resolution(), diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 5d7e6403b2..ac72b88091 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1074,6 +1074,7 @@ impl Terrain { &assets::load_expect("voxygen.texture.waves"), Some(gfx::texture::FilterMethod::Trilinear), Some(gfx::texture::WrapMode::Tile), + None, ) .expect("Failed to create wave texture"), phantom: PhantomData, diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index a3d7d1095a..eb51bcefe3 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1312,10 +1312,16 @@ impl WorldSim { let mut map_config = MapConfig::default(); map_config.lgain = 1.0; // Build a horizon map. - let scale_angle = - |angle: Alt| (angle.atan() * ::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 scale_angle = |angle: Alt| { + (/* 0.0.max( */angle /* ) */ + .atan() + * ::FRAC_2_PI() + * 255.0) + .floor() as u8 + }; + let scale_height = |height: Alt| { + (/* 0.0.max( */height/*)*/ as Alt * 255.0 / self.max_height as Alt).floor() as u8 + }; let samples_data = { let column_sample = ColumnGen::new(self); @@ -1340,6 +1346,7 @@ impl WorldSim { 32.0, )); sample.basement += sample.alt - alt; + // sample.water_level = CONFIG.sea_level.max(sample.water_level); Some(sample) }, diff --git a/world/src/sim/util.rs b/world/src/sim/util.rs index d25c115b45..3bb45acde0 100644 --- a/world/src/sim/util.rs +++ b/world/src/sim/util.rs @@ -416,7 +416,7 @@ pub fn get_horizon_map( let wposi = bounds.min + Vec2::new((posi % map_size.x) as i32, (posi / map_size.x) as i32); if wposi.reduce_partial_min() < 0 - || wposi.y as usize >= WORLD_SIZE.x + || wposi.x as usize >= WORLD_SIZE.x || wposi.y as usize >= WORLD_SIZE.y { return (to_angle(F::zero()), to_height(F::zero()));