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", "log 0.4.8",
"num 0.2.1", "num 0.2.1",
"num_cpus", "num_cpus",
"rayon",
"specs", "specs",
"uvth", "uvth",
"vek 0.10.0", "vek 0.10.0",

View File

@ -29,21 +29,25 @@ out vec4 tgt_color;
void main() { void main() {
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); 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 surf_color = /*srgb_to_linear*/(model_col.rgb * f_col);
vec3 k_a = surf_color; vec3 k_a = vec3(0.5);
vec3 k_d = 0.5 * surf_color; vec3 k_d = vec3(0.5);
vec3 k_s = 0.5 * surf_color; vec3 k_s = vec3(0.5);
float alpha = 2.0; float alpha = 2.0;
vec3 emitted_light, reflected_light; vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm); 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 point_light = light_at(f_pos, f_norm);
// vec3 light, diffuse_light, ambient_light; // 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, 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); // 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; // diffuse_light += point_light;
// reflected_light += point_light; // reflected_light += point_light;
// vec3 surf_color = illuminate(srgb_to_linear(model_col.rgb * f_col), light, diffuse_light, ambient_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); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; vec4 clouds;

View File

@ -1,5 +1,7 @@
#version 330 core #version 330 core
// https://www.shadertoy.com/view/XdsyWf
#include <globals.glsl> #include <globals.glsl>
#include <random.glsl> #include <random.glsl>
@ -66,6 +68,8 @@ void main() {
vec3 f_norm = normals[norm_axis + norm_dir]; vec3 f_norm = normals[norm_axis + norm_dir];
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); 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); float frag_dist = length(f_pos - cam_pos.xyz);
vec3 b_norm; vec3 b_norm;
@ -95,22 +99,31 @@ void main() {
vec4 _clouds; 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 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 surf_color = /*srgb_to_linear*/(vec3(0.2, 0.5, 1.0));
vec3 k_a = surf_color; vec3 k_a = vec3(1.0);
vec3 k_d = vec3(1.0); vec3 k_d = surf_color;
vec3 k_s = reflect_color; vec3 k_s = 2.0 * reflect_color;
float alpha = 0.255; float alpha = 0.255;
vec3 emitted_light, reflected_light; vec3 emitted_light, reflected_light;
// vec3 light, diffuse_light, ambient_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 // 0 = 100% reflection, 1 = translucent water
float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag), 0.5); float passthrough = pow(dot(faceforward(f_norm, f_norm, cam_to_frag/*-view_dir*/), -cam_to_frag/*view_dir*/), 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); vec3 diffuse_light_point = vec3(0.0);
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); 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); // get_sun_diffuse(norm, time_of_day.x, light, diffuse_light, ambient_light, 0.0);
// diffuse_light *= f_light * point_shadow; // diffuse_light *= f_light * point_shadow;
// ambient_light *= f_light * point_shadow; // ambient_light *= f_light * point_shadow;
@ -119,7 +132,7 @@ void main() {
// diffuse_light += point_light; // diffuse_light += point_light;
// reflected_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; // 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); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; 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; // vec3 reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.25, false, _clouds) * f_light;
// Tint // Tint
// reflect_color = mix(reflect_color, surf_color, 0.6); // 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 = 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 = 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 = surf_color; // 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 <random.glsl>
#include <sky.glsl>
uniform sampler2D t_map; 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 pos_to_uv(vec2 pos) {
vec2 uv_pos = (pos + 16) / 32768.0; vec2 uv_pos = (pos + 16) / 32768.0;
@ -52,7 +65,7 @@ vec4 textureBicubic(sampler2D sampler, vec2 texCoords) {
} }
float alt_at(vec2 pos) { 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; //+ (texture(t_noise, pos * 0.002).x - 0.5) * 64.0;
return 0.0 return 0.0
@ -61,6 +74,79 @@ float alt_at(vec2 pos) {
+ texture(t_noise, pos * 0.003).x * 30.0; + 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) { vec2 splay(vec2 pos) {
return pos * pow(length(pos) * 0.5, 3.0); 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) { vec3 lod_col(vec2 pos) {
//return vec3(0, 0.5, 0); //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; //+ (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)); 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) { float get_sun_brightness(vec3 sun_dir) {
return max(-sun_dir.z + 0.6, 0.0) * 0.9; 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). // 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). // 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; emitted_light = k_a * (ambient_sides + vec3(SUN_AMBIANCE * sun_light + moon_light)) + PERSISTENT_AMBIANCE;
// TODO: Add shadows. // TODO: Add shadows.
reflected_light = reflected_light =
sun_chroma * light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha) + 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; /* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE;
diffuse_light = diffuse_light =

View File

@ -11,9 +11,9 @@ vec3 srgb_to_linear(vec3 srgb) {
// //
// Note: norm, dir, light_dir must all be normalizd. // 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) { 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); float ndotL = max(dot(norm, -light_dir), 0.0);
if (ndotL > 0.0) { if (ndotL > 0.0/* && dot(s_norm, -light_dir) > 0.0*/) {
vec3 H = normalize(-light_dir + dir); vec3 H = normalize(light_dir + dir);
// (k_d * (L ⋅ N) + k_s * (R ⋅ V)^α) // (k_d * (L ⋅ N) + k_s * (R ⋅ V)^α)
return k_d * ndotL + k_s * pow(max(dot(norm, H), 0.0), alpha * 4.0); 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 f_col = lod_col(f_pos.xy);
vec3 emitted_light, reflected_light; 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); 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; // 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; // vec3 light, diffuse_light, ambient_light;
// get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0); // 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(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); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; 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 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 = 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; //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); tgt_color = vec4(color, 1.0);
} }

