mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'treeco/new-map' into 'master'
A new map and clouds See merge request veloren/veloren!2007
This commit is contained in:
commit
15caf440e8
@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Reworked mindflayer to have unique attacks
|
- Reworked mindflayer to have unique attacks
|
||||||
- Glowing remains are now `Armor` instead of `Ingredients`.
|
- Glowing remains are now `Armor` instead of `Ingredients`.
|
||||||
|
|
||||||
|
- Generated a net world map
|
||||||
|
- Overhauled clouds for more verticality and performance
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -179,7 +179,7 @@ void main() {
|
|||||||
// Squared to account for prior saturation.
|
// Squared to account for prior saturation.
|
||||||
float f_light = 1.0;// pow(f_light, 1.5);
|
float f_light = 1.0;// pow(f_light, 1.5);
|
||||||
vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true);
|
vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true);
|
||||||
reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, time_of_day.x, 100000.0, 0.25);
|
reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, time_of_day.x, 100000.0, 0.1);
|
||||||
reflect_color *= f_light;
|
reflect_color *= f_light;
|
||||||
// /*const */vec3 water_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));
|
||||||
// /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0));
|
// /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0));
|
||||||
|
@ -1,92 +1,115 @@
|
|||||||
#include <random.glsl>
|
#include <random.glsl>
|
||||||
#include <lod.glsl>
|
#include <lod.glsl>
|
||||||
|
|
||||||
const float CLOUD_THRESHOLD = 0.27;
|
float falloff(float x) {
|
||||||
const float CLOUD_SCALE = 5.0;
|
return pow(max(x > 0.577 ? (0.3849 / x - 0.1) : (0.9 - x * x), 0.0), 4);
|
||||||
const float CLOUD_DENSITY = 150.0;
|
|
||||||
|
|
||||||
vec2 get_cloud_heights(vec2 pos) {
|
|
||||||
const float CLOUD_HALF_WIDTH = 300;
|
|
||||||
const float CLOUD_HEIGHT_VARIATION = 1500.0;
|
|
||||||
float cloud_alt = CLOUD_AVG_ALT + (texture(t_noise, pos.xy * 0.00005).x - 0.5) * CLOUD_HEIGHT_VARIATION;
|
|
||||||
#if (CLOUD_MODE > CLOUD_MODE_MINIMAL)
|
|
||||||
cloud_alt += (texture(t_noise, pos.xy * 0.001).x - 0.5) * 0.1 * CLOUD_HEIGHT_VARIATION;
|
|
||||||
#endif
|
|
||||||
return vec2(cloud_alt, CLOUD_HALF_WIDTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float emission_strength = clamp((sin(time_of_day.x / (3600 * 24)) - 0.8) / 0.1, 0, 1);
|
float emission_strength = clamp((sin(time_of_day.x / (3600 * 24)) - 0.8) / 0.1, 0, 1);
|
||||||
|
|
||||||
|
// Return the 'broad' density of the cloud at a position. This gets refined later with extra noise, but is important
|
||||||
|
// for computing light access.
|
||||||
|
float cloud_broad(vec3 pos) {
|
||||||
|
return 0.0
|
||||||
|
+ 2 * (noise_3d(pos / vec3(vec2(30000.0), 20000.0) / cloud_scale + 1000.0) - 0.5)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns vec4(r, g, b, density)
|
// Returns vec4(r, g, b, density)
|
||||||
vec4 cloud_at(vec3 pos, float dist, out vec3 emission) {
|
vec4 cloud_at(vec3 pos, float dist, out vec3 emission) {
|
||||||
// Natural attenuation of air (air naturally attenuates light that passes through it)
|
// Natural attenuation of air (air naturally attenuates light that passes through it)
|
||||||
// Simulate the atmosphere thinning as you get higher. Not physically accurate, but then
|
// Simulate the atmosphere thinning as you get higher. Not physically accurate, but then
|
||||||
// it can't be since Veloren's world is flat, not spherical.
|
// it can't be since Veloren's world is flat, not spherical.
|
||||||
float air = 0.00035 * clamp((10000.0 - pos.z) / 7000, 0, 1);
|
float atmosphere_alt = CLOUD_AVG_ALT + 40000.0;
|
||||||
|
float air = 0.00005 * clamp((atmosphere_alt - pos.z) / 20000, 0, 1);
|
||||||
|
|
||||||
// Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water)
|
// Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water)
|
||||||
float mist_min_alt = 0.5;
|
float mist_min_alt = 0.5;
|
||||||
#if (CLOUD_MODE > CLOUD_MODE_LOW)
|
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
||||||
mist_min_alt = (texture(t_noise, pos.xy * 0.00015).x - 0.5) * 1.25 + 0.5;
|
mist_min_alt = (texture(t_noise, pos.xy / 50000.0).x - 0.5) * 1.5 + 0.5;
|
||||||
#endif
|
#endif
|
||||||
mist_min_alt *= 250;
|
mist_min_alt = view_distance.z * 1.5 * (1.0 + mist_min_alt * 0.5);
|
||||||
const float MIST_FADE_HEIGHT = 500;
|
const float MIST_FADE_HEIGHT = 500;
|
||||||
float mist = 0.00125 * pow(clamp(1.0 - (pos.z - mist_min_alt) / MIST_FADE_HEIGHT, 0.0, 1), 4.0) / (1.0 + pow(1.0 + dist / 20000.0, 2.0));
|
float mist = 0.00025 * pow(clamp(1.0 - (pos.z - mist_min_alt) / MIST_FADE_HEIGHT, 0.0, 1), 4.0) / (1.0 + pow(1.0 + dist / 20000.0, 2.0));
|
||||||
|
|
||||||
vec3 wind_pos = vec3(pos.xy + wind_offset, pos.z);
|
float alt = alt_at(pos.xy - focus_off.xy);
|
||||||
|
|
||||||
|
vec3 wind_pos = vec3(pos.xy + wind_offset, pos.z + noise_2d(pos.xy / 20000) * 500);
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
float cloud_tendency = cloud_tendency_at(pos.xy);
|
float cloud_tendency = cloud_tendency_at(pos.xy);
|
||||||
float cloud = 0;
|
float cloud = 0;
|
||||||
|
|
||||||
vec2 cloud_attr = get_cloud_heights(wind_pos.xy);
|
//vec2 cloud_attr = get_cloud_heights(wind_pos.xy);
|
||||||
float cloud_factor = 0.0;
|
|
||||||
float turb_noise = 0.0;
|
|
||||||
float sun_access = 0.0;
|
float sun_access = 0.0;
|
||||||
float moon_access = 0.0;
|
float moon_access = 0.0;
|
||||||
float cloud_sun_access = 0.0;
|
float cloud_sun_access = 0.0;
|
||||||
float cloud_moon_access = 0.0;
|
float cloud_moon_access = 0.0;
|
||||||
|
float cloud_broad_a = 0.0;
|
||||||
|
float cloud_broad_b = 0.0;
|
||||||
// This is a silly optimisation but it actually nets us a fair few fps by skipping quite a few expensive calcs
|
// This is a silly optimisation but it actually nets us a fair few fps by skipping quite a few expensive calcs
|
||||||
if (cloud_tendency > 0 || mist > 0.0) {
|
if ((pos.z < CLOUD_AVG_ALT + 15000.0 && cloud_tendency > 0.0) || mist > 0.0) {
|
||||||
// Turbulence (small variations in clouds/mist)
|
// Turbulence (small variations in clouds/mist)
|
||||||
const float turb_speed = -1.0; // Turbulence goes the opposite way
|
const float turb_speed = -1.0; // Turbulence goes the opposite way
|
||||||
vec3 turb_offset = vec3(1, 1, 0) * time_of_day.x * turb_speed;
|
vec3 turb_offset = vec3(1, 1, 0) * time_of_day.x * turb_speed;
|
||||||
|
mist *= 0.5
|
||||||
|
+ 4 * (noise_2d(wind_pos.xy / 20000) - 0.5)
|
||||||
|
+ 1 * (noise_3d(wind_pos / 1000) - 0.5);
|
||||||
|
|
||||||
|
float CLOUD_DEPTH = (view_distance.w - view_distance.z) * 0.8;
|
||||||
|
const float CLOUD_DENSITY = 5.0;
|
||||||
|
const float CLOUD_ALT_VARI_WIDTH = 100000.0;
|
||||||
|
const float CLOUD_ALT_VARI_SCALE = 5000.0;
|
||||||
|
float cloud_alt = CLOUD_AVG_ALT + alt * 0.5;
|
||||||
|
|
||||||
|
cloud_broad_a = cloud_broad(wind_pos + sun_dir.xyz * 250);
|
||||||
|
cloud_broad_b = cloud_broad(wind_pos - sun_dir.xyz * 250);
|
||||||
|
cloud = cloud_tendency + (0.0
|
||||||
|
+ 24 * (cloud_broad_a + cloud_broad_b) * 0.5
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_MINIMAL)
|
#if (CLOUD_MODE >= CLOUD_MODE_MINIMAL)
|
||||||
turb_noise = noise_3d((wind_pos + turb_offset) * 0.001) - 0.5;
|
+ 4 * (noise_3d((wind_pos + turb_offset) / 2000.0 / cloud_scale) - 0.5)
|
||||||
#endif
|
#endif
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
#if (CLOUD_MODE >= CLOUD_MODE_LOW)
|
||||||
turb_noise += (noise_3d((wind_pos + turb_offset * 0.3) * 0.004) - 0.5) * 0.35;
|
+ 0.5 * (noise_3d((wind_pos + turb_offset * 0.5) / 250.0 / cloud_scale) - 0.5)
|
||||||
#endif
|
#endif
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
||||||
turb_noise += (noise_3d((wind_pos + turb_offset * 0.3) * 0.01) - 0.5) * 0.125;
|
+ 0.5 * (noise_3d(wind_pos / 150.0 / cloud_scale) - 0.5)
|
||||||
#endif
|
#endif
|
||||||
mist *= 1.0 + turb_noise;
|
) * 0.01;
|
||||||
|
cloud = pow(cloud, 3) * sign(cloud);
|
||||||
cloud_factor = 0.25 * (1.0 - pow(min(abs(pos.z - cloud_attr.x) / (cloud_attr.y * pow(max(cloud_tendency * 20.0, 0), 0.5)), 1.0), 1.0));
|
cloud *= CLOUD_DENSITY * (cloud_tendency * 100) * falloff(abs(pos.z - cloud_alt) / CLOUD_DEPTH);
|
||||||
float cloud_flat = min(cloud_tendency, 0.07) * 0.05;
|
|
||||||
cloud_flat *= (1.0 + turb_noise * 7.0 * max(0, 1.0 - cloud_factor * 5));
|
|
||||||
cloud = cloud_flat * pow(cloud_factor, 2) * 20;
|
|
||||||
|
|
||||||
// What proportion of sunlight is *not* being blocked by nearby cloud? (approximation)
|
// What proportion of sunlight is *not* being blocked by nearby cloud? (approximation)
|
||||||
cloud_sun_access = clamp((pos.z - cloud_attr.x + turb_noise * 250.0) * 0.002 + 0.35, 0, 1);
|
// Basically, just throw together a few values that roughly approximate this term and come up with an average
|
||||||
// Since we're assuming the sun/moon is always above (not always correct) it's the same for the moon
|
cloud_sun_access = (clamp((
|
||||||
cloud_moon_access = sun_access;
|
// Cloud density gradient
|
||||||
|
0.25 * (cloud_broad_a - cloud_broad_b + (0.25 * (noise_3d(wind_pos / 4000 / cloud_scale) - 0.5) + 0.1 * (noise_3d(wind_pos / 1000 / cloud_scale) - 0.5)))
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
||||||
// Try to calculate a reasonable approximation of the cloud normal
|
// More noise
|
||||||
float cloud_tendency_x = cloud_tendency_at(pos.xy + vec2(100, 0));
|
+ 0.01 * (noise_3d(wind_pos / 500) / cloud_scale - 0.5)
|
||||||
float cloud_tendency_y = cloud_tendency_at(pos.xy + vec2(0, 100));
|
|
||||||
vec3 cloud_norm = vec3(
|
|
||||||
(cloud_tendency - cloud_tendency_x) * 4,
|
|
||||||
(cloud_tendency - cloud_tendency_y) * 4,
|
|
||||||
(pos.z - cloud_attr.x) / 250 + turb_noise + 0.5
|
|
||||||
);
|
|
||||||
cloud_sun_access = mix(max(dot(-sun_dir.xyz, cloud_norm) + 0.0, 0.025), cloud_sun_access, 0.25);
|
|
||||||
cloud_moon_access = mix(max(dot(-moon_dir.xyz, cloud_norm) + 0.35, 0.025), cloud_moon_access, 0.25);
|
|
||||||
#endif
|
#endif
|
||||||
|
) * 4.0 - 0.7, -1, 1) + 1.0);
|
||||||
|
// Since we're assuming the sun/moon is always above (not always correct) it's the same for the moon
|
||||||
|
cloud_moon_access = 1.0 - cloud_sun_access;
|
||||||
}
|
}
|
||||||
|
|
||||||
float mist_sun_access = 0.5 + turb_noise * 0.5;
|
// Keeping this because it's something I'm likely to reenable later
|
||||||
|
/*
|
||||||
|
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
||||||
|
// Try to calculate a reasonable approximation of the cloud normal
|
||||||
|
float cloud_tendency_x = cloud_tendency_at(pos.xy + vec2(100, 0));
|
||||||
|
float cloud_tendency_y = cloud_tendency_at(pos.xy + vec2(0, 100));
|
||||||
|
vec3 cloud_norm = vec3(
|
||||||
|
(cloud_tendency - cloud_tendency_x) * 4,
|
||||||
|
(cloud_tendency - cloud_tendency_y) * 4,
|
||||||
|
(pos.z - cloud_attr.x) / cloud_attr.y + 0.5
|
||||||
|
);
|
||||||
|
cloud_sun_access = mix(max(dot(-sun_dir.xyz, cloud_norm) - 1.0, 0.025), cloud_sun_access, 0.25);
|
||||||
|
cloud_moon_access = mix(max(dot(-moon_dir.xyz, cloud_norm) - 0.6, 0.025), cloud_moon_access, 0.25);
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
float mist_sun_access = noise_2d(wind_pos.xy / 10000);
|
||||||
float mist_moon_access = mist_sun_access;
|
float mist_moon_access = mist_sun_access;
|
||||||
sun_access = mix(cloud_sun_access, mist_sun_access, clamp(mist * 20000, 0, 1));
|
sun_access = mix(cloud_sun_access, mist_sun_access, clamp(mist * 20000, 0, 1));
|
||||||
moon_access = mix(cloud_moon_access, mist_moon_access, clamp(mist * 20000, 0, 1));
|
moon_access = mix(cloud_moon_access, mist_moon_access, clamp(mist * 20000, 0, 1));
|
||||||
@ -97,28 +120,21 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission) {
|
|||||||
//moon_access *= suppress_mist;
|
//moon_access *= suppress_mist;
|
||||||
|
|
||||||
// Prevent clouds and mist appearing underground (but fade them out gently)
|
// Prevent clouds and mist appearing underground (but fade them out gently)
|
||||||
float not_underground = clamp(1.0 - (alt_at(pos.xy - focus_off.xy) - (pos.z - focus_off.z)) / 80.0, 0, 1);
|
float not_underground = clamp(1.0 - (alt - (pos.z - focus_off.z)) / 80.0 + dist * 0.001, 0, 1);
|
||||||
air *= not_underground;
|
air *= not_underground;
|
||||||
float vapor_density = (mist + cloud) * not_underground;
|
float vapor_density = (mist + cloud) * not_underground;
|
||||||
|
|
||||||
if (emission_strength <= 0.0) {
|
if (emission_strength <= 0.0) {
|
||||||
emission = vec3(0);
|
emission = vec3(0);
|
||||||
} else {
|
} else {
|
||||||
float z = clamp(pos.z, 0, 10000);
|
float emission_alt = CLOUD_AVG_ALT * 2.0 + (noise_3d(vec3(wind_pos.xy * 0.0001 + cloud_tendency * 0.2, time_of_day.x * 0.0002)) - 0.5) * 6000;
|
||||||
float emission_alt = 4000.0;
|
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_LOW)
|
|
||||||
emission_alt += (noise_3d(vec3(wind_pos.xy * 0.00003 + cloud_tendency * 0.2, time_of_day.x * 0.0001)) - 0.5) * 6000;
|
|
||||||
#endif
|
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_HIGH)
|
|
||||||
emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.0005)) - 0.5) * 1000;
|
|
||||||
#endif
|
|
||||||
float tail = (texture(t_noise, wind_pos.xy * 0.00005).x - 0.5) * 10 + (z - emission_alt) * 0.001;
|
|
||||||
vec3 emission_col = vec3(0.6 + tail * 0.6, 1.0, 0.3 + tail * 0.2);
|
|
||||||
float emission_nz = max(texture(t_noise, wind_pos.xy * 0.00003).x - 0.6, 0) / (10.0 + abs(z - emission_alt) / 40);
|
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
||||||
emission_nz *= (1.0 + (noise_3d(vec3(wind_pos.xy * 0.05, time_of_day.x * 0.15) * 0.004) - 0.5) * 4.0);
|
emission_alt += (noise_3d(vec3(wind_pos.xy * 0.0005 + cloud_tendency * 0.2, emission_alt * 0.0001 + time_of_day.x * 0.001)) - 0.5) * 1000;
|
||||||
#endif
|
#endif
|
||||||
emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 20;
|
float tail = (texture(t_noise, wind_pos.xy * 0.000025).x - 0.5) * 5 + (pos.z - emission_alt) * 0.0001;
|
||||||
|
vec3 emission_col = vec3(0.8 + tail * 1.5, 0.5 - tail * 0.2, 0.3 + tail * 0.2);
|
||||||
|
float emission_nz = max(pow(texture(t_noise, wind_pos.xy * 0.000015).x, 8), 0.01) * 0.25 / (10.0 + abs(pos.z - emission_alt) / 80);
|
||||||
|
emission = emission_col * emission_nz * emission_strength * max(sun_dir.z, 0) * 500000 / (1000.0 + abs(pos.z - emission_alt) * 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We track vapor density and air density separately. Why? Because photons will ionize particles in air
|
// We track vapor density and air density separately. Why? Because photons will ionize particles in air
|
||||||
@ -136,13 +152,13 @@ const float DIST_CAP = 50000;
|
|||||||
#if (CLOUD_MODE == CLOUD_MODE_ULTRA)
|
#if (CLOUD_MODE == CLOUD_MODE_ULTRA)
|
||||||
const uint QUALITY = 200u;
|
const uint QUALITY = 200u;
|
||||||
#elif (CLOUD_MODE == CLOUD_MODE_HIGH)
|
#elif (CLOUD_MODE == CLOUD_MODE_HIGH)
|
||||||
const uint QUALITY = 50u;
|
const uint QUALITY = 40u;
|
||||||
#elif (CLOUD_MODE == CLOUD_MODE_MEDIUM)
|
#elif (CLOUD_MODE == CLOUD_MODE_MEDIUM)
|
||||||
const uint QUALITY = 30u;
|
const uint QUALITY = 18u;
|
||||||
#elif (CLOUD_MODE == CLOUD_MODE_LOW)
|
#elif (CLOUD_MODE == CLOUD_MODE_LOW)
|
||||||
const uint QUALITY = 16u;
|
const uint QUALITY = 6u;
|
||||||
#elif (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
#elif (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||||
const uint QUALITY = 5u;
|
const uint QUALITY = 2u;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const float STEP_SCALE = DIST_CAP / (10.0 * float(QUALITY));
|
const float STEP_SCALE = DIST_CAP / (10.0 * float(QUALITY));
|
||||||
@ -175,11 +191,14 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of
|
|||||||
splay += (texture(t_noise, vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005).x - 0.5) * 0.075 / (1.0 + pow(dir.z, 2) * 10);
|
splay += (texture(t_noise, vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005).x - 0.5) * 0.075 / (1.0 + pow(dir.z, 2) * 10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* const float RAYLEIGH = 0.25; */
|
||||||
|
const vec3 RAYLEIGH = vec3(0.025, 0.1, 0.5);
|
||||||
|
|
||||||
// Proportion of sunlight that get scattered back into the camera by clouds
|
// Proportion of sunlight that get scattered back into the camera by clouds
|
||||||
float sun_scatter = max(dot(-dir, sun_dir.xyz), 0.5);
|
float sun_scatter = dot(-dir, sun_dir.xyz) * 0.5 + 0.7;
|
||||||
float moon_scatter = max(dot(-dir, moon_dir.xyz), 0.5);
|
float moon_scatter = dot(-dir, moon_dir.xyz) * 0.5 + 0.7;
|
||||||
vec3 sky_color = get_sky_color();
|
|
||||||
float net_light = get_sun_brightness() + get_moon_brightness();
|
float net_light = get_sun_brightness() + get_moon_brightness();
|
||||||
|
vec3 sky_color = RAYLEIGH * net_light;
|
||||||
|
|
||||||
float cdist = max_dist;
|
float cdist = max_dist;
|
||||||
float ldist = cdist;
|
float ldist = cdist;
|
||||||
@ -196,22 +215,16 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of
|
|||||||
|
|
||||||
float sun_access = sample.x;
|
float sun_access = sample.x;
|
||||||
float moon_access = sample.y;
|
float moon_access = sample.y;
|
||||||
float scatter_factor = 1.0 - 1.0 / (1.0 + density_integrals.x);
|
float cloud_scatter_factor = 1.0 - 1.0 / (1.0 + clamp(density_integrals.x, 0, 1));
|
||||||
|
float global_scatter_factor = 1.0 - 1.0 / (1.0 + clamp(density_integrals.y, 0, 1));
|
||||||
const float RAYLEIGH = 0.25;
|
|
||||||
|
|
||||||
surf_color =
|
surf_color =
|
||||||
// Attenuate light passing through the clouds
|
// Attenuate light passing through the clouds
|
||||||
surf_color * (1.0 - scatter_factor) +
|
surf_color * (1.0 - cloud_scatter_factor - global_scatter_factor) +
|
||||||
// This is not rayleigh scattering, but it's good enough for our purposes (only considers sun)
|
// Add the directed light light scattered into the camera by the clouds and the atmosphere (global illumination)
|
||||||
(1.0 - surf_color) * net_light * sky_color * density_integrals.y * RAYLEIGH +
|
get_sun_color() * sun_scatter * get_sun_brightness() * (sun_access * cloud_scatter_factor + sky_color * global_scatter_factor) +
|
||||||
// Add the directed light light scattered into the camera by the clouds
|
get_moon_color() * moon_scatter * get_moon_brightness() * (moon_access * cloud_scatter_factor + sky_color * global_scatter_factor) +
|
||||||
get_sun_color() * sun_scatter * sun_access * scatter_factor * get_sun_brightness() +
|
emission * density_integrals.y;
|
||||||
get_moon_color() * moon_scatter * moon_access * scatter_factor * get_moon_brightness() +
|
|
||||||
emission * density_integrals.y +
|
|
||||||
// Global illumination (uniform scatter from the sky)
|
|
||||||
sky_color * sun_access * scatter_factor * get_sun_brightness() +
|
|
||||||
sky_color * moon_access * scatter_factor * get_moon_brightness();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return surf_color;
|
return surf_color;
|
||||||
|
@ -18,14 +18,14 @@ const float PI = 3.141592;
|
|||||||
const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9);
|
const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9);
|
||||||
const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8);
|
const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8);
|
||||||
const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3);
|
const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3);
|
||||||
const vec3 DAY_LIGHT = vec3(2.8, 3.5, 1.8);
|
const vec3 DAY_LIGHT = vec3(3.8, 3.0, 1.8);
|
||||||
const vec3 SUN_HALO_DAY = vec3(0.06, 0.06, 0.005);
|
const vec3 SUN_HALO_DAY = vec3(0.8, 0.8, 0.001);
|
||||||
|
|
||||||
const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20);
|
const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20);
|
||||||
const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15);
|
const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15);
|
||||||
const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23);
|
const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23);
|
||||||
const vec3 DUSK_LIGHT = vec3(8.0, 1.5, 0.15);
|
const vec3 DUSK_LIGHT = vec3(8.0, 1.5, 0.15);
|
||||||
const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.01);
|
const vec3 SUN_HALO_DUSK = vec3(2.2, 0.5, 0.1);
|
||||||
|
|
||||||
const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025);
|
const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025);
|
||||||
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
const vec3 SKY_NIGHT_MID = vec3(0.001, 0.005, 0.02);
|
||||||
@ -76,17 +76,16 @@ vec3 glow_light(vec3 pos) {
|
|||||||
// 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));
|
||||||
//}
|
//}
|
||||||
|
|
||||||
float CLOUD_AVG_ALT = view_distance.z + 0.75 * view_distance.w;
|
float CLOUD_AVG_ALT = view_distance.z + (view_distance.w - view_distance.z) * 1.25;
|
||||||
|
|
||||||
const float wind_speed = 0.25;
|
const float wind_speed = 0.25;
|
||||||
vec2 wind_offset = vec2(time_of_day.x * wind_speed);
|
vec2 wind_offset = vec2(time_of_day.x * wind_speed);
|
||||||
|
|
||||||
|
float cloud_scale = view_distance.z / 150.0;
|
||||||
|
|
||||||
float cloud_tendency_at(vec2 pos) {
|
float cloud_tendency_at(vec2 pos) {
|
||||||
float nz = texture(t_noise, (pos + wind_offset) * 0.000075).x - 0.5;
|
float nz = texture(t_noise, (pos + wind_offset) / 60000.0 / cloud_scale).x - 0.3;
|
||||||
nz = clamp(nz, 0, 1);
|
nz = pow(clamp(nz, 0, 1), 4);
|
||||||
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
|
||||||
nz += (texture(t_noise, (pos + wind_offset) * 0.00035).x - 0.5) * 0.15;
|
|
||||||
#endif
|
|
||||||
return nz;
|
return nz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,9 +100,7 @@ float cloud_shadow(vec3 pos, vec3 light_dir) {
|
|||||||
float fade = 1.0 - clamp((length(xy_offset) - FADE_RANGE.x) / (FADE_RANGE.y - FADE_RANGE.x), 0, 1);
|
float fade = 1.0 - clamp((length(xy_offset) - FADE_RANGE.x) / (FADE_RANGE.y - FADE_RANGE.x), 0, 1);
|
||||||
float cloud = cloud_tendency_at(pos.xy + focus_off.xy - xy_offset);
|
float cloud = cloud_tendency_at(pos.xy + focus_off.xy - xy_offset);
|
||||||
|
|
||||||
cloud = cloud * 2.0;
|
return clamp(1 - fade * cloud * 16.0, 0, 1);
|
||||||
|
|
||||||
return clamp(1 - fade * cloud * 1.65, 0, 1);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +109,7 @@ float get_sun_brightness(/*vec3 sun_dir*/) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float get_moon_brightness(/*vec3 moon_dir*/) {
|
float get_moon_brightness(/*vec3 moon_dir*/) {
|
||||||
return max(-moon_dir.z + 0.6, 0.0) * 0.2;
|
return max(-moon_dir.z + 0.6, 0.0) * 0.05;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 get_sun_color(/*vec3 sun_dir*/) {
|
vec3 get_sun_color(/*vec3 sun_dir*/) {
|
||||||
@ -142,7 +139,7 @@ vec3 get_sky_color(/*vec3 sun_dir*/) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec3 get_moon_color(/*vec3 moon_dir*/) {
|
vec3 get_moon_color(/*vec3 moon_dir*/) {
|
||||||
return vec3(0.05, 0.05, 0.6);
|
return vec3(0.05, 0.05, 1.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectionalLight get_sun_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/, /*vec4 sun_pos*/vec3 f_pos) {
|
DirectionalLight get_sun_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/, /*vec4 sun_pos*/vec3 f_pos) {
|
||||||
@ -413,7 +410,7 @@ float is_star_at(vec3 dir) {
|
|||||||
|
|
||||||
//return 0.0;
|
//return 0.0;
|
||||||
|
|
||||||
return 1.0 / (1.0 + pow(dist * 1000, 8));
|
return 1.0 / (1.0 + pow(dist * 750, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) {
|
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) {
|
||||||
@ -434,7 +431,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sun
|
// Sun
|
||||||
const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 3.0;
|
const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 8.0;
|
||||||
|
|
||||||
vec3 sun_halo_color = mix(
|
vec3 sun_halo_color = mix(
|
||||||
SUN_HALO_DUSK,
|
SUN_HALO_DUSK,
|
||||||
@ -442,7 +439,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
|||||||
max(-sun_dir.z, 0.0)
|
max(-sun_dir.z, 0.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
vec3 sun_halo = sun_halo_color * 16 * pow(max(dot(dir, -sun_dir), 0), 8.0);
|
vec3 sun_halo = sun_halo_color * 4 * pow(max(dot(dir, -sun_dir), 0), 20.0);
|
||||||
vec3 sun_surf = vec3(0);
|
vec3 sun_surf = vec3(0);
|
||||||
if (with_features) {
|
if (with_features) {
|
||||||
float angle = 0.00035;
|
float angle = 0.00035;
|
||||||
@ -451,11 +448,11 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
|||||||
vec3 sun_light = sun_halo + sun_surf;
|
vec3 sun_light = sun_halo + sun_surf;
|
||||||
|
|
||||||
// Moon
|
// Moon
|
||||||
const vec3 MOON_SURF_COLOR = vec3(0.7, 1.0, 1.5) * 3.0;
|
const vec3 MOON_SURF_COLOR = vec3(0.7, 1.0, 1.5) * 20.0;
|
||||||
const vec3 MOON_HALO_COLOR = vec3(0.015, 0.015, 0.05) * 25;
|
const vec3 MOON_HALO_COLOR = vec3(0.015, 0.015, 0.05) * 48;
|
||||||
|
|
||||||
vec3 moon_halo_color = MOON_HALO_COLOR;
|
vec3 moon_halo_color = MOON_HALO_COLOR;
|
||||||
vec3 moon_halo = moon_halo_color * pow(max(dot(dir, -moon_dir), 0), 500.0);
|
vec3 moon_halo = moon_halo_color * pow(max(dot(dir, -moon_dir), 0), 100.0);
|
||||||
vec3 moon_surf = vec3(0);
|
vec3 moon_surf = vec3(0);
|
||||||
if (with_features) {
|
if (with_features) {
|
||||||
float angle = 0.00035;
|
float angle = 0.00035;
|
||||||
@ -465,52 +462,50 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
|||||||
|
|
||||||
// Replaced all clamp(sun_dir, 0, 1) with max(sun_dir, 0) because sun_dir is calculated from sin and cos, which are never > 1
|
// Replaced all clamp(sun_dir, 0, 1) with max(sun_dir, 0) because sun_dir is calculated from sin and cos, which are never > 1
|
||||||
|
|
||||||
vec3 sky_top = mix(
|
#if (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||||
mix(
|
vec3 sky_top = mix(
|
||||||
SKY_DUSK_TOP + star / (1.0 + moon_surf * 100.0),
|
mix(
|
||||||
SKY_NIGHT_TOP + star / (1.0 + moon_surf * 100.0),
|
SKY_DUSK_TOP + star / (1.0 + moon_surf * 100.0),
|
||||||
max(pow(sun_dir.z, 0.2), 0)
|
SKY_NIGHT_TOP + star / (1.0 + moon_surf * 100.0),
|
||||||
),
|
max(pow(sun_dir.z, 0.2), 0)
|
||||||
SKY_DAY_TOP,
|
),
|
||||||
max(-sun_dir.z, 0)
|
SKY_DAY_TOP,
|
||||||
);
|
max(-sun_dir.z, 0)
|
||||||
|
);
|
||||||
|
|
||||||
vec3 sky_mid = mix(
|
vec3 sky_mid = mix(
|
||||||
mix( SKY_DUSK_MID,
|
mix( SKY_DUSK_MID,
|
||||||
SKY_NIGHT_MID,
|
SKY_NIGHT_MID,
|
||||||
max(pow(sun_dir.z, 0.2), 0)
|
max(pow(sun_dir.z, 0.2), 0)
|
||||||
),
|
),
|
||||||
SKY_DAY_MID,
|
SKY_DAY_MID,
|
||||||
max(-sun_dir.z, 0)
|
max(-sun_dir.z, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
vec3 sky_bot = mix(
|
vec3 sky_bot = mix(
|
||||||
mix(
|
mix(
|
||||||
SKY_DUSK_BOT,
|
SKY_DUSK_BOT,
|
||||||
SKY_NIGHT_BOT,
|
SKY_NIGHT_BOT,
|
||||||
max(pow(sun_dir.z, 0.2), 0)
|
max(pow(sun_dir.z, 0.2), 0)
|
||||||
),
|
),
|
||||||
SKY_DAY_BOT,
|
SKY_DAY_BOT,
|
||||||
max(-sun_dir.z, 0)
|
max(-sun_dir.z, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
vec3 sky_color = mix(
|
vec3 sky_color = mix(
|
||||||
mix(
|
mix(
|
||||||
sky_mid,
|
sky_mid,
|
||||||
sky_bot,
|
sky_bot,
|
||||||
pow(max(-dir.z, 0), 0.4)
|
pow(max(-dir.z, 0), 0.4)
|
||||||
),
|
),
|
||||||
sky_top,
|
sky_top,
|
||||||
max(dir.z, 0)
|
max(dir.z, 0)
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
|
vec3 sky_color = vec3(0) + star;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Approximate distance to fragment
|
return sky_color + sun_light + moon_light;
|
||||||
float f_dist = distance(origin, f_pos);
|
|
||||||
|
|
||||||
if (f_dist > 5000.0) {
|
|
||||||
sky_color += sun_light + moon_light;
|
|
||||||
}
|
|
||||||
return sky_color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars) {
|
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars) {
|
||||||
|
@ -648,7 +648,7 @@ void main() {
|
|||||||
float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag);
|
float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag);
|
||||||
|
|
||||||
vec3 reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true);
|
vec3 reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true);
|
||||||
reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, time_of_day.x, 100000.0, 0.25);
|
reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, time_of_day.x, 100000.0, 0.1);
|
||||||
|
|
||||||
const float REFLECTANCE = 0.5;
|
const float REFLECTANCE = 0.5;
|
||||||
surf_color = illuminate(max_light, view_dir, f_col * emitted_light, reflect_color * REFLECTANCE + water_color * reflected_light);
|
surf_color = illuminate(max_light, view_dir, f_col * emitted_light, reflect_color * REFLECTANCE + water_color * reflected_light);
|
||||||
|
@ -294,7 +294,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
} else if (inst_mode == SNOW) {
|
} else if (inst_mode == SNOW) {
|
||||||
float height = mix(-4, 60, pow(start_end(1, 0), 3));
|
float height = mix(-4, 60, pow(start_end(1, 0), 3));
|
||||||
float wind_speed = (inst_pos.z - 250) * 0.025;
|
float wind_speed = (inst_pos.z - 2000) * 0.025;
|
||||||
vec3 offset = linear_motion(vec3(0), vec3(1, 1, 0) * wind_speed);
|
vec3 offset = linear_motion(vec3(0), vec3(1, 1, 0) * wind_speed);
|
||||||
float end_alt = alt_at(start_pos.xy + offset.xy);
|
float end_alt = alt_at(start_pos.xy + offset.xy);
|
||||||
attr = Attr(
|
attr = Attr(
|
||||||
|
BIN
assets/voxygen/texture/noise.png
(Stored with Git LFS)
BIN
assets/voxygen/texture/noise.png
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/map/veloren_0_6_0_0.bin
(Stored with Git LFS)
BIN
assets/world/map/veloren_0_6_0_0.bin
(Stored with Git LFS)
Binary file not shown.
BIN
assets/world/map/veloren_0_9_0_0.bin
(Stored with Git LFS)
Normal file
BIN
assets/world/map/veloren_0_9_0_0.bin
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -33,7 +33,7 @@ use common::{
|
|||||||
grid::Grid,
|
grid::Grid,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
recipe::RecipeBook,
|
recipe::RecipeBook,
|
||||||
resources::PlayerEntity,
|
resources::{DeltaTime, PlayerEntity, TimeOfDay},
|
||||||
terrain::{block::Block, neighbors, BiomeKind, SitesKind, TerrainChunk, TerrainChunkSize},
|
terrain::{block::Block, neighbors, BiomeKind, SitesKind, TerrainChunk, TerrainChunkSize},
|
||||||
trade::{PendingTrade, SitePrices, TradeAction, TradeId, TradeResult},
|
trade::{PendingTrade, SitePrices, TradeAction, TradeId, TradeResult},
|
||||||
uid::{Uid, UidAllocator},
|
uid::{Uid, UidAllocator},
|
||||||
@ -1472,7 +1472,9 @@ impl Client {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ServerGeneral::TimeOfDay(time_of_day) => {
|
ServerGeneral::TimeOfDay(time_of_day) => {
|
||||||
*self.state.ecs_mut().write_resource() = time_of_day;
|
let dt = self.state.ecs().read_resource::<DeltaTime>().0;
|
||||||
|
let mut tod = self.state.ecs_mut().write_resource::<TimeOfDay>();
|
||||||
|
tod.0 = Lerp::lerp(tod.0, time_of_day.0, dt as f64);
|
||||||
},
|
},
|
||||||
ServerGeneral::EntitySync(entity_sync_package) => {
|
ServerGeneral::EntitySync(entity_sync_package) => {
|
||||||
self.state
|
self.state
|
||||||
|
@ -80,6 +80,7 @@ pub enum ChatCommand {
|
|||||||
Safezone,
|
Safezone,
|
||||||
Say,
|
Say,
|
||||||
SetMotd,
|
SetMotd,
|
||||||
|
Site,
|
||||||
SkillPoint,
|
SkillPoint,
|
||||||
Spawn,
|
Spawn,
|
||||||
Sudo,
|
Sudo,
|
||||||
@ -140,6 +141,7 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
|||||||
ChatCommand::Safezone,
|
ChatCommand::Safezone,
|
||||||
ChatCommand::Say,
|
ChatCommand::Say,
|
||||||
ChatCommand::SetMotd,
|
ChatCommand::SetMotd,
|
||||||
|
ChatCommand::Site,
|
||||||
ChatCommand::SkillPoint,
|
ChatCommand::SkillPoint,
|
||||||
ChatCommand::Spawn,
|
ChatCommand::Spawn,
|
||||||
ChatCommand::Sudo,
|
ChatCommand::Sudo,
|
||||||
@ -438,6 +440,9 @@ impl ChatCommand {
|
|||||||
ChatCommand::SetMotd => {
|
ChatCommand::SetMotd => {
|
||||||
cmd(vec![Message(Optional)], "Set the server description", Admin)
|
cmd(vec![Message(Optional)], "Set the server description", Admin)
|
||||||
},
|
},
|
||||||
|
// Uses Message because site names can contain spaces, which would be assumed to be
|
||||||
|
// separators otherwise
|
||||||
|
ChatCommand::Site => cmd(vec![Message(Required)], "Teleport to a site", Admin),
|
||||||
ChatCommand::SkillPoint => cmd(
|
ChatCommand::SkillPoint => cmd(
|
||||||
vec![
|
vec![
|
||||||
Enum("skill tree", SKILL_TREES.clone(), Required),
|
Enum("skill tree", SKILL_TREES.clone(), Required),
|
||||||
@ -546,6 +551,7 @@ impl ChatCommand {
|
|||||||
ChatCommand::Safezone => "safezone",
|
ChatCommand::Safezone => "safezone",
|
||||||
ChatCommand::Say => "say",
|
ChatCommand::Say => "say",
|
||||||
ChatCommand::SetMotd => "set_motd",
|
ChatCommand::SetMotd => "set_motd",
|
||||||
|
ChatCommand::Site => "site",
|
||||||
ChatCommand::SkillPoint => "skill_point",
|
ChatCommand::SkillPoint => "skill_point",
|
||||||
ChatCommand::Spawn => "spawn",
|
ChatCommand::Spawn => "spawn",
|
||||||
ChatCommand::Sudo => "sudo",
|
ChatCommand::Sudo => "sudo",
|
||||||
|
@ -127,6 +127,7 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
|||||||
ChatCommand::Safezone => handle_safezone,
|
ChatCommand::Safezone => handle_safezone,
|
||||||
ChatCommand::Say => handle_say,
|
ChatCommand::Say => handle_say,
|
||||||
ChatCommand::SetMotd => handle_set_motd,
|
ChatCommand::SetMotd => handle_set_motd,
|
||||||
|
ChatCommand::Site => handle_site,
|
||||||
ChatCommand::SkillPoint => handle_skill_point,
|
ChatCommand::SkillPoint => handle_skill_point,
|
||||||
ChatCommand::Spawn => handle_spawn,
|
ChatCommand::Spawn => handle_spawn,
|
||||||
ChatCommand::Sudo => handle_sudo,
|
ChatCommand::Sudo => handle_sudo,
|
||||||
@ -463,6 +464,51 @@ fn handle_goto(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_site(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
target: EcsEntity,
|
||||||
|
args: String,
|
||||||
|
action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
if let Ok(dest_name) = scan_fmt!(&args, &action.arg_fmt(), String) {
|
||||||
|
if server
|
||||||
|
.state
|
||||||
|
.read_component_copied::<comp::Pos>(target)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
match server.world.civs().sites().find(|site| {
|
||||||
|
site.site_tmp
|
||||||
|
.map_or(false, |id| server.index.sites[id].name() == dest_name)
|
||||||
|
}) {
|
||||||
|
Some(site) => {
|
||||||
|
let pos = server
|
||||||
|
.world
|
||||||
|
.find_lowest_accessible_pos(server.index.as_index_ref(), site.center);
|
||||||
|
server.state.write_component(target, comp::Pos(pos));
|
||||||
|
server.state.write_component(target, comp::ForceUpdate);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandError, "Site not found"),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandError, "You have no position."),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandError, action.help_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_home(
|
fn handle_home(
|
||||||
server: &mut Server,
|
server: &mut Server,
|
||||||
client: EcsEntity,
|
client: EcsEntity,
|
||||||
|
@ -66,7 +66,6 @@ use common::{
|
|||||||
slowjob::SlowJobPool,
|
slowjob::SlowJobPool,
|
||||||
terrain::TerrainChunkSize,
|
terrain::TerrainChunkSize,
|
||||||
uid::UidAllocator,
|
uid::UidAllocator,
|
||||||
vol::{ReadVol, RectVolSize},
|
|
||||||
};
|
};
|
||||||
use common_ecs::run_now;
|
use common_ecs::run_now;
|
||||||
use common_net::{
|
use common_net::{
|
||||||
@ -297,50 +296,28 @@ impl Server {
|
|||||||
// but are needed to be explicit about casting (and to make the compiler stop
|
// but are needed to be explicit about casting (and to make the compiler stop
|
||||||
// complaining)
|
// complaining)
|
||||||
|
|
||||||
// spawn in the chunk, that is in the middle of the world
|
// Search for town defined by spawn_town server setting. If this fails, or is
|
||||||
let center_chunk: Vec2<i32> = world.sim().map_size_lg().chunks().map(i32::from) / 2;
|
// None, set spawn to the nearest town to the centre of the world
|
||||||
|
let spawn_chunk = match settings.spawn_town.as_ref().and_then(|spawn_town| {
|
||||||
// Find a town to spawn in that's close to the centre of the world
|
world.civs().sites().find(|site| {
|
||||||
let spawn_chunk = world
|
site.site_tmp
|
||||||
.civs()
|
.map_or(false, |id| index.sites[id].name() == spawn_town)
|
||||||
.sites()
|
|
||||||
.filter(|site| matches!(site.kind, world::civ::SiteKind::Settlement))
|
|
||||||
.map(|site| site.center)
|
|
||||||
.min_by_key(|site_pos| site_pos.distance_squared(center_chunk))
|
|
||||||
.unwrap_or(center_chunk);
|
|
||||||
|
|
||||||
// Calculate the middle of the chunk in the world
|
|
||||||
let spawn_wpos = TerrainChunkSize::center_wpos(spawn_chunk);
|
|
||||||
|
|
||||||
// Unwrapping because generate_chunk only returns err when should_continue evals
|
|
||||||
// to true
|
|
||||||
let (tc, _cs) = world.generate_chunk(index, spawn_chunk, || false).unwrap();
|
|
||||||
let min_z = tc.get_min_z();
|
|
||||||
let max_z = tc.get_max_z();
|
|
||||||
|
|
||||||
let pos = Vec3::new(spawn_wpos.x, spawn_wpos.y, min_z);
|
|
||||||
(0..(max_z - min_z))
|
|
||||||
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
|
||||||
.find(|test_pos| {
|
|
||||||
let chunk_relative_xy = test_pos
|
|
||||||
.xy()
|
|
||||||
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.rem_euclid(sz as i32));
|
|
||||||
tc.get(
|
|
||||||
Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z)
|
|
||||||
- Vec3::unit_z(),
|
|
||||||
)
|
|
||||||
.map_or(false, |b| b.is_filled())
|
|
||||||
&& (0..3).all(|z| {
|
|
||||||
tc.get(
|
|
||||||
Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z)
|
|
||||||
+ Vec3::unit_z() * z,
|
|
||||||
)
|
|
||||||
.map_or(true, |b| !b.is_solid())
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.unwrap_or(pos)
|
}) {
|
||||||
.map(|e| e as f32)
|
Some(t) => t.center,
|
||||||
+ 0.5
|
None => {
|
||||||
|
let center_chunk = world.sim().map_size_lg().chunks().map(i32::from) / 2;
|
||||||
|
world
|
||||||
|
.civs()
|
||||||
|
.sites()
|
||||||
|
.filter(|site| matches!(site.kind, world::civ::SiteKind::Settlement))
|
||||||
|
.map(|site| site.center)
|
||||||
|
.min_by_key(|site_pos| site_pos.distance_squared(center_chunk))
|
||||||
|
.unwrap_or(center_chunk)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
world.find_lowest_accessible_pos(index, spawn_chunk)
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "worldgen"))]
|
#[cfg(not(feature = "worldgen"))]
|
||||||
let spawn_point = Vec3::new(0.0, 0.0, 256.0);
|
let spawn_point = Vec3::new(0.0, 0.0, 256.0);
|
||||||
|
@ -98,7 +98,7 @@ pub fn init(state: &mut State, #[cfg(feature = "worldgen")] world: &world::World
|
|||||||
#[cfg(not(feature = "worldgen"))]
|
#[cfg(not(feature = "worldgen"))]
|
||||||
let mut rtsim = RtSim::new(Vec2::new(40, 40));
|
let mut rtsim = RtSim::new(Vec2::new(40, 40));
|
||||||
|
|
||||||
for _ in 0..2500 {
|
for _ in 0..world.sim().get_size().product() / 400 {
|
||||||
let pos = rtsim
|
let pos = rtsim
|
||||||
.chunks
|
.chunks
|
||||||
.size()
|
.size()
|
||||||
|
@ -16,7 +16,7 @@ use std::{
|
|||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
use world::sim::FileOpts;
|
use world::sim::FileOpts;
|
||||||
|
|
||||||
const DEFAULT_WORLD_SEED: u32 = 59686;
|
const DEFAULT_WORLD_SEED: u32 = 25269;
|
||||||
const CONFIG_DIR: &str = "server_config";
|
const CONFIG_DIR: &str = "server_config";
|
||||||
const SETTINGS_FILENAME: &str = "settings.ron";
|
const SETTINGS_FILENAME: &str = "settings.ron";
|
||||||
const WHITELIST_FILENAME: &str = "whitelist.ron";
|
const WHITELIST_FILENAME: &str = "whitelist.ron";
|
||||||
@ -42,6 +42,7 @@ pub struct Settings {
|
|||||||
pub banned_words_files: Vec<PathBuf>,
|
pub banned_words_files: Vec<PathBuf>,
|
||||||
pub max_player_group_size: u32,
|
pub max_player_group_size: u32,
|
||||||
pub client_timeout: Duration,
|
pub client_timeout: Duration,
|
||||||
|
pub spawn_town: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
@ -59,6 +60,7 @@ impl Default for Settings {
|
|||||||
banned_words_files: Vec::new(),
|
banned_words_files: Vec::new(),
|
||||||
max_player_group_size: 6,
|
max_player_group_size: 6,
|
||||||
client_timeout: Duration::from_secs(40),
|
client_timeout: Duration::from_secs(40),
|
||||||
|
spawn_town: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,7 @@ impl Civs {
|
|||||||
let initial_civ_count = initial_civ_count(sim.map_size_lg());
|
let initial_civ_count = initial_civ_count(sim.map_size_lg());
|
||||||
let mut ctx = GenCtx { sim, rng };
|
let mut ctx = GenCtx { sim, rng };
|
||||||
|
|
||||||
// TODO: Care about world size when generating caves.
|
for _ in 0..ctx.sim.get_size().product() / 10_000 {
|
||||||
for _ in 0..100 {
|
|
||||||
this.generate_cave(&mut ctx);
|
this.generate_cave(&mut ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,13 +250,13 @@ impl Civs {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|posi| {
|
.for_each(|posi| {
|
||||||
let chpos = uniform_idx_as_vec2(ctx.sim.map_size_lg(), posi);
|
let chpos = uniform_idx_as_vec2(ctx.sim.map_size_lg(), posi);
|
||||||
let wpos = chpos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
|
let wpos = chpos.map(|e| e as i64) * TerrainChunkSize::RECT_SIZE.map(|e| e as i64);
|
||||||
let closest_site = (*sites)
|
let closest_site = (*sites)
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.filter(|s| !matches!(s.1.kind, crate::site::SiteKind::Dungeon(_)))
|
.filter(|s| !matches!(s.1.kind, crate::site::SiteKind::Dungeon(_)))
|
||||||
.min_by_key(|(_id, s)| s.get_origin().distance_squared(wpos));
|
.min_by_key(|(_id, s)| s.get_origin().map(|e| e as i64).distance_squared(wpos));
|
||||||
if let Some((_id, s)) = closest_site {
|
if let Some((_id, s)) = closest_site {
|
||||||
let distance_squared = s.get_origin().distance_squared(wpos);
|
let distance_squared = s.get_origin().map(|e| e as i64).distance_squared(wpos);
|
||||||
s.economy
|
s.economy
|
||||||
.add_chunk(ctx.sim.get(chpos).unwrap(), distance_squared);
|
.add_chunk(ctx.sim.get(chpos).unwrap(), distance_squared);
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,41 @@ impl World {
|
|||||||
|
|
||||||
pub fn sample_blocks(&self) -> BlockGen { BlockGen::new(ColumnGen::new(&self.sim)) }
|
pub fn sample_blocks(&self) -> BlockGen { BlockGen::new(ColumnGen::new(&self.sim)) }
|
||||||
|
|
||||||
|
pub fn find_lowest_accessible_pos(&self, index: IndexRef, chunk_pos: Vec2<i32>) -> Vec3<f32> {
|
||||||
|
// Calculate the middle of the chunk in the world
|
||||||
|
let spawn_wpos = TerrainChunkSize::center_wpos(chunk_pos);
|
||||||
|
|
||||||
|
// Unwrapping because generate_chunk only returns err when should_continue evals
|
||||||
|
// to true
|
||||||
|
let (tc, _cs) = self.generate_chunk(index, chunk_pos, || false).unwrap();
|
||||||
|
let min_z = tc.get_min_z();
|
||||||
|
let max_z = tc.get_max_z();
|
||||||
|
|
||||||
|
let pos = Vec3::new(spawn_wpos.x, spawn_wpos.y, min_z);
|
||||||
|
(0..(max_z - min_z))
|
||||||
|
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
||||||
|
.find(|test_pos| {
|
||||||
|
let chunk_relative_xy = test_pos
|
||||||
|
.xy()
|
||||||
|
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e.rem_euclid(sz as i32));
|
||||||
|
tc.get(
|
||||||
|
Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z)
|
||||||
|
- Vec3::unit_z(),
|
||||||
|
)
|
||||||
|
.map_or(false, |b| b.is_filled())
|
||||||
|
&& (0..3).all(|z| {
|
||||||
|
tc.get(
|
||||||
|
Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z)
|
||||||
|
+ Vec3::unit_z() * z,
|
||||||
|
)
|
||||||
|
.map_or(true, |b| !b.is_solid())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(pos)
|
||||||
|
.map(|e| e as f32)
|
||||||
|
+ 0.5
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||||
#[allow(clippy::eval_order_dependence)]
|
#[allow(clippy::eval_order_dependence)]
|
||||||
#[allow(clippy::result_unit_err)]
|
#[allow(clippy::result_unit_err)]
|
||||||
|
@ -265,7 +265,7 @@ pub type ModernMap = WorldMap_0_7_0;
|
|||||||
/// with changing versions, or at least keep it in a constant somewhere that's
|
/// with changing versions, or at least keep it in a constant somewhere that's
|
||||||
/// easy to change.
|
/// easy to change.
|
||||||
#[allow(clippy::redundant_static_lifetimes)] // TODO: Pending review in #587
|
#[allow(clippy::redundant_static_lifetimes)] // TODO: Pending review in #587
|
||||||
pub const DEFAULT_WORLD_MAP: &'static str = "world.map.veloren_0_6_0_0";
|
pub const DEFAULT_WORLD_MAP: &'static str = "world.map.veloren_0_9_0_0";
|
||||||
|
|
||||||
impl WorldFileLegacy {
|
impl WorldFileLegacy {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -462,7 +462,7 @@ impl WorldSim {
|
|||||||
//
|
//
|
||||||
// FIXME: This is a hack! At some point we will hae a more principled way of
|
// FIXME: This is a hack! At some point we will hae a more principled way of
|
||||||
// dealing with this.
|
// dealing with this.
|
||||||
let continent_scale_hack = 1.0/*4.0*/;
|
let continent_scale_hack = 2.0/*4.0*/;
|
||||||
let (parsed_world_file, map_size_lg) = parsed_world_file
|
let (parsed_world_file, map_size_lg) = parsed_world_file
|
||||||
.and_then(|map| match MapSizeLg::new(map.map_size_lg) {
|
.and_then(|map| match MapSizeLg::new(map.map_size_lg) {
|
||||||
Ok(map_size_lg) => Some((Some(map), map_size_lg)),
|
Ok(map_size_lg) => Some((Some(map), map_size_lg)),
|
||||||
|
@ -568,7 +568,7 @@ fn trade_at_site(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut paid_amount = allocated_amount - balance / *price;
|
let mut paid_amount = (allocated_amount - balance / *price).min(economy.stocks[*g]);
|
||||||
if paid_amount / allocated_amount < 0.95 {
|
if paid_amount / allocated_amount < 0.95 {
|
||||||
debug!(
|
debug!(
|
||||||
"Client {} is broke on {:?} : {} {} severity {}",
|
"Client {} is broke on {:?} : {} {} severity {}",
|
||||||
|
@ -279,7 +279,7 @@ impl Economy {
|
|||||||
// info!("resources {:?}", self.stocks);
|
// info!("resources {:?}", self.stocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_chunk(&mut self, ch: &SimChunk, distance_squared: i32) {
|
pub fn add_chunk(&mut self, ch: &SimChunk, distance_squared: i64) {
|
||||||
let biome = ch.get_biome();
|
let biome = ch.get_biome();
|
||||||
// we don't scale by pi, although that would be correct
|
// we don't scale by pi, although that would be correct
|
||||||
let distance_bin = (distance_squared >> 16).min(64) as usize;
|
let distance_bin = (distance_squared >> 16).min(64) as usize;
|
||||||
|
Loading…
Reference in New Issue
Block a user