weather: add wet road glow and light halos

This commit is contained in:
Richard Zink committed 2026-10-12 23:06:53 +02:00
1 parent fb113e2e2d
commit 92dd812072
2 files changed
+52 -5

No files matched your search

+44 -5
View File
@@ -3870,6 +3870,8 @@ var CAR_FRAG_SRC = [
'uniform float uBright;', // band brightness (CONFIG.carLights.bandBrightness)',
'uniform float uFadeA;', // distance where the fade starts',
'uniform float uFadeB;', // distance where it is fully faded',
'uniform float uWet;', // wet-road factor 0..1',
'uniform float uWetGain;', // extra road glow when wet',
'varying float vLen;',
'varying float vSide;',
'varying float vDens;',
@@ -3886,9 +3888,13 @@ var CAR_FRAG_SRC = [
// what a road looks like when the individual vehicle points are',
// closer together than one light - the "bar" along the A-net.',
'float body = 1.0 - smoothstep(0.0, 1.0, abs(vSide));',
'float a = dens * body * uNight * df * uBright;',
'float wet = clamp(uWet, 0.0, 1.0);',
'float a = dens * body * uNight * df * uBright * (1.0 + wet * uWetGain);',
'if (a <= 0.002) discard;',
'gl_FragColor = vec4(vec3(1.0, 0.82, 0.58) * a, 1.0);',
'vec3 dryCol = vec3(1.0, 0.82, 0.58);',
'vec3 wetCol = vec3(0.72, 0.82, 1.0);',
'vec3 col = mix(dryCol, wetCol, wet * 0.55);',
'gl_FragColor = vec4(col * a, 1.0);',
'}'
].join('\n');
@@ -3975,6 +3981,8 @@ var CARP_FRAG_SRC = [
'uniform float uBright;', // overall light intensity',
'uniform float uFadeA;', // distance where the fade starts',
'uniform float uFadeB;', // distance where it is fully faded',
'uniform float uWet;', // wet-road factor 0..1',
'uniform float uWetGain;', // extra halo on lights when wet',
'varying float vApproach;',
'varying float vDist;',
'varying float vSeed;',
@@ -3989,8 +3997,9 @@ var CARP_FRAG_SRC = [
'vec2 pc = gl_PointCoord - 0.5;',
'float d = length(pc) * 2.0;',
// hot core plus a wide faint halo: a round light at any size',
'float wet = clamp(uWet, 0.0, 1.0);',
'float core = exp(-d * d * 4.0);',
'float halo = (1.0 - smoothstep(0.0, 1.0, d)) * 0.30;',
'float halo = (1.0 - smoothstep(0.0, 1.0, d)) * (0.30 + wet * uWetGain);',
'float g = max(core, halo);',
'if (g <= 0.004) discard;',
// soft occupancy + per-vehicle life cycle: a car fades in as the',
@@ -4894,7 +4903,9 @@ function applyCarBuild(gl, res) {
halfW: gl.getUniformLocation(carProg, 'uHalfW'),
bright: gl.getUniformLocation(carProg, 'uBright'),
fadeA: gl.getUniformLocation(carProg, 'uFadeA'),
fadeB: gl.getUniformLocation(carProg, 'uFadeB')
fadeB: gl.getUniformLocation(carProg, 'uFadeB'),
wet: gl.getUniformLocation(carProg, 'uWet'),
wetGain: gl.getUniformLocation(carProg, 'uWetGain')
};
}
}
@@ -6041,6 +6052,26 @@ var WEATHER_LIGHTNING_MIN_DELAY = (typeof WEATHER_LIGHTNING_CFG.minDelayS === 'n
var WEATHER_LIGHTNING_MAX_DELAY = (typeof WEATHER_LIGHTNING_CFG.maxDelayS === 'number') ? Math.max(WEATHER_LIGHTNING_MIN_DELAY, WEATHER_LIGHTNING_CFG.maxDelayS) : 45;
var WEATHER_LIGHTNING_DOUBLE = WEATHER_LIGHTNING_CFG.doubleFlash !== false;
var lightningNextT = 0, lightningSeq = 0, lightningSeqT = 0, lightningFlash = 0;
var WET_ROADS_CFG = WEATHER_FX_CFG.wetRoads || {};
var WET_ROADS_ON = WET_ROADS_CFG.enabled !== false;
var WET_ROADS_DRY_MINUTES = (typeof WET_ROADS_CFG.dryMinutes === 'number') ? Math.max(1, WET_ROADS_CFG.dryMinutes) : 30;
var WET_ROADS_GAIN = (typeof WET_ROADS_CFG.roadGain === 'number') ? Math.max(0, WET_ROADS_CFG.roadGain) : 0.8;
var WET_LIGHT_GAIN = (typeof WET_ROADS_CFG.lightGain === 'number') ? Math.max(0, WET_ROADS_CFG.lightGain) : 0.35;
var roadWetness = 0, lastWetT = null;
function updateRoadWetness(now) {
if (!WET_ROADS_ON) { roadWetness = 0; lastWetT = null; return 0; }
if (lastWetT === null) { lastWetT = now; return roadWetness; }
var dt = Math.max(0, Math.min(5, now - lastWetT));
lastWetT = now;
var wx = window.__currentWeather || {};
var precip = Number(wx.precipMm || 0);
var snow = Number(wx.snowMm || 0);
var input = Math.min(1.0, (precip + snow * 0.55) * 0.75);
var dry = dt / (WET_ROADS_DRY_MINUTES * 60.0);
roadWetness = Math.max(0, Math.min(1, roadWetness + input * dt * 0.25 - dry));
return roadWetness;
}
function updateLightning(now) {
if (!WEATHER_LIGHTNING_ON) {
@@ -6795,6 +6826,7 @@ window.clouds3dRender = function(target) {
// Aggregate artificial-light level (road ribbon, density curves,
// aircraft): the mean over the per-light thresholds.
var carNight = lightFactor(window.__currentSunAlt || 0);
var _roadWet = updateRoadWetness(now);
if (carProg && (carVboM || carVboB) && carNight > 0.01) {
var carPxScale = Math.max(0.45, Math.min(1.25, gl.drawingBufferHeight / 1080));
var tCurve = Math.max(0, Math.min(1, (carNight - 0.10) / 0.40));
@@ -6821,6 +6853,8 @@ window.clouds3dRender = function(target) {
gl.uniform1f(carUniforms.bright, CAR_BAND_BRIGHT);
gl.uniform1f(carUniforms.fadeA, CAR_FADE_A);
gl.uniform1f(carUniforms.fadeB, CAR_FADE_B);
gl.uniform1f(carUniforms.wet, _roadWet);
gl.uniform1f(carUniforms.wetGain, WET_ROADS_GAIN);
gl.enable(gl.DEPTH_TEST);
gl.depthMask(false);
gl.enable(gl.BLEND);
@@ -6876,7 +6910,9 @@ window.clouds3dRender = function(target) {
sunAlt: gl.getUniformLocation(cpp, 'uSunAlt'),
lightHi: gl.getUniformLocation(cpp, 'uLightHi'),
lightLo: gl.getUniformLocation(cpp, 'uLightLo'),
lightSoft: gl.getUniformLocation(cpp, 'uLightSoft')
lightSoft: gl.getUniformLocation(cpp, 'uLightSoft'),
wet: gl.getUniformLocation(cpp, 'uWet'),
wetGain: gl.getUniformLocation(cpp, 'uWetGain')
};
}
}
@@ -6907,6 +6943,8 @@ window.clouds3dRender = function(target) {
gl.uniform1f(carPtsUniforms.bright, CAR_BRIGHT);
gl.uniform1f(carPtsUniforms.fadeA, CAR_FADE_A);
gl.uniform1f(carPtsUniforms.fadeB, CAR_FADE_B);
gl.uniform1f(carPtsUniforms.wet, _roadWet);
gl.uniform1f(carPtsUniforms.wetGain, WET_LIGHT_GAIN);
var carPtsGroup = function (vbo, count, dash, speed, maxDens) {
if (!vbo || !count) return;
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
@@ -7318,6 +7356,7 @@ window.clouds3dRender = function(target) {
rain: +_weather[0].toFixed(2),
snow: +_weather[1].toFixed(2),
lightning: +lightningFlash.toFixed(2),
wet: +roadWetness.toFixed(2),
code: Number((window.__currentWeather || {}).code || 0)
};
var _rainI = _weather[0];