View File

@ -17,16 +17,19 @@ const float FADE_DIST = 32.0;
void main() { void main() {
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); 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 surf_color = /*srgb_to_linear*/(f_col);
vec3 k_a = surf_color; vec3 k_a = vec3(1.0);
vec3 k_d = 0.5 * surf_color; vec3 k_d = vec3(0.5);
vec3 k_s = 0.5 * surf_color; vec3 k_s = vec3(0.5);
float alpha = 2.0; float alpha = 2.0;
vec3 emitted_light, reflected_light; vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm); 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 light, diffuse_light, ambient_light;
// vec3 emitted_light, reflected_light; // vec3 emitted_light, reflected_light;
@ -34,7 +37,7 @@ void main() {
// vec3 point_light = light_at(f_pos, f_norm); // vec3 point_light = light_at(f_pos, f_norm);
// vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); // vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0));
// vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); // 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); // 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); // float point_shadow = shadow_at(f_pos, f_norm);
// diffuse_light *= f_light * point_shadow; // diffuse_light *= f_light * point_shadow;
@ -42,8 +45,8 @@ void main() {
// light += point_light; // light += point_light;
// diffuse_light += point_light; // diffuse_light += point_light;
// reflected_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); lights_at(f_pos, f_norm, cam_to_frag, k_a, k_d, k_s, alpha, emitted_light, reflected_light);
surf_color = illuminate(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); // vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light);
float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); 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 <sky.glsl>
#include <light.glsl> #include <light.glsl>
#include <lod.glsl>
void main() { void main() {
// First 3 normals are negative, next 3 are positive // 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 f_norm = normals[(f_pos_norm >> 29) & 0x7u];
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); 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 surf_color = /*srgb_to_linear*/(f_col);
vec3 k_a = 0.5 * surf_color; vec3 k_a = vec3(1.0);
vec3 k_d = 0.5 * surf_color; vec3 k_d = vec3(0.5);
vec3 k_s = 0.5 * surf_color; vec3 k_s = vec3(0.5);
float alpha = 2.0; float alpha = 2.0;
vec3 emitted_light, reflected_light; vec3 emitted_light, reflected_light;
float point_shadow = shadow_at(f_pos, f_norm); 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); // float point_shadow = shadow_at(f_pos, f_norm);
// vec3 point_light = light_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 // light_reflection_factorplight_reflection_factor
// vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light); // 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); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x);
vec4 clouds; 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 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 = surf_color;
// vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a); vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
tgt_color = vec4(color, 1.0); tgt_color = vec4(color, 1.0);
} }

View File

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

View File

