mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'isse/shader-fp-fixes' into 'master'
Shader floating point fixes See merge request veloren/veloren!4120
This commit is contained in:
commit
472b996c8e
@ -68,6 +68,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- You can no longer write messages to old groups after being kicked and not having updated your chat mode.
|
||||
- Location names are now also correct after editing and creating characters
|
||||
- NPC's wont pick up recently dropped items (if not hostile towards you)
|
||||
- Fixed "low fps" of different shaders caused by low floating point precision when using time.
|
||||
|
||||
## [0.15.0] - 2023-07-01
|
||||
|
||||
|
@ -236,19 +236,19 @@ void main() {
|
||||
uvec4 new_mat = texelFetch(usampler2D(t_src_mat, s_src_depth), clamp(ivec2(new_uv * mat_sz), ivec2(0), ivec2(mat_sz) - 1), 0);
|
||||
// If it's the sky, just go determine the sky color analytically to avoid sampling the incomplete skybox
|
||||
// Otherwise, pull the color from the screen-space color buffer
|
||||
vec3 sky_col = min(get_sky_color(refl_dir, time_of_day.x, wpos, vec3(-100000), 0.125, false, 0.0, true, 0.0), vec3(1)) * not_underground;
|
||||
vec3 sky_col = min(get_sky_color(refl_dir, wpos, vec3(-100000), 0.125, false, 0.0, true, 0.0), vec3(1)) * not_underground;
|
||||
if (new_mat.a == MAT_SKY) {
|
||||
refl_col = sky_col;
|
||||
} else {
|
||||
refl_col = mix(sky_col, texelFetch(sampler2D(t_src_color, s_src_color), clamp(ivec2(new_uv * col_sz), ivec2(0), ivec2(col_sz) - 1), 0).rgb, merge);
|
||||
}
|
||||
// Apply clouds to reflected colour
|
||||
refl_col = mix(refl_col, get_cloud_color(refl_col, refl_dir, wpos, time_of_day.x, distance(new_wpos, wpos.xyz), 1.0), not_underground);
|
||||
refl_col = mix(refl_col, get_cloud_color(refl_col, refl_dir, wpos, distance(new_wpos, wpos.xyz), 1.0), not_underground);
|
||||
} else {
|
||||
// No: assume that anything off-screen is the colour of the sky
|
||||
refl_col = min(get_sky_color(refl_dir, time_of_day.x, wpos, vec3(-100000), 0.125, true, 1.0, true, 1.0) * not_underground, vec3(1));
|
||||
refl_col = min(get_sky_color(refl_dir, wpos, vec3(-100000), 0.125, true, 1.0, true, 1.0) * not_underground, vec3(1));
|
||||
// Apply clouds to reflection
|
||||
refl_col = mix(refl_col, get_cloud_color(refl_col, refl_dir, wpos, time_of_day.x, 100000.0, 1.0), not_underground);
|
||||
refl_col = mix(refl_col, get_cloud_color(refl_col, refl_dir, wpos, 100000.0, 1.0), not_underground);
|
||||
}
|
||||
color.rgb = mix(color.rgb, refl_col, color.a);
|
||||
cloud_blend = 1;
|
||||
@ -260,7 +260,7 @@ void main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
color.rgb = mix(color.rgb, get_cloud_color(color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0), cloud_blend);
|
||||
color.rgb = mix(color.rgb, get_cloud_color(color.rgb, dir, cam_pos.xyz, dist, 1.0), cloud_blend);
|
||||
|
||||
#if (CLOUD_MODE == CLOUD_MODE_NONE)
|
||||
color.rgb = apply_point_glow(cam_pos.xyz + focus_off.xyz, dir, dist, color.rgb);
|
||||
|
@ -288,8 +288,8 @@ void main() {
|
||||
/*
|
||||
if ((material & (1u << 1u)) > 0u && false) {
|
||||
vec3 reflect_ray_dir = reflect(cam_to_frag, f_norm);
|
||||
reflect_color = get_sky_color(reflect_ray_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_sky_color(reflect_ray_dir, f_pos, vec3(-100000), 0.125, true);
|
||||
reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, 100000.0, 0.25);
|
||||
reflectance = 1.0;
|
||||
}
|
||||
*/
|
||||
|
@ -52,22 +52,22 @@ layout(location = 1) out uvec4 tgt_mat;
|
||||
#include <light.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
vec4 water_col(vec4 posx, vec4 posy) {
|
||||
posx = (posx + focus_off.x) * 0.1;
|
||||
posy = (posy + focus_off.y) * 0.1;
|
||||
vec4 water_col(vec2 pos) {
|
||||
pos += focus_off.xy;
|
||||
pos *= 0.1;
|
||||
vec2 v = floor(f_vel) * 0.1;
|
||||
vec4 uv = tick_loop4(1, -v.xxyy - vec2(0, 0.1).xyxy, pos.xxyy);
|
||||
|
||||
return 0.5 + (vec4(
|
||||
textureLod(sampler2D(t_noise, s_noise), vec2(posx.x, posy.x), 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), vec2(posx.y, posy.y), 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), vec2(posx.z, posy.z), 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), vec2(posx.w, posy.w), 0).x
|
||||
textureLod(sampler2D(t_noise, s_noise), uv.xz, 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), uv.yz, 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), uv.xw, 0).x,
|
||||
textureLod(sampler2D(t_noise, s_noise), uv.yw, 0).x
|
||||
) - 0.5) * 1.0;
|
||||
}
|
||||
|
||||
float water_col_vel(vec2 pos){
|
||||
vec4 cols = water_col(
|
||||
pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy,
|
||||
pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy
|
||||
);
|
||||
vec4 cols = water_col(pos);
|
||||
return mix(
|
||||
mix(cols.x, cols.y, fract(f_vel.x + 1.0)),
|
||||
mix(cols.z, cols.w, fract(f_vel.x + 1.0)),
|
||||
@ -163,7 +163,7 @@ void main() {
|
||||
|
||||
vec3 reflect_color = vec3(0.0);
|
||||
#if (REFLECTION_MODE >= REFLECTION_MODE_MEDIUM)
|
||||
reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
reflect_color = get_sky_color(reflect_ray_dir, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
#endif
|
||||
|
||||
vec3 emitted_light, reflected_light;
|
||||
|
@ -54,13 +54,16 @@ layout(location = 1) out uvec4 tgt_mat;
|
||||
#include <light.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
void wave_dx(vec4 posx, vec4 posy, vec2 dir, float speed, float frequency, float timeshift, out vec4 wave, out vec4 dx) {
|
||||
vec4 x = vec4(
|
||||
dot(dir, vec2(posx.x, posy.x)),
|
||||
dot(dir, vec2(posx.y, posy.y)),
|
||||
dot(dir, vec2(posx.z, posy.z)),
|
||||
dot(dir, vec2(posx.w, posy.w))
|
||||
) * frequency + timeshift * speed;
|
||||
void wave_dx(vec2 pos, vec2 dir, float speed, float frequency, float factor, vec4 accumx, vec4 accumy, out vec4 wave, out vec4 dx) {
|
||||
float ff = frequency * factor;
|
||||
|
||||
vec2 v = floor(f_vel);
|
||||
vec4 kx = (v.x + vec2(0, 1)).xyxy;
|
||||
vec4 ky = (v.y + vec2(0, 1)).xxyy;
|
||||
vec4 p = speed - ff * (dir.x * kx + dir.y * ky);
|
||||
vec4 q = frequency * ((dir.x * factor * pos.x + accumx) + dir.y * (factor * pos.y + accumy));
|
||||
vec4 x = tick_loop4(2 * PI, p, q);
|
||||
|
||||
wave = sin(x) + 0.5;
|
||||
wave *= wave;
|
||||
dx = -wave * cos(x);
|
||||
@ -70,7 +73,7 @@ void wave_dx(vec4 posx, vec4 posy, vec2 dir, float speed, float frequency, float
|
||||
// Modified to allow calculating the wave function 4 times at once using different positions (used for intepolation
|
||||
// for moving water). The general idea is to sample the wave function at different positions, where those positions
|
||||
// depend on increments of the velocity, and then interpolate between those velocities to get a smooth water velocity.
|
||||
vec4 wave_height(vec4 posx, vec4 posy) {
|
||||
vec4 wave_height(vec2 pos) {
|
||||
float iter = 0.0;
|
||||
float phase = 4.0;
|
||||
float weight = 1.5;
|
||||
@ -79,27 +82,28 @@ vec4 wave_height(vec4 posx, vec4 posy) {
|
||||
const float speed_per_iter = 0.1;
|
||||
#if (FLUID_MODE == FLUID_MODE_HIGH)
|
||||
float speed = 1.0;
|
||||
posx *= 0.2;
|
||||
posy *= 0.2;
|
||||
const float factor = 0.2;
|
||||
const float drag_factor = 0.035;
|
||||
const int iters = 21;
|
||||
const float scale = 15.0;
|
||||
#else
|
||||
float speed = 2.0;
|
||||
posx *= 0.3;
|
||||
posy *= 0.3;
|
||||
const float factor = 0.3;
|
||||
const float drag_factor = 0.04;
|
||||
const int iters = 11;
|
||||
const float scale = 3.0;
|
||||
#endif
|
||||
const float iter_shift = (3.14159 * 2.0) / 7.3;
|
||||
|
||||
vec4 accumx = vec4(0);
|
||||
vec4 accumy = vec4(0);
|
||||
|
||||
for(int i = 0; i < iters; i ++) {
|
||||
vec2 p = vec2(sin(iter), cos(iter));
|
||||
vec4 wave, dx;
|
||||
wave_dx(posx, posy, p, speed, phase, tick.x, wave, dx);
|
||||
posx += p.x * dx * weight * drag_factor;
|
||||
posy += p.y * dx * weight * drag_factor;
|
||||
wave_dx(pos, p, speed, phase, factor, accumx, accumy, wave, dx);
|
||||
accumx += p.x * dx * weight * drag_factor;
|
||||
accumy += p.y * dx * weight * drag_factor;
|
||||
w += wave * weight;
|
||||
iter += iter_shift * 1.5;
|
||||
ws += weight;
|
||||
@ -111,10 +115,7 @@ vec4 wave_height(vec4 posx, vec4 posy) {
|
||||
}
|
||||
|
||||
float wave_height_vel(vec2 pos) {
|
||||
vec4 heights = wave_height(
|
||||
pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy,
|
||||
pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy
|
||||
);
|
||||
vec4 heights = wave_height(pos);
|
||||
return mix(
|
||||
mix(heights.x, heights.y, fract(f_vel.x + 1.0)),
|
||||
mix(heights.z, heights.w, fract(f_vel.x + 1.0)),
|
||||
@ -275,7 +276,7 @@ void main() {
|
||||
/* reflect_color = get_cloud_color(reflect_color, ray_dir, f_pos.xyz, time_of_day.x, 100000.0, 0.1); */
|
||||
reflect_color = vec3(0);
|
||||
#else
|
||||
reflect_color = get_sky_color(ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
reflect_color = get_sky_color(ray_dir, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
#endif
|
||||
// Sort of non-physical, but we try to balance the reflection intensity with the direct light from the sun,
|
||||
// resulting in decent reflection of the ambient environment even after the sun has gone down.
|
||||
@ -339,7 +340,7 @@ void main() {
|
||||
float passthrough = max(dot(cam_norm, -cam_to_frag), 0) * 0.75;
|
||||
|
||||
float max_light = 0.0;
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, cam_norm, /*time_of_day.x*/sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, cam_norm, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
emitted_light *= not_underground;
|
||||
reflected_light *= not_underground;
|
||||
|
||||
|
@ -65,7 +65,7 @@ void main() {
|
||||
// Terrain 'pop-in' effect
|
||||
#ifndef EXPERIMENTAL_BAREMINIMUM
|
||||
#ifndef EXPERIMENTAL_NOTERRAINPOP
|
||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
|
||||
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include <lod.glsl>
|
||||
#include <sky.glsl>
|
||||
|
||||
vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) {
|
||||
vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, float max_dist, float quality) {
|
||||
// Underwater light attenuation
|
||||
surf_color = water_diffuse(surf_color, dir, max_dist);
|
||||
|
||||
if (max_dist < DIST_CAP) {
|
||||
vec3 sky_light = get_sky_light(dir, time_of_day, false);
|
||||
vec3 sky_light = get_sky_light(dir, false);
|
||||
surf_color = mix(sky_light, surf_color, 1.0 / exp(max_dist / 5000.0));
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ vec4 cloud_at(vec3 pos, float dist, out vec3 emission, out float not_underground
|
||||
if (emission_strength <= 0.0) {
|
||||
emission = vec3(0);
|
||||
} else {
|
||||
float nz = textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005 - time_of_day.x * 0.0001, 0).x;//noise_3d(vec3(wind_pos.xy * 0.00005 + cloud_tendency * 0.2, time_of_day.x * 0.0002));
|
||||
float nz = textureLod(sampler2D(t_noise, s_noise), wind_pos.xy * 0.00005 - time_of_day.y * 8.0, 0).x;//noise_3d(vec3(wind_pos.xy * 0.00005 + cloud_tendency * 0.2, time_of_day.x * 0.0002));
|
||||
|
||||
float emission_alt = alt * 0.5 + 1000 + 1000 * nz;
|
||||
float emission_height = 1000.0;
|
||||
@ -195,7 +195,7 @@ float dist_to_step(float dist, float quality) {
|
||||
// consistently support forward declarations (not surprising, it's designed for single-pass compilers).
|
||||
#include <point_glow.glsl>
|
||||
|
||||
vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of_day, float max_dist, const float quality) {
|
||||
vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, float max_dist, const float quality) {
|
||||
// Limit the marching distance to reduce maximum jumps
|
||||
max_dist = min(max_dist, DIST_CAP);
|
||||
|
||||
@ -205,7 +205,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of
|
||||
// improves visual quality for low cloud settings
|
||||
float splay = 1.0;
|
||||
#if (CLOUD_MODE == CLOUD_MODE_MINIMAL)
|
||||
splay += (textureLod(sampler2D(t_noise, s_noise), vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day * 0.00005, 0).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10);
|
||||
splay += (textureLod(sampler2D(t_noise, s_noise), vec2(atan2(dir.x, dir.y) * 2 / PI, dir.z) * 5.0 - time_of_day.y * 4.0, 0).x - 0.5) * 0.025 / (1.0 + pow(dir.z, 2) * 10);
|
||||
#endif
|
||||
|
||||
const vec3 RAYLEIGH = vec3(0.025, 0.1, 0.5);
|
||||
@ -215,7 +215,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of
|
||||
float moon_scatter = dot(-dir, moon_dir.xyz) * 0.5 + 0.7;
|
||||
float net_light = get_sun_brightness() + get_moon_brightness();
|
||||
vec3 sky_color = RAYLEIGH * net_light;
|
||||
vec3 sky_light = get_sky_light(dir, time_of_day, false);
|
||||
vec3 sky_light = get_sky_light(dir, false);
|
||||
vec3 sun_color = get_sun_color();
|
||||
vec3 moon_color = get_moon_color();
|
||||
|
||||
|
@ -9,9 +9,14 @@ layout(std140, set = 0, binding = 0) uniform u_globals {
|
||||
vec4 focus_off;
|
||||
vec4 focus_pos;
|
||||
vec4 view_distance;
|
||||
// .x = time of day, repeats every day.
|
||||
// .y = a continuous value for what day it is. Repeats every `tick_overflow` for precisions sake.
|
||||
vec4 time_of_day;
|
||||
vec4 sun_dir;
|
||||
vec4 moon_dir;
|
||||
// .x = The `Time` resource, repeated every `tick_overflow`
|
||||
// .y = a floored (`Time` / `tick_overflow`)
|
||||
// .z = `Time`, not recommended to be used as it might have low precision
|
||||
vec4 tick;
|
||||
vec4 screen_res;
|
||||
uvec4 light_shadow_count;
|
||||
@ -39,4 +44,33 @@ mat4 threshold_matrix = mat4(
|
||||
float distance_divider = 2;
|
||||
float shadow_dithering = 0.5;
|
||||
|
||||
float tick_overflow = 300000.0;
|
||||
|
||||
// Get a scaled time with an offset that loops at a period.
|
||||
float tick_loop(float period, float scale, float offset) {
|
||||
float loop = tick_overflow * scale;
|
||||
float rem = mod(loop, period);
|
||||
float rest = rem * tick.y;
|
||||
|
||||
return mod(rest + tick.x * scale + offset, period);
|
||||
}
|
||||
|
||||
float tick_loop(float period) {
|
||||
return tick_loop(period, 1.0, 0.0);
|
||||
}
|
||||
|
||||
|
||||
vec4 tick_loop4(float period, vec4 scale, vec4 offset) {
|
||||
vec4 loop = tick_overflow * scale;
|
||||
vec4 rem = mod(loop, period);
|
||||
vec4 rest = rem * tick.y;
|
||||
|
||||
return mod(rest + tick.x * scale + offset, period);
|
||||
}
|
||||
|
||||
// Only works if t happened within tick_overflow
|
||||
float time_since(float t) {
|
||||
return tick.x < t ? (tick_overflow - t + tick.x) : (tick.x - t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -152,8 +152,7 @@ float alt_at_real(vec2 pos) {
|
||||
}
|
||||
|
||||
|
||||
float horizon_at2(vec4 f_horizons, float alt, vec3 pos, /*float time_of_day*/vec4 light_dir) {
|
||||
// vec3 sun_dir = get_sun_dir(time_of_day);
|
||||
float horizon_at2(vec4 f_horizons, float alt, vec3 pos, vec4 light_dir) {
|
||||
const float PI_2 = 3.1415926535897932384626433832795 / 2.0;
|
||||
const float MIN_LIGHT = 0.0;//0.115/*0.0*/;
|
||||
|
||||
|
@ -58,7 +58,7 @@ vec3 apply_point_glow(vec3 wpos, vec3 dir, float max_dist, vec3 color) {
|
||||
#endif
|
||||
|
||||
#ifdef FLASHING_LIGHTS_ENABLED
|
||||
float time_since_lightning = tick.x - last_lightning.w;
|
||||
float time_since_lightning = time_since(last_lightning.w);
|
||||
if (time_since_lightning < MAX_LIGHTNING_PERIOD) {
|
||||
// Apply lightning
|
||||
apply_point_glow_light(Light(last_lightning.xyzw + vec4(0, 0, LIGHTNING_HEIGHT, 0), vec4(vec3(0.2, 0.4, 1) * lightning_intensity() * 0.003, 1)), wpos, dir, max_dist, color);
|
||||
|
@ -17,7 +17,7 @@ struct DirectionalLight {
|
||||
// float brightness;
|
||||
};
|
||||
|
||||
const float PI = 3.141592;
|
||||
const float PI = 3.141592653;
|
||||
|
||||
const vec3 SKY_DAWN_TOP = vec3(0.10, 0.1, 0.10);
|
||||
const vec3 SKY_DAWN_MID = vec3(1.2, 0.3, 0.2);
|
||||
@ -94,7 +94,7 @@ vec3 glow_light(vec3 pos) {
|
||||
float CLOUD_AVG_ALT = view_distance.z + (view_distance.w - view_distance.z) * 1.25;
|
||||
|
||||
const float wind_speed = 0.25;
|
||||
vec2 wind_offset = vec2(time_of_day.x * wind_speed);
|
||||
vec2 wind_offset = vec2(time_of_day.y * wind_speed * (3600.0 * 24.0));
|
||||
|
||||
float cloud_scale = view_distance.z / 150.0;
|
||||
|
||||
@ -140,7 +140,7 @@ float cloud_shadow(vec3 pos, vec3 light_dir) {
|
||||
#endif
|
||||
}
|
||||
|
||||
float magnetosphere = sin(time_of_day.x / (3600 * 24));
|
||||
float magnetosphere = sin(time_of_day.y);
|
||||
#if (CLOUD_MODE <= CLOUD_MODE_LOW)
|
||||
const vec3 magnetosphere_tint = vec3(1);
|
||||
#else
|
||||
@ -156,7 +156,7 @@ float magnetosphere = sin(time_of_day.x / (3600 * 24));
|
||||
#if (CLOUD_MODE > CLOUD_MODE_NONE)
|
||||
float emission_strength = clamp((magnetosphere - 0.3) * 1.3, 0, 1) * max(-moon_dir.z, 0);
|
||||
#if (CLOUD_MODE >= CLOUD_MODE_MEDIUM)
|
||||
float emission_br = abs(pow(fract(time_of_day.x * 0.000005) * 2 - 1, 2));
|
||||
float emission_br = abs(pow(fract(time_of_day.y * 0.5) * 2 - 1, 2));
|
||||
#else
|
||||
float emission_br = 0.5;
|
||||
#endif
|
||||
@ -236,7 +236,7 @@ const float LIGHTNING_HEIGHT = 25.0;
|
||||
const float MAX_LIGHTNING_PERIOD = 5.0;
|
||||
|
||||
float lightning_intensity() {
|
||||
float time_since_lightning = tick.x - last_lightning.w;
|
||||
float time_since_lightning = time_since(last_lightning.w);
|
||||
return
|
||||
// Strength
|
||||
1000000
|
||||
@ -247,7 +247,7 @@ float lightning_intensity() {
|
||||
}
|
||||
|
||||
vec3 lightning_at(vec3 wpos) {
|
||||
float time_since_lightning = tick.x - last_lightning.w;
|
||||
float time_since_lightning = time_since(last_lightning.w);
|
||||
if (time_since_lightning < MAX_LIGHTNING_PERIOD) {
|
||||
vec3 diff = wpos + focus_off.xyz - (last_lightning.xyz + vec3(0, 0, LIGHTNING_HEIGHT));
|
||||
float dist = length(diff);
|
||||
@ -489,7 +489,6 @@ float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, ve
|
||||
|
||||
// This has been extracted into a function to allow quick exit when detecting a star.
|
||||
float is_star_at(vec3 dir) {
|
||||
|
||||
float star_scale = 80.0;
|
||||
|
||||
// Star positions
|
||||
@ -516,7 +515,7 @@ float is_star_at(vec3 dir) {
|
||||
return power * max(sun_dir.z, 0.1) / (1.0 + pow(dist * 750, 8));
|
||||
}
|
||||
|
||||
vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) {
|
||||
vec3 get_sky_light(vec3 dir, bool with_stars) {
|
||||
// Add white dots for stars. Note these flicker and jump due to FXAA
|
||||
float star = 0.0;
|
||||
if (with_stars) {
|
||||
@ -580,15 +579,11 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) {
|
||||
return sky_color * magnetosphere_tint;
|
||||
}
|
||||
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex, bool fake_clouds, float sun_shade_frac) {
|
||||
vec3 get_sky_color(vec3 dir, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex, bool fake_clouds, float sun_shade_frac) {
|
||||
// Sky color
|
||||
/* vec3 sun_dir = get_sun_dir(time_of_day);
|
||||
vec3 moon_dir = get_moon_dir(time_of_day); */
|
||||
vec3 sun_dir = sun_dir.xyz;
|
||||
vec3 moon_dir = moon_dir.xyz;
|
||||
|
||||
// sun_dir = sun_dir.z <= 0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : sun_dir;
|
||||
// moon_dir = moon_dir.z <= 0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : moon_dir;
|
||||
|
||||
// Sun
|
||||
const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 10.0;
|
||||
@ -660,10 +655,10 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
||||
#else
|
||||
if (fake_clouds || medium.x == MEDIUM_WATER) {
|
||||
#endif
|
||||
sky_color = get_sky_light(dir, time_of_day, !fake_clouds);
|
||||
sky_color = get_sky_light(dir, !fake_clouds);
|
||||
} else {
|
||||
if (medium.x == MEDIUM_WATER) {
|
||||
sky_color = get_sky_light(dir, time_of_day, true);
|
||||
sky_color = get_sky_light(dir, true);
|
||||
} else {
|
||||
vec3 star_dir = normalize(sun_dir.xyz * dir.z + cross(sun_dir.xyz, vec3(0, 1, 0)) * dir.x + vec3(0, 1, 0) * dir.y);
|
||||
float star = is_star_at(star_dir);
|
||||
@ -674,12 +669,12 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q
|
||||
return sky_color + sun_light + moon_light;
|
||||
}
|
||||
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) {
|
||||
return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_features, refractionIndex, false, 1.0);
|
||||
vec3 get_sky_color(vec3 dir, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) {
|
||||
return get_sky_color(dir, origin, f_pos, quality, with_features, refractionIndex, false, 1.0);
|
||||
}
|
||||
|
||||
vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars) {
|
||||
return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0, false, 1.0);
|
||||
vec3 get_sky_color(vec3 dir, vec3 origin, vec3 f_pos, float quality, bool with_stars) {
|
||||
return get_sky_color(dir, origin, f_pos, quality, with_stars, 1.0, false, 1.0);
|
||||
}
|
||||
|
||||
float fog(vec3 f_pos, vec3 focus_pos, uint medium) {
|
||||
|
@ -662,10 +662,10 @@ void main() {
|
||||
|
||||
vec3 reflect_color;
|
||||
#if (FLUID_MODE == FLUID_MODE_HIGH)
|
||||
reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, time_of_day.x, 100000.0, 0.1);
|
||||
reflect_color = get_sky_color(reflect_ray, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, 100000.0, 0.1);
|
||||
#else
|
||||
reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
reflect_color = get_sky_color(reflect_ray, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
#endif
|
||||
reflect_color *= sun_shade_frac * 0.75 + 0.25;
|
||||
|
||||
@ -678,7 +678,7 @@ void main() {
|
||||
surf_alpha = 1.0 - passthrough;
|
||||
#else
|
||||
surf_alpha = 0.9;
|
||||
surf_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
surf_color = get_sky_color(reflect_ray, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac);
|
||||
#endif
|
||||
} else {
|
||||
mat = MAT_LOD;
|
||||
|
@ -95,7 +95,17 @@ struct Attr {
|
||||
mat4 rot;
|
||||
};
|
||||
|
||||
float lifetime = tick.x - inst_time;
|
||||
float lifetime = time_since(inst_time);
|
||||
|
||||
// Retrieves inst_time, repeating over a period. This will be consistent
|
||||
// over a time overflow.
|
||||
float loop_inst_time(float period, float scale) {
|
||||
if (tick.x < inst_time) {
|
||||
return mod(mod(tick_overflow * scale, period) + inst_time * scale, period);
|
||||
} else {
|
||||
return mod(inst_time * scale, period);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 linear_motion(vec3 init_offs, vec3 vel) {
|
||||
return init_offs + vel * lifetime;
|
||||
@ -420,14 +430,14 @@ void main() {
|
||||
break;
|
||||
case LIFESTEAL_BEAM:
|
||||
f_reflect = 0.0;
|
||||
float green_col = 0.8 + 0.8 * sin(tick.x * 5 + lifetime * 5);
|
||||
float purple_col = 0.6 + 0.5 * sin(tick.x * 4 - lifetime * 4) - min(max(green_col - 1, 0), 0.3);
|
||||
float red_col = 1.15 + 0.1 * sin(tick.x * 3 - lifetime * 3) - min(max(green_col - 1, 0), 0.3) - max(purple_col - 0.5, 0);
|
||||
float green_col = 0.8 + 0.8 * sin(tick_loop(2 * PI, 5, lifetime * 5));
|
||||
float purple_col = 0.6 + 0.5 * sin(loop_inst_time(2 * PI, 4)) - min(max(green_col - 1, 0), 0.3);
|
||||
float red_col = 1.15 + 0.1 * sin(loop_inst_time(2 * PI, 3)) - min(max(green_col - 1, 0), 0.3) - max(purple_col - 0.5, 0);
|
||||
attr = Attr(
|
||||
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time),
|
||||
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
|
||||
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, loop_inst_time(2.0 * PI, 1.0)),
|
||||
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick_loop(2 * PI, 10, -lifetime * 4)))),
|
||||
vec4(vec3(red_col + purple_col * 0.6, green_col + purple_col * 0.35, purple_col), 1),
|
||||
spin_in_axis(inst_dir, tick.z)
|
||||
spin_in_axis(inst_dir, tick_loop(2 * PI))
|
||||
);
|
||||
break;
|
||||
case ENERGY_NATURE:
|
||||
|
@ -244,7 +244,9 @@ void main() {
|
||||
vec2 sample_uv = uv;
|
||||
#ifdef EXPERIMENTAL_UNDERWARPER
|
||||
if (medium.x == MEDIUM_WATER) {
|
||||
sample_uv += sin(uv.yx * 60 + tick.xx * 3.0) * 0.003;
|
||||
float x = tick_loop(2.0 * PI, 3.0, uv.y * 60);
|
||||
float y = tick_loop(2.0 * PI, 3.0, uv.x * 60);
|
||||
sample_uv += sin(vec2(x, y)) * 0.003;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -310,7 +312,7 @@ void main() {
|
||||
float dist = distance(wpos, cam_pos.xyz);
|
||||
vec3 dir = (wpos - cam_pos.xyz) / dist;
|
||||
|
||||
aa_color.rgb = get_cloud_color(aa_color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0);
|
||||
aa_color.rgb = get_cloud_color(aa_color.rgb, dir, cam_pos.xyz, dist, 1.0);
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
@ -56,6 +56,6 @@ void main() {
|
||||
} */
|
||||
vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist;
|
||||
|
||||
tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex, false, 1.0), 1.0);
|
||||
tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), cam_pos.xyz, wpos, 1.0, true, refractionIndex, false, 1.0), 1.0);
|
||||
tgt_mat = uvec4(uvec3(0), MAT_SKY);
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ float wind_wave(float off, float scaling, float speed, float strength) {
|
||||
strength = max(strength, 6.0);
|
||||
aspeed = max(aspeed, 5.0);
|
||||
|
||||
return (sin(tick.x * 0.35 * scaling * floor(aspeed) + off) * (1.0 - fract(aspeed))
|
||||
+ sin(tick.x * 0.35 * scaling * ceil(aspeed) + off) * fract(aspeed)) * abs(strength) * 0.25;
|
||||
return (sin(tick_loop(2.0 * PI, 0.35 * scaling * floor(aspeed), off)) * (1.0 - fract(aspeed))
|
||||
+ sin(tick_loop(2.0 * PI, 0.35 * scaling * ceil(aspeed), off)) * fract(aspeed)) * abs(strength) * 0.25;
|
||||
//return sin(tick.x * 1.5 * scaling + off) + sin(tick.x * 0.35 * scaling + off);
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ void main() {
|
||||
#ifndef EXPERIMENTAL_BAREMINIMUM
|
||||
#ifndef EXPERIMENTAL_NOTERRAINPOP
|
||||
// Terrain 'pop-in' effect
|
||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||
f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -267,12 +267,14 @@ void main() {
|
||||
if (puddle > 0.0) {
|
||||
f_alpha = puddle * 0.2 * max(1.0 + cam_to_frag.z, 0.3);
|
||||
#ifdef EXPERIMENTAL_PUDDLEDETAILS
|
||||
float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3)
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6);
|
||||
float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3)
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6);
|
||||
float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3)
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6);
|
||||
let t0 = sin(tick_loop(2.0 * PI, 8.0, f_pos.x * 3));
|
||||
let t1 = sin(tick_loop(2.0 * PI, 3.5, -f_pos.x * 6));
|
||||
float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * t0
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * t1;
|
||||
float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * t0
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * t1;
|
||||
float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * t0
|
||||
+ (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * t1;
|
||||
f_norm.xy += mix(vec2(0), vec2(h - hx, h - hy) / 0.1 * 0.03, puddle);
|
||||
#endif
|
||||
alpha = mix(1.0, 0.2, puddle);
|
||||
@ -387,7 +389,7 @@ void main() {
|
||||
vec3 emitted_light = vec3(1.0);
|
||||
vec3 reflected_light = vec3(1.0);
|
||||
|
||||
float sun_diffuse = get_sun_diffuse2(/*time_of_day.x, */sun_info, moon_info, f_norm, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
float sun_diffuse = get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
max_light += sun_diffuse;
|
||||
|
||||
// emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW);
|
||||
|
@ -82,7 +82,7 @@ void main() {
|
||||
// Terrain 'pop-in' effect
|
||||
#ifndef EXPERIMENTAL_BAREMINIMUM
|
||||
#ifndef EXPERIMENTAL_NOTERRAINPOP
|
||||
v_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0));
|
||||
v_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(time_since(load_time), 10.0), 1.0));
|
||||
// f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0));
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1929,9 +1929,9 @@ impl Client {
|
||||
self.tick_terrain()?;
|
||||
|
||||
// Send a ping to the server once every second
|
||||
if self.state.get_time() - self.last_server_ping > 1. {
|
||||
if self.state.get_program_time() - self.last_server_ping > 1. {
|
||||
self.send_msg_err(PingMsg::Ping)?;
|
||||
self.last_server_ping = self.state.get_time();
|
||||
self.last_server_ping = self.state.get_program_time();
|
||||
}
|
||||
|
||||
// 6) Update the server about the player's physics attributes.
|
||||
@ -2269,12 +2269,13 @@ impl Client {
|
||||
ServerGeneral::TimeOfDay(time_of_day, calendar, new_time, time_scale) => {
|
||||
self.target_time_of_day = Some(time_of_day);
|
||||
*self.state.ecs_mut().write_resource() = calendar;
|
||||
*self.state.ecs_mut().write_resource() = time_scale;
|
||||
let mut time = self.state.ecs_mut().write_resource::<Time>();
|
||||
// Avoid side-eye from Einstein
|
||||
// If new time from server is at least 5 seconds ahead, replace client time.
|
||||
// Otherwise try to slightly twean client time (by 1%) to keep it in line with
|
||||
// server time.
|
||||
let dt_adjustment = if new_time.0 > time.0 + 5.0 {
|
||||
self.dt_adjustment = if new_time.0 > time.0 + 5.0 {
|
||||
*time = new_time;
|
||||
1.0
|
||||
} else if new_time.0 > time.0 {
|
||||
@ -2282,7 +2283,6 @@ impl Client {
|
||||
} else {
|
||||
0.99
|
||||
};
|
||||
self.dt_adjustment = dt_adjustment * time_scale.0;
|
||||
},
|
||||
ServerGeneral::EntitySync(entity_sync_package) => {
|
||||
let uid = self.uid();
|
||||
@ -2592,8 +2592,8 @@ impl Client {
|
||||
self.send_msg_err(PingMsg::Pong)?;
|
||||
},
|
||||
PingMsg::Pong => {
|
||||
self.last_server_pong = self.state.get_time();
|
||||
self.last_ping_delta = self.state.get_time() - self.last_server_ping;
|
||||
self.last_server_pong = self.state.get_program_time();
|
||||
self.last_ping_delta = self.state.get_program_time() - self.last_server_ping;
|
||||
|
||||
// Maintain the correct number of deltas for calculating the rolling average
|
||||
// ping. The client sends a ping to the server every second so we should be
|
||||
@ -2664,18 +2664,18 @@ impl Client {
|
||||
// Check that we have an valid connection.
|
||||
// Use the last ping time as a 1s rate limiter, we only notify the user once per
|
||||
// second
|
||||
if self.state.get_time() - self.last_server_ping > 1. {
|
||||
let duration_since_last_pong = self.state.get_time() - self.last_server_pong;
|
||||
if self.state.get_program_time() - self.last_server_ping > 1. {
|
||||
let duration_since_last_pong = self.state.get_program_time() - self.last_server_pong;
|
||||
|
||||
// Dispatch a notification to the HUD warning they will be kicked in {n} seconds
|
||||
const KICK_WARNING_AFTER_REL_TO_TIMEOUT_FRACTION: f64 = 0.75;
|
||||
if duration_since_last_pong
|
||||
>= (self.client_timeout.as_secs() as f64
|
||||
* KICK_WARNING_AFTER_REL_TO_TIMEOUT_FRACTION)
|
||||
&& self.state.get_time() - duration_since_last_pong > 0.
|
||||
&& self.state.get_program_time() - duration_since_last_pong > 0.
|
||||
{
|
||||
frontend_events.push(Event::DisconnectionNotification(
|
||||
(self.state.get_time() - duration_since_last_pong).round() as u64,
|
||||
(self.state.get_program_time() - duration_since_last_pong).round() as u64,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -2683,8 +2683,11 @@ impl Client {
|
||||
let msg_count = self.handle_messages(&mut frontend_events)?;
|
||||
|
||||
if msg_count == 0
|
||||
&& self.state.get_time() - self.last_server_pong > self.client_timeout.as_secs() as f64
|
||||
&& self.state.get_program_time() - self.last_server_pong
|
||||
> self.client_timeout.as_secs() as f64
|
||||
{
|
||||
dbg!(self.state.get_program_time());
|
||||
dbg!(self.last_server_pong);
|
||||
return Err(Error::ServerTimeout);
|
||||
}
|
||||
|
||||
@ -2884,9 +2887,18 @@ impl Client {
|
||||
// Advance state time manually since we aren't calling `State::tick`
|
||||
self.state
|
||||
.ecs()
|
||||
.write_resource::<common::resources::Time>()
|
||||
.write_resource::<common::resources::ProgramTime>()
|
||||
.0 += dt.as_secs_f64();
|
||||
|
||||
let time_scale = *self
|
||||
.state
|
||||
.ecs()
|
||||
.read_resource::<common::resources::TimeScale>();
|
||||
self.state
|
||||
.ecs()
|
||||
.write_resource::<common::resources::Time>()
|
||||
.0 += dt.as_secs_f64() * time_scale.0;
|
||||
|
||||
// Handle new messages from the server.
|
||||
self.handle_new_messages()?;
|
||||
|
||||
@ -2910,9 +2922,9 @@ impl Client {
|
||||
drop(terrain);
|
||||
|
||||
// Send a ping to the server once every second
|
||||
if self.state.get_time() - self.last_server_ping > 1. {
|
||||
if self.state.get_program_time() - self.last_server_ping > 1. {
|
||||
self.send_msg_err(PingMsg::Ping)?;
|
||||
self.last_server_ping = self.state.get_time();
|
||||
self.last_server_ping = self.state.get_program_time();
|
||||
}
|
||||
|
||||
// 6) Update the server about the player's physics attributes.
|
||||
|
@ -11,6 +11,10 @@ pub struct TimeOfDay(pub f64);
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Time(pub f64);
|
||||
|
||||
/// A resource that stores the real tick, local to the server/client.
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||
pub struct ProgramTime(pub f64);
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct TimeScale(pub f64);
|
||||
|
||||
|
@ -13,8 +13,8 @@ use common::{
|
||||
mounting::{Mount, Rider, VolumeRider, VolumeRiders},
|
||||
outcome::Outcome,
|
||||
resources::{
|
||||
DeltaTime, EntitiesDiedLastTick, GameMode, PlayerEntity, PlayerPhysicsSettings, Time,
|
||||
TimeOfDay, TimeScale,
|
||||
DeltaTime, EntitiesDiedLastTick, GameMode, PlayerEntity, PlayerPhysicsSettings,
|
||||
ProgramTime, Time, TimeOfDay, TimeScale,
|
||||
},
|
||||
shared_server_config::ServerConstants,
|
||||
slowjob::SlowJobPool,
|
||||
@ -269,6 +269,7 @@ impl State {
|
||||
ecs.insert(Calendar::default());
|
||||
ecs.insert(WeatherGrid::new(Vec2::zero()));
|
||||
ecs.insert(Time(0.0));
|
||||
ecs.insert(ProgramTime(0.0));
|
||||
ecs.insert(TimeScale(1.0));
|
||||
|
||||
// Register unsynced resources used by the ECS.
|
||||
@ -437,6 +438,11 @@ impl State {
|
||||
/// Note that this does not correspond to the time of day.
|
||||
pub fn get_time(&self) -> f64 { self.ecs.read_resource::<Time>().0 }
|
||||
|
||||
/// Get the current true in-game time, unaffected by time_scale.
|
||||
///
|
||||
/// Note that this does not correspond to the time of day.
|
||||
pub fn get_program_time(&self) -> f64 { self.ecs.read_resource::<ProgramTime>().0 }
|
||||
|
||||
/// Get the current delta time.
|
||||
pub fn get_delta_time(&self) -> f32 { self.ecs.read_resource::<DeltaTime>().0 }
|
||||
|
||||
@ -637,6 +643,7 @@ impl State {
|
||||
self.ecs.write_resource::<TimeOfDay>().0 +=
|
||||
dt.as_secs_f64() * server_constants.day_cycle_coefficient * time_scale;
|
||||
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64() * time_scale;
|
||||
self.ecs.write_resource::<ProgramTime>().0 += dt.as_secs_f64();
|
||||
|
||||
// Update delta time.
|
||||
// Beyond a delta time of MAX_DELTA_TIME, start lagging to avoid skipping
|
||||
|
@ -2,7 +2,7 @@ use crate::client::Client;
|
||||
use common::{
|
||||
comp::{ChatMode, ChatType, Content, Group, Player},
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::Time,
|
||||
resources::ProgramTime,
|
||||
uid::Uid,
|
||||
};
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
@ -81,7 +81,7 @@ impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
Read<'a, Time>,
|
||||
Read<'a, ProgramTime>,
|
||||
ReadStorage<'a, Uid>,
|
||||
ReadStorage<'a, ChatMode>,
|
||||
ReadStorage<'a, Player>,
|
||||
@ -95,7 +95,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
fn run(
|
||||
_job: &mut Job<Self>,
|
||||
(entities, server_event_bus, time, uids, chat_modes, players, groups, mut clients): Self::SystemData,
|
||||
(entities, server_event_bus, program_time, uids, chat_modes, players, groups, mut clients): Self::SystemData,
|
||||
) {
|
||||
(&entities, &mut clients, players.maybe())
|
||||
.par_join()
|
||||
@ -117,7 +117,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
if let Ok(1_u64..=u64::MAX) = res {
|
||||
// Update client ping.
|
||||
client.last_ping = time.0
|
||||
client.last_ping = program_time.0
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{client::Client, Settings};
|
||||
use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::Time,
|
||||
resources::ProgramTime,
|
||||
};
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use common_net::msg::PingMsg;
|
||||
@ -26,7 +26,7 @@ impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
Read<'a, Time>,
|
||||
Read<'a, ProgramTime>,
|
||||
WriteStorage<'a, Client>,
|
||||
Read<'a, Settings>,
|
||||
);
|
||||
@ -37,7 +37,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
fn run(
|
||||
_job: &mut Job<Self>,
|
||||
(entities, server_event_bus, time, mut clients, settings): Self::SystemData,
|
||||
(entities, server_event_bus, program_time, mut clients, settings): Self::SystemData,
|
||||
) {
|
||||
(&entities, &mut clients).par_join().for_each_init(
|
||||
|| server_event_bus.emitter(),
|
||||
@ -59,11 +59,11 @@ impl<'a> System<'a> for Sys {
|
||||
},
|
||||
Ok(1_u64..=u64::MAX) => {
|
||||
// Update client ping.
|
||||
client.last_ping = time.0
|
||||
client.last_ping = program_time.0
|
||||
},
|
||||
Ok(0) => {
|
||||
let last_ping: f64 = client.last_ping;
|
||||
if time.0 - last_ping > settings.client_timeout.as_secs() as f64
|
||||
if program_time.0 - last_ping > settings.client_timeout.as_secs() as f64
|
||||
// Timeout
|
||||
{
|
||||
info!(?entity, "timeout error with client, disconnecting");
|
||||
@ -71,7 +71,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
common::comp::DisconnectReason::Timeout,
|
||||
));
|
||||
} else if time.0 - last_ping
|
||||
} else if program_time.0 - last_ping
|
||||
> settings.client_timeout.as_secs() as f64 * 0.5
|
||||
{
|
||||
// Try pinging the client if the timeout is nearing.
|
||||
|
@ -91,6 +91,8 @@ pub struct Shadow {
|
||||
pos_radius: [f32; 4],
|
||||
}
|
||||
|
||||
pub const TIME_OVERFLOW: f64 = 300000.0;
|
||||
|
||||
impl Globals {
|
||||
/// Create global consts from the provided parameters.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@ -127,10 +129,27 @@ impl Globals {
|
||||
focus_off: Vec4::from(focus_pos).map(|e: f32| e.trunc()).into_array(),
|
||||
focus_pos: Vec4::from(focus_pos).map(|e: f32| e.fract()).into_array(),
|
||||
view_distance: [view_distance, tgt_detail, map_bounds.x, map_bounds.y],
|
||||
time_of_day: [time_of_day as f32; 4],
|
||||
time_of_day: [
|
||||
(time_of_day % (3600.0 * 24.0)) as f32,
|
||||
// TODO: Find a better way than just pure repetition. A solution like
|
||||
// the one applied to `tick` could work, but it would be used in hot
|
||||
// shader_code. So we might not want to use that method there.
|
||||
//
|
||||
// Repeats every 1000 ingame days. This increases by dt * (1 / 3600)
|
||||
// per tick on defualt server settings. So those per tick changes can't
|
||||
// really be fully represented at a value above `50.0`.
|
||||
(time_of_day / (3600.0 * 24.0) % 1000.0) as f32,
|
||||
0.0,
|
||||
0.0,
|
||||
],
|
||||
sun_dir: Vec4::from_direction(Self::get_sun_dir(time_of_day)).into_array(),
|
||||
moon_dir: Vec4::from_direction(Self::get_moon_dir(time_of_day)).into_array(),
|
||||
tick: [tick as f32; 4],
|
||||
tick: [
|
||||
(tick % TIME_OVERFLOW) as f32,
|
||||
(tick / TIME_OVERFLOW).floor() as f32,
|
||||
tick as f32,
|
||||
0.0,
|
||||
],
|
||||
// Provide the shadow map far plane as well.
|
||||
screen_res: [
|
||||
screen_res.x as f32,
|
||||
@ -165,7 +184,7 @@ impl Globals {
|
||||
gamma_exposure: [gamma, exposure, 0.0, 0.0],
|
||||
last_lightning: last_lightning
|
||||
.0
|
||||
.with_w(last_lightning.1 as f32)
|
||||
.with_w((last_lightning.1 % TIME_OVERFLOW) as f32)
|
||||
.into_array(),
|
||||
wind_vel: wind_vel.into_array(),
|
||||
ambiance: ambiance.clamped(0.0, 1.0),
|
||||
@ -176,8 +195,8 @@ impl Globals {
|
||||
}
|
||||
|
||||
fn get_angle_rad(time_of_day: f64) -> f32 {
|
||||
const TIME_FACTOR: f32 = (std::f32::consts::PI * 2.0) / (3600.0 * 24.0);
|
||||
time_of_day as f32 * TIME_FACTOR
|
||||
const TIME_FACTOR: f64 = (std::f64::consts::PI * 2.0) / (3600.0 * 24.0);
|
||||
((time_of_day * TIME_FACTOR) % (std::f64::consts::PI * 2.0)) as f32
|
||||
}
|
||||
|
||||
/// Computes the direction of light from the sun based on the time of day.
|
||||
|
@ -148,7 +148,7 @@ impl Instance {
|
||||
) -> Self {
|
||||
use rand::Rng;
|
||||
Self {
|
||||
inst_time: inst_time as f32,
|
||||
inst_time: (inst_time % super::TIME_OVERFLOW) as f32,
|
||||
inst_lifespan: lifespan,
|
||||
inst_entropy: rand::thread_rng().gen(),
|
||||
inst_mode: inst_mode as i32,
|
||||
@ -166,7 +166,7 @@ impl Instance {
|
||||
) -> Self {
|
||||
use rand::Rng;
|
||||
Self {
|
||||
inst_time: inst_time as f32,
|
||||
inst_time: (inst_time % super::TIME_OVERFLOW) as f32,
|
||||
inst_lifespan: lifespan,
|
||||
inst_entropy: rand::thread_rng().gen(),
|
||||
inst_mode: inst_mode as i32,
|
||||
|
@ -533,6 +533,31 @@ impl Scene {
|
||||
.get(scene_data.viewpoint_entity)
|
||||
.map_or(Quaternion::identity(), |ori| ori.to_quat());
|
||||
|
||||
let viewpoint_look_ori = ecs
|
||||
.read_storage::<comp::CharacterActivity>()
|
||||
.get(scene_data.viewpoint_entity)
|
||||
.and_then(|activity| activity.look_dir)
|
||||
.map(|dir| {
|
||||
let d = dir.to_vec();
|
||||
|
||||
let pitch = (-d.z).asin();
|
||||
let yaw = d.x.atan2(d.y);
|
||||
|
||||
Vec3::new(yaw, pitch, 0.0)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let q = viewpoint_ori;
|
||||
let sinr_cosp = 2.0 * (q.w * q.x + q.y * q.z);
|
||||
let cosr_cosp = 1.0 - 2.0 * (q.x * q.x + q.y * q.y);
|
||||
let pitch = sinr_cosp.atan2(cosr_cosp);
|
||||
|
||||
let siny_cosp = 2.0 * (q.w * q.z + q.x * q.y);
|
||||
let cosy_cosp = 1.0 - 2.0 * (q.y * q.y + q.z * q.z);
|
||||
let yaw = siny_cosp.atan2(cosy_cosp);
|
||||
|
||||
Vec3::new(-yaw, -pitch, 0.0)
|
||||
});
|
||||
|
||||
let viewpoint_scale = ecs
|
||||
.read_storage::<comp::Scale>()
|
||||
.get(scene_data.viewpoint_entity)
|
||||
@ -558,24 +583,7 @@ impl Scene {
|
||||
.rotate_by(Vec3::from([0.0, self.camera_input_state.y, 0.0]));
|
||||
} else {
|
||||
// Otherwise set the cameras rotation to the viewpoints
|
||||
let q = viewpoint_ori;
|
||||
let sinr_cosp = 2.0 * (q.w * q.x + q.y * q.z);
|
||||
let cosr_cosp = 1.0 - 2.0 * (q.x * q.x + q.y * q.y);
|
||||
let roll = sinr_cosp.atan2(cosr_cosp);
|
||||
|
||||
let sinp = 2.0 * (q.w * q.y - q.z * q.x);
|
||||
let pitch = if sinp.abs() >= 1.0 {
|
||||
std::f32::consts::FRAC_PI_2.copysign(sinp)
|
||||
} else {
|
||||
sinp.asin()
|
||||
};
|
||||
|
||||
let siny_cosp = 2.0 * (q.w * q.z + q.x * q.y);
|
||||
let cosy_cosp = 1.0 - 2.0 * (q.y * q.y + q.z * q.z);
|
||||
let yaw = siny_cosp.atan2(cosy_cosp);
|
||||
|
||||
self.camera
|
||||
.set_orientation_instant(Vec3::new(-yaw, pitch, roll));
|
||||
self.camera.set_orientation(viewpoint_look_ori);
|
||||
}
|
||||
|
||||
let viewpoint_offset = if is_humanoid {
|
||||
|
@ -1195,6 +1195,11 @@ impl PlayState for SessionState {
|
||||
if self.viewpoint_entity.is_some() {
|
||||
self.viewpoint_entity = None;
|
||||
self.scene.camera_mut().set_mode(CameraMode::Freefly);
|
||||
let mut ori = self.scene.camera().get_orientation();
|
||||
// Remove any roll that could have possibly been set to the
|
||||
// camera as a result of spectating.
|
||||
ori.z = 0.0;
|
||||
self.scene.camera_mut().set_orientation(ori);
|
||||
} else if let Some(interactable) = &self.interactable {
|
||||
if self.scene.camera().get_mode() == CameraMode::Freefly {
|
||||
match interactable {
|
||||
|
Loading…
Reference in New Issue
Block a user