diff --git a/Cargo.lock b/Cargo.lock index 9ccee0c8ce..e33cec52ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4908,6 +4908,7 @@ dependencies = [ "log 0.4.8", "num 0.2.1", "num_cpus", + "rayon", "specs", "uvth", "vek 0.10.0", diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index c408aac687..7a9055fd78 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -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; diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 63de7173ff..23360a25b2 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -1,5 +1,7 @@ #version 330 core +// https://www.shadertoy.com/view/XdsyWf + #include #include @@ -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); + 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; @@ -133,11 +146,12 @@ void main() { // vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, false, _clouds) * f_light; // 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); } diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index c9a2e64474..36587b24b7 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -1,6 +1,19 @@ #include +#include 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; } diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 7109144695..9565b27303 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -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 = diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index 40b39b7b85..9654e7fb6b 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -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); } diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 8b2eb7e0cc..01e99f45aa 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -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); } diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 2a57206683..f07ed32810 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -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); diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 04d9c6b412..ab2dea79e5 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -11,6 +11,7 @@ out vec4 tgt_color; #include #include +#include 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); } diff --git a/client/Cargo.toml b/client/Cargo.toml index 2b76763b42..b5fa0b31b9 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -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"] } diff --git a/client/src/lib.rs b/client/src/lib.rs index 8a623f0a67..fe8d946b0d 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -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, + /// 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, /// 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,131 +108,137 @@ 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()? { - ServerMsg::InitialSync { - entity_package, - server_info, - time_of_day, - world_map, - } => { - // TODO: Display that versions don't match in Voxygen - if server_info.git_hash != common::util::GIT_HASH.to_string() { - log::warn!( - "Server is running {}[{}], you are running {}[{}], versions might be \ - incompatible!", - server_info.git_hash, - server_info.git_date, - common::util::GIT_HASH.to_string(), - common::util::GIT_DATE.to_string(), - ); - } + let (state, entity, server_info, lod_base, lod_horizon, world_map) = + match postbox.next_message()? { + ServerMsg::InitialSync { + entity_package, + server_info, + time_of_day, + world_map, + } => { + // TODO: Display that versions don't match in Voxygen + if server_info.git_hash != common::util::GIT_HASH.to_string() { + log::warn!( + "Server is running {}[{}], you are running {}[{}], versions might be \ + incompatible!", + server_info.git_hash, + server_info.git_date, + common::util::GIT_HASH.to_string(), + common::util::GIT_DATE.to_string(), + ); + } - log::debug!("Auth Server: {:?}", server_info.auth_provider); + log::debug!("Auth Server: {:?}", server_info.auth_provider); - // Initialize `State` - let mut state = State::default(); - // Client-only components - state - .ecs_mut() - .register::>(); + // Initialize `State` + let mut state = State::default(); + // Client-only components + state + .ecs_mut() + .register::>(); - let entity = state.ecs_mut().apply_entity_package(entity_package); - *state.ecs_mut().write_resource() = time_of_day; + let entity = state.ecs_mut().apply_entity_package(entity_package); + *state.ecs_mut().write_resource() = time_of_day; - let map_size = world_map.dimensions; - let max_height = world_map.max_height; - let rgba = world_map.rgba; - assert_eq!(rgba.len(), (map_size.x * map_size.y) as usize); - let [west, east] = world_map.horizons; - let scale_angle = - |a: u8| (a as Alt / 255.0 * ::FRAC_PI_2()).tan(); - let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt; + let map_size = world_map.dimensions; + let max_height = world_map.max_height; + let rgba = world_map.rgba; + assert_eq!(rgba.len(), (map_size.x * map_size.y) as usize); + let [west, east] = world_map.horizons; + let scale_angle = + |a: u8| (a as Alt / 255.0 * ::FRAC_PI_2()).tan(); + 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<_>)| { - ( - angles.into_iter().map(scale_angle).collect::>(), - heights.into_iter().map(scale_height).collect::>(), - ) - }; - let horizons = [unzip_horizons(west), unzip_horizons(east)]; + log::debug!("Preparing image..."); + let unzip_horizons = |(angles, heights): &(Vec<_>, Vec<_>)| { + ( + angles.iter().copied().map(scale_angle).collect::>(), + heights + .iter() + .copied() + .map(scale_height) + .collect::>(), + ) + }; + let horizons = [unzip_horizons(&west), unzip_horizons(&east)]; - // Redraw map (with shadows this time). - let mut world_map = vec![0u32; rgba.len()]; - let mut map_config = world::sim::MapConfig::default(); - map_config.lgain = 1.0; - map_config.gain = max_height; - map_config.horizons = Some(&horizons); - map_config.focus.z = 0.0; - let rescale_height = |h: Alt| (h / max_height as Alt) as f32; - let bounds_check = |pos: Vec2| { - pos.reduce_partial_min() >= 0 - && pos.x < map_size.x as i32 - && pos.y < map_size.y as i32 - }; - map_config.generate( - |pos| { - let (rgba, downhill_wpos) = if bounds_check(pos) { - let posi = pos.y as usize * map_size.x as usize + pos.x as usize; - let [r, g, b, a] = rgba[posi].to_le_bytes(); - // Compute downhill. - let downhill = { - let mut best = -1; - let mut besth = a; - // TODO: Fix to work for dynamic WORLD_SIZE (i.e. map_size). - for nposi in neighbors(posi) { - let nbh = rgba[nposi].to_le_bytes()[3]; - if nbh < besth { - besth = nbh; - best = nposi as isize; + // Redraw map (with shadows this time). + let mut world_map = vec![0u32; rgba.len()]; + let mut map_config = world::sim::MapConfig::default(); + 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| { + pos.reduce_partial_min() >= 0 + && pos.x < map_size.x as i32 + && pos.y < map_size.y as i32 + }; + map_config.generate( + |pos| { + let (rgba, downhill_wpos) = if bounds_check(pos) { + let posi = pos.y as usize * map_size.x as usize + pos.x as usize; + let [r, g, b, a] = rgba[posi].to_le_bytes(); + // Compute downhill. + let downhill = { + let mut best = -1; + let mut besth = a; + // TODO: Fix to work for dynamic WORLD_SIZE (i.e. map_size). + for nposi in neighbors(posi) { + let nbh = rgba[nposi].to_le_bytes()[3]; + if nbh < besth { + besth = nbh; + best = nposi as isize; + } } - } - best - }; - let downhill_wpos = if downhill < 0 { - None + best + }; + let downhill_wpos = if downhill < 0 { + None + } else { + Some( + Vec2::new( + (downhill as usize % map_size.x as usize) as i32, + (downhill as usize / map_size.x as usize) as i32, + ) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32), + ) + }; + (Rgba::new(r, g, b, a), downhill_wpos) } else { - Some( - Vec2::new( - (downhill as usize % map_size.x as usize) as i32, - (downhill as usize / map_size.x as usize) as i32, - ) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32), - ) + (Rgba::zero(), None) }; - (Rgba::new(r, g, b, a), downhill_wpos) - } else { - (Rgba::zero(), None) - }; - let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32); - let downhill_wpos = downhill_wpos - .unwrap_or(wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32)); - let alt = rescale_height(scale_height(rgba.a)); - world::sim::MapSample { - rgb: Rgb::from(rgba), - alt: alt as Alt, - downhill_wpos, - connections: None, - } - }, - |wpos| { - let pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32); - rescale_height(if bounds_check(pos) { - let posi = pos.y as usize * map_size.x as usize + pos.x as usize; - scale_height(rgba[posi].to_le_bytes()[3]) - } else { - 0.0 - }) - }, - |pos, (r, g, b, a)| { - world_map[pos.y * map_size.x as usize + pos.x] = - u32::from_le_bytes([r, g, b, a]); - }, - ); - let make_raw = |rgba| -> Result<_, Error> { - let mut raw = vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/]; - LittleEndian::write_u32_into(rgba, &mut raw); - Ok(Arc::new( - image::DynamicImage::ImageRgba8({ + let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32); + let downhill_wpos = downhill_wpos + .unwrap_or(wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32)); + let alt = rescale_height(scale_height(rgba.a)); + world::sim::MapSample { + rgb: Rgb::from(rgba), + alt: alt as Alt, + downhill_wpos, + connections: None, + } + }, + |wpos| { + let pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32); + rescale_height(if bounds_check(pos) { + let posi = pos.y as usize * map_size.x as usize + pos.x as usize; + scale_height(rgba[posi].to_le_bytes()[3]) + } else { + 0.0 + }) + }, + |pos, (r, g, b, a)| { + world_map[pos.y * map_size.x as usize + pos.x] = + u32::from_le_bytes([r, g, b, a]); + }, + ); + let make_raw = |rgba| -> Result<_, Error> { + let mut raw = vec![0u8; 4 * world_map.len()/*map_size.x * map_size.y*/]; + LittleEndian::write_u32_into(rgba, &mut raw); + Ok(Arc::new( + image::DynamicImage::ImageRgba8({ // Should not fail if the dimensions are correct. let map = image::ImageBuffer::from_raw(map_size.x, map_size.y, raw); @@ -236,17 +247,29 @@ impl Client { // Flip the image, since Voxygen uses an orientation where rotation from // positive x axis to positive y axis is counterclockwise around the z axis. .flipv(), - )) - }; - let lod_base = make_raw(&rgba)?; - let world_map = make_raw(&world_map)?; - log::debug!("Done preparing image..."); + )) + }; + 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::>(); + let lod_horizon = make_raw(&horizons)?; + log::debug!("Done preparing image..."); - (state, entity, server_info, lod_base, (world_map, map_size)) - }, - ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers), - _ => return Err(Error::ServerWentMad), - }; + ( + state, + entity, + server_info, + lod_base, + lod_horizon, + (world_map, map_size), + ) + }, + ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers), + _ => return Err(Error::ServerWentMad), + }; postbox.send_message(ClientMsg::Ping); @@ -262,6 +285,7 @@ impl Client { server_info, world_map, lod_base, + lod_horizon, player_list: HashMap::new(), postbox, diff --git a/voxygen/src/render/pipelines/lod_terrain.rs b/voxygen/src/render/pipelines/lod_terrain.rs index 83ca581c0b..e1213adc9a 100644 --- a/voxygen/src/render/pipelines/lod_terrain.rs +++ b/voxygen/src/render/pipelines/lod_terrain.rs @@ -23,6 +23,7 @@ gfx_defines! { locals: gfx::ConstantBuffer = "u_locals", globals: gfx::ConstantBuffer = "u_globals", map: gfx::TextureSampler<[f32; 4]> = "t_map", + horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", noise: gfx::TextureSampler = "t_noise", diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 6899a8eb18..41eb8edd53 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -28,6 +28,9 @@ gfx_defines! { lights: gfx::ConstantBuffer = "u_lights", shadows: gfx::ConstantBuffer = "u_shadows", + map: gfx::TextureSampler<[f32; 4]> = "t_map", + horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon", + noise: gfx::TextureSampler = "t_noise", tgt_color: gfx::RenderTarget = "tgt_color", diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 0939adc730..efcd190b92 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -557,6 +557,8 @@ impl Renderer { locals: &Consts, lights: &Consts, shadows: &Consts, + 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, locals: &Consts, 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(), }, diff --git a/voxygen/src/scene/lod.rs b/voxygen/src/scene/lod.rs index 48f6f5c5a4..7c6ecc8dd5 100644 --- a/voxygen/src/scene/lod.rs +++ b/voxygen/src/scene/lod.rs @@ -12,7 +12,8 @@ use vek::*; pub struct Lod { model: Option<(u32, Model)>, locals: Consts, - 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) { 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); } } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index ea7e8730a8..bbee0b6634 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -395,6 +395,7 @@ impl Scene { &self.globals, &self.lights, &self.shadows, + &self.lod, self.camera.get_focus_pos(), ); self.figure_mgr.render( diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 1fd3fadf4f..ed3b6cef4b 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -6,7 +6,7 @@ use crate::{ }, }; -use super::SceneData; +use super::{Lod, SceneData}; use common::{ assets, figure::Segment, @@ -1393,6 +1393,7 @@ impl Terrain { globals: &Consts, lights: &Consts, shadows: &Consts, + lod: &Lod, focus_pos: Vec3, ) { let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { @@ -1415,6 +1416,8 @@ impl Terrain { &chunk.locals, lights, shadows, + &lod.map, + &lod.horizon, ); } } diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index a994baf712..105d4b8a87 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -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>>, wpos: Vec2, diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index dafbbda996..4f87c53f04 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1316,6 +1316,42 @@ impl WorldSim { |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 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::>() + .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::>() - .into_boxed_slice() - }; - let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y]; // TODO: Parallelize again. let config = MapConfig {