@ -34,6 +34,7 @@ use hashbrown::HashMap;
use image::DynamicImage; use image::DynamicImage;
use log::{error, warn}; use log::{error, warn};
use num::traits::FloatConst; use num::traits::FloatConst;
use rayon::prelude::*;
use std::{ use std::{
net::SocketAddr, net::SocketAddr,
sync::Arc, sync::Arc,
@ -72,6 +73,10 @@ pub struct Client {
/// shadows, rivers, and probably foliage, cities, roads, and other /// shadows, rivers, and probably foliage, cities, roads, and other
/// structures. /// structures.
pub lod_base: Arc<DynamicImage>, 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 /// 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 /// 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 /// 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)?; let mut postbox = PostBox::to(addr)?;
// Wait for initial sync // 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) =
ServerMsg::InitialSync { match postbox.next_message()? {
entity_package, ServerMsg::InitialSync {
server_info, entity_package,
time_of_day, server_info,
world_map, 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() { // TODO: Display that versions don't match in Voxygen
log::warn!( if server_info.git_hash != common::util::GIT_HASH.to_string() {
"Server is running {}[{}], you are running {}[{}], versions might be \ log::warn!(
incompatible!", "Server is running {}[{}], you are running {}[{}], versions might be \
server_info.git_hash, incompatible!",
server_info.git_date, server_info.git_hash,
common::util::GIT_HASH.to_string(), server_info.git_date,
common::util::GIT_DATE.to_string(), 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` // Initialize `State`
let mut state = State::default(); let mut state = State::default();
// Client-only components // Client-only components
state state
.ecs_mut() .ecs_mut()
.register::<comp::Last<comp::CharacterState>>(); .register::<comp::Last<comp::CharacterState>>();
let entity = state.ecs_mut().apply_entity_package(entity_package); let entity = state.ecs_mut().apply_entity_package(entity_package);
*state.ecs_mut().write_resource() = time_of_day; *state.ecs_mut().write_resource() = time_of_day;
let map_size = world_map.dimensions; let map_size = world_map.dimensions;
let max_height = world_map.max_height; let max_height = world_map.max_height;
let rgba = world_map.rgba; let rgba = world_map.rgba;
assert_eq!(rgba.len(), (map_size.x * map_size.y) as usize); assert_eq!(rgba.len(), (map_size.x * map_size.y) as usize);
let [west, east] = world_map.horizons; let [west, east] = world_map.horizons;
let scale_angle = let scale_angle =
|a: u8| (a as Alt / 255.0 * <Alt as FloatConst>::FRAC_PI_2()).tan(); |a: u8| (a as Alt / 255.0 * <Alt as FloatConst>::FRAC_PI_2()).tan();
let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt; let scale_height = |h: u8| h as Alt / 255.0 * max_height as Alt;
log::debug!("Preparing image..."); 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<_>>(), angles.iter().copied().map(scale_angle).collect::<Vec<_>>(),
heights.into_iter().map(scale_height).collect::<Vec<_>>(), heights
) .iter()
}; .copied()
let horizons = [unzip_horizons(west), unzip_horizons(east)]; .map(scale_height)
.collect::<Vec<_>>(),
)
};
let horizons = [unzip_horizons(&west), unzip_horizons(&east)];
// Redraw map (with shadows this time). // Redraw map (with shadows this time).
let mut world_map = vec![0u32; rgba.len()]; let mut world_map = vec![0u32; rgba.len()];
let mut map_config = world::sim::MapConfig::default(); let mut map_config = world::sim::MapConfig::default();
map_config.lgain = 1.0; map_config.lgain = 1.0;
map_config.gain = max_height; map_config.gain = max_height;
map_config.horizons = Some(&horizons); map_config.horizons = Some(&horizons);
map_config.focus.z = 0.0; // map_config.light_direction = Vec3::new(1.0, -1.0, 0.0);
let rescale_height = |h: Alt| (h / max_height as Alt) as f32; map_config.focus.z = 0.0;
let bounds_check = |pos: Vec2<i32>| { let rescale_height = |h: Alt| (h / max_height as Alt) as f32;
pos.reduce_partial_min() >= 0 let bounds_check = |pos: Vec2<i32>| {
&& pos.x < map_size.x as i32 pos.reduce_partial_min() >= 0
&& pos.y < map_size.y as i32 && pos.x < map_size.x as i32
}; && pos.y < map_size.y as i32
map_config.generate( };
|pos| { map_config.generate(
let (rgba, downhill_wpos) = if bounds_check(pos) { |pos| {
let posi = pos.y as usize * map_size.x as usize + pos.x as usize; let (rgba, downhill_wpos) = if bounds_check(pos) {
let [r, g, b, a] = rgba[posi].to_le_bytes(); let posi = pos.y as usize * map_size.x as usize + pos.x as usize;
// Compute downhill. let [r, g, b, a] = rgba[posi].to_le_bytes();
let downhill = { // Compute downhill.
let mut best = -1; let downhill = {
let mut besth = a; let mut best = -1;
// TODO: Fix to work for dynamic WORLD_SIZE (i.e. map_size). let mut besth = a;
for nposi in neighbors(posi) { // TODO: Fix to work for dynamic WORLD_SIZE (i.e. map_size).
let nbh = rgba[nposi].to_le_bytes()[3]; for nposi in neighbors(posi) {
if nbh < besth { let nbh = rgba[nposi].to_le_bytes()[3];
besth = nbh; if nbh < besth {
best = nposi as isize; besth = nbh;
best = nposi as isize;
}
} }
} best
best };
}; let downhill_wpos = if downhill < 0 {
let downhill_wpos = if downhill < 0 { None
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 { } else {
Some( (Rgba::zero(), None)
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) let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
} else { let downhill_wpos = downhill_wpos
(Rgba::zero(), None) .unwrap_or(wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32));
}; let alt = rescale_height(scale_height(rgba.a));
let wpos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32); world::sim::MapSample {
let downhill_wpos = downhill_wpos rgb: Rgb::from(rgba),
.unwrap_or(wpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32)); alt: alt as Alt,
let alt = rescale_height(scale_height(rgba.a)); downhill_wpos,
world::sim::MapSample { connections: None,
rgb: Rgb::from(rgba), }
alt: alt as Alt, },
downhill_wpos, |wpos| {
connections: None, 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;
|wpos| { scale_height(rgba[posi].to_le_bytes()[3])
let pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e / f as i32); } else {
rescale_height(if bounds_check(pos) { 0.0
let posi = pos.y as usize * map_size.x as usize + pos.x as usize; })
scale_height(rgba[posi].to_le_bytes()[3]) },
} else { |pos, (r, g, b, a)| {
0.0 world_map[pos.y * map_size.x as usize + pos.x] =
}) u32::from_le_bytes([r, g, b, a]);
}, },
|pos, (r, g, b, a)| { );
world_map[pos.y * map_size.x as usize + pos.x] = let make_raw = |rgba| -> Result<_, Error> {
u32::from_le_bytes([r, g, b, a]); 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(
let make_raw = |rgba| -> Result<_, Error> { image::DynamicImage::ImageRgba8({
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. // Should not fail if the dimensions are correct.
let map = let map =
image::ImageBuffer::from_raw(map_size.x, map_size.y, raw); 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 // Flip the image, since Voxygen uses an orientation where rotation from
// positive x axis to positive y axis is counterclockwise around the z axis. // positive x axis to positive y axis is counterclockwise around the z axis.
.flipv(), .flipv(),
)) ))
}; };
let lod_base = make_raw(&rgba)?; let lod_base = make_raw(&rgba)?;
let world_map = make_raw(&world_map)?; let world_map = make_raw(&world_map)?;
log::debug!("Done preparing image..."); 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,
ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers), entity,
_ => return Err(Error::ServerWentMad), 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); postbox.send_message(ClientMsg::Ping);
@ -262,6 +285,7 @@ impl Client {
server_info, server_info,
world_map, world_map,
lod_base, lod_base,
lod_horizon,
player_list: HashMap::new(), player_list: HashMap::new(),
postbox, postbox,

View File

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

View File

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

View File

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

View File

@ -12,7 +12,8 @@ use vek::*;
pub struct Lod { pub struct Lod {
model: Option<(u32, Model<LodTerrainPipeline>)>, model: Option<(u32, Model<LodTerrainPipeline>)>,
locals: Consts<Locals>, locals: Consts<Locals>,
map: Texture, pub map: Texture,
pub horizon: Texture,
tgt_detail: u32, tgt_detail: u32,
} }
@ -24,6 +25,9 @@ impl Lod {
map: renderer map: renderer
.create_texture(&client.lod_base, Some(FilterMethod::Trilinear), None) .create_texture(&client.lod_base, Some(FilterMethod::Trilinear), None)
.expect("Failed to generate map texture"), .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), 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>) { pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
if let Some((_, model)) = self.model.as_ref() { 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.globals,
&self.lights, &self.lights,
&self.shadows, &self.shadows,
&self.lod,
self.camera.get_focus_pos(), self.camera.get_focus_pos(),
); );
self.figure_mgr.render( self.figure_mgr.render(

View File

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

View File

@ -36,7 +36,7 @@ impl<'a> BlockGen<'a> {
.as_ref() .as_ref()
} }
fn get_cliff_height( pub fn get_cliff_height(
column_gen: &ColumnGen<'a>, column_gen: &ColumnGen<'a>,
cache: &mut SmallCache<Option<ColumnSample<'a>>>, cache: &mut SmallCache<Option<ColumnSample<'a>>>,
wpos: Vec2<f32>, 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; |angle: Alt| (angle.atan() * <Alt as FloatConst>::FRAC_2_PI() * 255.0).floor() as u8;
let scale_height = let scale_height =
|height: Alt| (height as Alt * 255.0 / self.max_height as Alt).floor() as u8; |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( let horizons = get_horizon_map(
map_config.lgain, map_config.lgain,
Aabr { Aabr {
@ -1325,27 +1361,18 @@ impl WorldSim {
CONFIG.sea_level as Alt, CONFIG.sea_level as Alt,
(CONFIG.sea_level + self.max_height) as Alt, (CONFIG.sea_level + self.max_height) as Alt,
|posi| { |posi| {
let chunk = &self.chunks[posi]; /* let chunk = &self.chunks[posi];
chunk.alt.max(chunk.water_alt) as Alt 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), |a| scale_angle(a),
|h| scale_height(h), |h| scale_height(h),
) )
.unwrap(); .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]; let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y];
// TODO: Parallelize again. // TODO: Parallelize again.
let config = MapConfig { let config = MapConfig {