M1c: weather, snap building, shelter, beds and regrowth
- Seeded weather (clear/cloudy/rain/storm, snow and blizzards on cold days and above the snowline), lightning, synthesised rain/wind/thunder sound - Rain/snow particles stopped by roofs; wet ground, settled snow and wind via global shader uniforms - Snap-together wood floor, wall, door, roof and gable with structural support, collapse and X to dismantle - Shelter detection: dry under a roof, warmer and Rested inside with a fire; rain burns an uncovered campfire faster - Bed sets the spawn point and lets you sleep through the night - Trees, boulders and ground pickups regrow; timers saved - Grass cleared under floors; shorter HUD hint - New test_weather_building suite (62 checks) and tests/run_all.sh, which also fails on script errors
This commit is contained in:
@@ -5,6 +5,22 @@
|
||||
|
||||
uniform sampler2D noise_tex : filter_linear_mipmap, repeat_enable;
|
||||
|
||||
// Set every frame by weather_fx.gd (declared in project.godot [shader_globals]).
|
||||
global uniform float weather_wet; // 0..1 rain-soaked ground
|
||||
global uniform float weather_snow; // 0..1 settled snow
|
||||
global uniform float weather_wind; // wind multiplier, ~1 on a calm day
|
||||
|
||||
// Wet surfaces: darker and glossier.
|
||||
vec3 wet_albedo(vec3 c, float wet) {
|
||||
return c * (1.0 - 0.35 * wet);
|
||||
}
|
||||
|
||||
// Settled snow on upward-facing surfaces, patchy where it's thin.
|
||||
float snow_mask(float up, float patch) {
|
||||
float s = weather_snow * 1.25 - (1.0 - patch) * 0.45;
|
||||
return clamp(s, 0.0, 1.0) * smoothstep(0.55, 0.85, up);
|
||||
}
|
||||
|
||||
float nz(vec2 p) {
|
||||
return texture(noise_tex, p).r;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ void vertex() {
|
||||
float phase = dot(inst_pos.xz, vec2(0.13, 0.17));
|
||||
float gust = nz(inst_pos.xz * 0.012 + vec2(TIME * 0.02, TIME * 0.013));
|
||||
vec3 sway = vec3(sin(TIME * 0.9 + phase), 0.0, cos(TIME * 0.7 + phase * 1.3) * 0.6);
|
||||
sway *= wind_strength * h * (0.4 + gust);
|
||||
sway += vec3(sin(TIME * 3.7 + dot(VERTEX, vec3(3.1, 1.7, 2.3)) + phase)) * flutter * clamp(VERTEX.y, 0.0, 1.0);
|
||||
float wk = min(weather_wind, 2.2); // storms bend crowns, but not into the ground
|
||||
sway *= wind_strength * wk * h * (0.4 + gust);
|
||||
sway += vec3(sin(TIME * 3.7 * (0.7 + 0.3 * wk) + dot(VERTEX, vec3(3.1, 1.7, 2.3)) + phase)) * flutter * wk * clamp(VERTEX.y, 0.0, 1.0);
|
||||
VERTEX += (inverse(MODEL_MATRIX) * vec4(sway, 0.0)).xyz;
|
||||
}
|
||||
|
||||
@@ -27,6 +28,10 @@ void fragment() {
|
||||
float v = nz(inst_pos.xz * 0.045);
|
||||
vec3 tint = mix(vec3(0.88, 1.0, 0.85), vec3(1.12, 1.04, 0.78), v);
|
||||
vec3 col = to_linear(COLOR.rgb) * tint;
|
||||
// Snow on the upper faces of the crowns.
|
||||
float up = (INV_VIEW_MATRIX * vec4(NORMAL, 0.0)).y;
|
||||
col = mix(col, vec3(0.86, 0.89, 0.93), snow_mask(up, v) * 0.9);
|
||||
col = wet_albedo(col, weather_wet * 0.5);
|
||||
ALBEDO = col;
|
||||
ROUGHNESS = 0.85;
|
||||
SPECULAR = 0.3;
|
||||
|
||||
@@ -23,7 +23,7 @@ void vertex() {
|
||||
vec2 wd = normalize(wind_dir);
|
||||
float gust = nz(wp.xz * 0.015 - TIME * 0.05 * wd);
|
||||
float sway = sin(TIME * 1.8 + wp.x * 0.35 + wp.z * 0.25) * 0.35 + gust * 1.3 - 0.4;
|
||||
float k = wind_strength * hfac * hfac;
|
||||
float k = wind_strength * weather_wind * hfac * hfac;
|
||||
vec3 off = vec3(wd.x * sway * k, -abs(sway) * k * 0.3, wd.y * sway * k);
|
||||
VERTEX += (inverse(MODEL_MATRIX) * vec4(off, 0.0)).xyz;
|
||||
}
|
||||
@@ -35,6 +35,10 @@ void fragment() {
|
||||
base *= 0.82 + 0.36 * nz(inst_pos.xz * 0.17);
|
||||
vec3 col = base * mix(0.55, 1.0, hfac); // darker at the root
|
||||
col = mix(col, col * tip_tint * 1.3, smoothstep(0.6, 1.0, hfac) * 0.3);
|
||||
// Snow weighs down on the blades from the root up; rain darkens them.
|
||||
float snowy = clamp(weather_snow * 1.3 - hfac * 0.5 + (nz(inst_pos.xz * 0.17) - 0.5) * 0.4, 0.0, 0.85);
|
||||
col = mix(col, vec3(0.62, 0.65, 0.7), snowy); // greyer than ground snow: blades are lit as if flat
|
||||
col = wet_albedo(col, weather_wet * 0.6 * (1.0 - snowy));
|
||||
ALBEDO = col;
|
||||
ROUGHNESS = 0.9;
|
||||
SPECULAR = 0.2;
|
||||
|
||||
@@ -33,8 +33,13 @@ void fragment() {
|
||||
float snow = smoothstep(snow_height - 3.0, snow_height + 3.0, w_pos.y + (a - 0.5) * 10.0);
|
||||
snow *= smoothstep(0.35, 0.7, w_nrm.y);
|
||||
col = mix(col, snow_col, snow);
|
||||
float wsnow = snow_mask(w_nrm.y, a);
|
||||
col = mix(col, snow_col, wsnow);
|
||||
snow = max(snow, wsnow);
|
||||
float wet = weather_wet * (1.0 - snow);
|
||||
col = wet_albedo(col, wet);
|
||||
|
||||
ALBEDO = col;
|
||||
ROUGHNESS = mix(mix(0.8, 0.95, moss), 0.6, snow);
|
||||
ROUGHNESS = mix(mix(mix(0.8, 0.95, moss), 0.6, snow), 0.3, wet * 0.8);
|
||||
SPECULAR = 0.35;
|
||||
}
|
||||
|
||||
@@ -66,8 +66,16 @@ void fragment() {
|
||||
snow_m *= 1.0 - smoothstep(0.5, 0.7, slope);
|
||||
col = mix(col, snow_col * (0.92 + 0.08 * fine), snow_m);
|
||||
|
||||
// Weather: fresh snow settles on flat ground above the waterline; rain
|
||||
// darkens and glosses everything else.
|
||||
float wsnow = snow_mask(w_nrm.y, fine * 0.6 + mid * 0.4) * step(water_level + 0.1, w_pos.y);
|
||||
col = mix(col, snow_col * (0.9 + 0.1 * fine), wsnow);
|
||||
snow_m = max(snow_m, wsnow);
|
||||
float wet = weather_wet * (1.0 - snow_m);
|
||||
col = wet_albedo(col, wet);
|
||||
|
||||
ALBEDO = col;
|
||||
ROUGHNESS = mix(mix(0.95, 0.82, rock_m), 0.6, snow_m);
|
||||
ROUGHNESS = mix(mix(mix(0.95, 0.82, rock_m), 0.6, snow_m), 0.4, wet * 0.8);
|
||||
SPECULAR = 0.3;
|
||||
NORMAL_MAP = texture(normal_tex, w_pos.xz * 0.35).rgb;
|
||||
NORMAL_MAP_DEPTH = mix(0.5, 1.4, rock_m) * (1.0 - snow_m * 0.7);
|
||||
|
||||
Reference in New Issue
Block a user