progress logs behind CONFIG.debug, CONFIG.antialias + high-performance context, cheaper cloud sampling (skip far detail octave and redundant self-shading probe), brighter night contrails via CONFIG.flights.contrailNight, window.__flightDbg counters, real sun/moon by default
This commit is contained in:
1 parent
113e4c522d
commit
6d21b37e8f
2 files changed
+98
-37
No files matched your search
@@ -17,6 +17,7 @@
|
||||
* tile/DEM/Overpass origin, figure-eight centre
|
||||
* renderScale internal 3D resolution (0.2..1) with blocky upscale
|
||||
* maxFps scene frame cap (0 = free running)
|
||||
* antialias MSAA on the WebGL framebuffer (true/false)
|
||||
* weatherSim ignore Open-Meteo and cycle the weather themes
|
||||
* tiles basemap/elevation cache behaviour + debug overlays
|
||||
* ground basemap style
|
||||
@@ -51,7 +52,7 @@ window.CONFIG = {
|
||||
theme: 'ash', // 'ash' | 'nord' | 'gruvbox' (see window.THEMES)
|
||||
language: 'en', // 'en', 'de' - keys of the i18n.js dictionaries
|
||||
timeFormat: 'DD. MMMM, YYYY ‒ HH:mm:SS',
|
||||
debug: 0, // 1 = debug panel with the theme palette
|
||||
debug: 0, // 1 = debug panel + progress logs in the console
|
||||
credits: true, // false = hide the attribution line
|
||||
units: { temperature: 'C' }, // 'F' for Fahrenheit
|
||||
|
||||
@@ -67,6 +68,10 @@ window.CONFIG = {
|
||||
// Scene frame cap. All motion is time-based, so this only changes
|
||||
// smoothness, never speed. 0 = free running (vsync).
|
||||
maxFps: 30,
|
||||
// MSAA on the WebGL framebuffer. Costs fill rate, and with renderScale
|
||||
// below 1 the pixel blocks dominate anyway - set false if the scene is
|
||||
// GPU bound. Read once at context creation, so a reload is needed.
|
||||
antialias: true,
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Location
|
||||
@@ -169,11 +174,16 @@ window.CONFIG = {
|
||||
wStrip: 1,
|
||||
// Contrails: contrailChance of the aircraft leaves a trail once
|
||||
// above contrailStartKm, visible for contrailLifeS seconds.
|
||||
contrailChance: 0.85,
|
||||
contrailChance: 1.00,
|
||||
contrailStartKm: 6,
|
||||
contrailLifeS: 300,
|
||||
contrailWidthM: 620, // full trail width
|
||||
contrailFadeKm: 100, // fully faded at this distance (ramp starts at 35 %)
|
||||
// Night contrast: a physically scaled contrail is a faint grey thread
|
||||
// that disappears at 4x pixel scale, so this is the night share of its
|
||||
// opacity (0.34 was the old value) and it also drives the gain on the
|
||||
// moon/star light. 0 = night contrails off, 1 = strongest.
|
||||
contrailNight: 0.85,
|
||||
// Night strobes. Point size shrinks with distance but never below
|
||||
// lightPx and never above lightMaxPx for a jet directly overhead.
|
||||
// The white strobe is a double flash: two flashes blinkFlashS long,
|
||||
@@ -301,11 +311,12 @@ window.CONFIG = {
|
||||
// east, culminates south, sets west) and the clock plus the sun/moon
|
||||
// tables follow the simulated date. false uses the real SunCalc positions.
|
||||
day: {
|
||||
simulation: true,
|
||||
cycleSeconds: 60, // 60 s = one simulated day per minute
|
||||
simulation: false, // false = the real sun and moon (default)
|
||||
cycleSeconds: 60, // only used when simulation is true:
|
||||
// 60 s = one simulated day per minute
|
||||
fixedTime: null // 'HH:MM' or 0-24 freezes the sim clock
|
||||
// (clouds, traffic and flights keep moving)
|
||||
// day: { simulation: false } // real sun and moon
|
||||
// day: { simulation: true, cycleSeconds: 60 } // accelerated day
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
Vendored
+82
-32
@@ -10,6 +10,13 @@
|
||||
|
||||
(function() {
|
||||
|
||||
// Progress and build diagnostics are only interesting while the debug panel
|
||||
// is on; a wall display must not fill the console with them.
|
||||
var DEBUG_LOG = !!(window.CONFIG && window.CONFIG.debug);
|
||||
function dbgLog() {
|
||||
if (DEBUG_LOG) console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
function makeShader(gl, type, src) {
|
||||
var s = gl.createShader(type);
|
||||
gl.shaderSource(s, src);
|
||||
@@ -147,8 +154,13 @@ var FRAG_SRC = [
|
||||
// the fine structure that cannot be resolved disappears.
|
||||
'float cloudDensity(vec3 p, float baseThresh, float soft) {',
|
||||
'float n = fbm3(p * 0.35 + vec3(0.0, 0.0, uTime * 0.06));',
|
||||
'float d = fbm3(p * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
|
||||
'n = n + d * mix(0.20, 0.0, soft);',
|
||||
// The detail octave weighs at most 0.20 and fades to zero with
|
||||
// distance; past soft = 0.95 it contributes under 1 %, so the whole
|
||||
// 4-octave lookup is skipped for the (numerous) far samples.
|
||||
'if (soft < 0.95) {',
|
||||
'float d = fbm3(p * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
|
||||
'n = n + d * mix(0.20, 0.0, soft);',
|
||||
'}',
|
||||
// Cloud layer between uCloudBot and uCloudTop, densest in the
|
||||
// middle (bell curve).
|
||||
'float h = clamp((p.y - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);',
|
||||
@@ -343,7 +355,10 @@ var FRAG_SRC = [
|
||||
'vec3 albC = uCloudAlbedo * mix(0.78, 1.0, lit);',
|
||||
// Self-shading: probe the density towards the sun, so
|
||||
// thick cloud interior stays dark and thin edges light up.
|
||||
'float thick = cloudDensity(p + uSunDir * 2.2, baseThresh, cSoft);',
|
||||
// d > 0.85 already clamps selfLit to its floor, so the
|
||||
// second density lookup (a whole fbm) is skipped there.
|
||||
'float thick = (d > 0.85) ? 1.0 :',
|
||||
'cloudDensity(p + uSunDir * 2.2, baseThresh, cSoft);',
|
||||
'float selfLit = clamp(1.0 - thick * 1.3, 0.12, 1.0);',
|
||||
// Forward scattering - clouds brighten towards the sun
|
||||
// (silver lining) instead of a flat day/night ramp.
|
||||
@@ -484,8 +499,13 @@ var CLOUD_SAMPLER_GLSL = [
|
||||
'}',
|
||||
'float cloudDensity(vec3 p, float baseThresh, float soft) {',
|
||||
'float n = fbm3(p * 0.35 + vec3(0.0, 0.0, uTime * 0.06));',
|
||||
'float d = fbm3(p * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
|
||||
'n = n + d * mix(0.20, 0.0, soft);',
|
||||
// The detail octave weighs at most 0.20 and fades to zero with
|
||||
// distance; past soft = 0.95 it contributes under 1 %, so the whole
|
||||
// 4-octave lookup is skipped for the (numerous) far samples.
|
||||
'if (soft < 0.95) {',
|
||||
'float d = fbm3(p * 1.4 + vec3(uTime * 0.04, 7.3, uTime * 0.03));',
|
||||
'n = n + d * mix(0.20, 0.0, soft);',
|
||||
'}',
|
||||
'float h = clamp((p.y - uCloudBot) / (uCloudTop - uCloudBot), 0.0, 1.0);',
|
||||
'float profile = 4.0 * h * (1.0 - h);',
|
||||
'profile = max(profile, 0.0);',
|
||||
@@ -627,8 +647,12 @@ var TERRAIN_FRAG_SRC = [
|
||||
].join('\n');
|
||||
|
||||
function init(canvas) {
|
||||
var gl = canvas.getContext('webgl2', { antialias: false, alpha: false })
|
||||
|| canvas.getContext('webgl', { antialias: false, alpha: false });
|
||||
// CONFIG.antialias (default on) asks for MSAA on the default framebuffer.
|
||||
// It costs fill rate, and at renderScale < 1 the pixel blocks dominate
|
||||
// anyway - set it to false if the scene is GPU bound.
|
||||
var AA_ON = !(window.CONFIG && window.CONFIG.antialias === false);
|
||||
var glOpts = { antialias: AA_ON, alpha: false, powerPreference: 'high-performance' };
|
||||
var gl = canvas.getContext('webgl2', glOpts) || canvas.getContext('webgl', glOpts);
|
||||
if (!gl) {
|
||||
console.error('clouds3d: WebGL not available');
|
||||
return null;
|
||||
@@ -1195,7 +1219,7 @@ function tileProbeProxy() {
|
||||
var type = (r.headers.get('Content-Type') || '').toLowerCase();
|
||||
if (r.ok && type.indexOf('image/') === 0) {
|
||||
apply();
|
||||
console.log('[clouds3d] tiles: using dev proxy ' + path);
|
||||
dbgLog('[clouds3d] tiles: using dev proxy ' + path);
|
||||
}
|
||||
}, function () {});
|
||||
}
|
||||
@@ -2151,7 +2175,7 @@ function opProbeProxy() {
|
||||
}).then(function (r) {
|
||||
if (r.status === 200) {
|
||||
CAR_ENDPOINTS = OP_PUBLIC.concat(OP_PROXY);
|
||||
console.log('[clouds3d] overpass: dev proxy available');
|
||||
dbgLog('[clouds3d] overpass: dev proxy available');
|
||||
}
|
||||
}, function () {});
|
||||
}
|
||||
@@ -2433,11 +2457,11 @@ function fetchMotorways() {
|
||||
var fresh = 0; // cells that needed a real fetch this cycle
|
||||
var fpParts = []; // "id:savedAt" of every raw cell -> fp()
|
||||
var doneCells = 0, totalCells = CAR_QUERIES.length;
|
||||
console.log('[clouds3d] road cells: starting 0/' + totalCells);
|
||||
dbgLog('[clouds3d] road cells: starting 0/' + totalCells);
|
||||
function progCell(cached) {
|
||||
doneCells++;
|
||||
if (doneCells % 10 === 0 || doneCells === totalCells) {
|
||||
console.log('[clouds3d] road cells: ' + doneCells + '/' + totalCells +
|
||||
dbgLog('[clouds3d] road cells: ' + doneCells + '/' + totalCells +
|
||||
(cached ? ' (cached)' : ' (fresh ' + fresh + ')'));
|
||||
}
|
||||
}
|
||||
@@ -2535,14 +2559,14 @@ function fetchMotorways() {
|
||||
// be replayed forever and never grow.
|
||||
if (newest > rec.savedAt) return false;
|
||||
if (missing > Math.max(1, total * 0.1)) {
|
||||
console.log('[clouds3d] car layer: ' + missing + '/' + total +
|
||||
dbgLog('[clouds3d] car layer: ' + missing + '/' + total +
|
||||
' cells missing - rebuilding instead of replaying the cache');
|
||||
return false;
|
||||
}
|
||||
carGeo = { motorway: { cnts: Int32Array.from(rec.mCnts), pts: b64ToF32(rec.mData) },
|
||||
secondary: { cnts: Int32Array.from(rec.bCnts), pts: b64ToF32(rec.bData) } };
|
||||
kickCarBuild(false);
|
||||
console.log('[clouds3d] car layer: ' + carGeo.motorway.cnts.length +
|
||||
dbgLog('[clouds3d] car layer: ' + carGeo.motorway.cnts.length +
|
||||
' motorway + ' + carGeo.secondary.cnts.length + ' chains (from cache' +
|
||||
(missing ? ', ' + missing + ' cells unavailable' : '') + ')');
|
||||
return true;
|
||||
@@ -2558,7 +2582,7 @@ function fetchMotorways() {
|
||||
carPersistFp = geoFp(fpParts);
|
||||
carCycleFp = carPersistFp;
|
||||
kickCarBuild(true);
|
||||
console.log('[clouds3d] car layer: ' + carRaw.motorway.length +
|
||||
dbgLog('[clouds3d] car layer: ' + carRaw.motorway.length +
|
||||
' motorway + ' + carRaw.secondary.length +
|
||||
' secondary polylines queued (' + fresh + ' cells re-fetched)');
|
||||
});
|
||||
@@ -2594,7 +2618,7 @@ function fetchSettlements() {
|
||||
function progCell(cached) {
|
||||
doneCells++;
|
||||
if (doneCells % 5 === 0 || doneCells === totalCells) {
|
||||
console.log('[clouds3d] place cells: ' + doneCells + '/' + totalCells +
|
||||
dbgLog('[clouds3d] place cells: ' + doneCells + '/' + totalCells +
|
||||
(cached ? ' (cached)' : ' (fresh ' + fresh + ')'));
|
||||
}
|
||||
}
|
||||
@@ -2623,7 +2647,7 @@ function fetchSettlements() {
|
||||
}
|
||||
}
|
||||
totalCells = cells.length;
|
||||
console.log('[clouds3d] place cells: starting 0/' + totalCells);
|
||||
dbgLog('[clouds3d] place cells: starting 0/' + totalCells);
|
||||
var list = [];
|
||||
var seenB = {}; // bucket -> index in list: dedupe node/way/rel of one place
|
||||
function parse(data) {
|
||||
@@ -2688,7 +2712,7 @@ function fetchSettlements() {
|
||||
var before = list.length;
|
||||
parse(obj);
|
||||
if (list.length > before)
|
||||
console.log('[clouds3d] place cell ' + entry.id + ': +' +
|
||||
dbgLog('[clouds3d] place cell ' + entry.id + ': +' +
|
||||
(list.length - before) + ' places (total ' + list.length + ')');
|
||||
if (!entry._cached) fresh++;
|
||||
// dot geometry is generated in the geo worker; the debounce
|
||||
@@ -2715,7 +2739,7 @@ function fetchSettlements() {
|
||||
cityGeo = b64ToF32(rec.data);
|
||||
kickCityBuild();
|
||||
if (carGeo) kickCarBuild(false);
|
||||
console.log('[clouds3d] settlements: ' + rec.cnt + ' places (from cache)');
|
||||
dbgLog('[clouds3d] settlements: ' + rec.cnt + ' places (from cache)');
|
||||
return true;
|
||||
});
|
||||
});
|
||||
@@ -2731,7 +2755,7 @@ function fetchSettlements() {
|
||||
tileDbPut(db, { id: 'geo/placecache_v1', fp: geoFp(fpParts),
|
||||
cnt: list.length, data: f32ToB64(packPlaces(list)), savedAt: Date.now() });
|
||||
});
|
||||
console.log('[clouds3d] settlements: ' + list.length + ' places queued for build' +
|
||||
dbgLog('[clouds3d] settlements: ' + list.length + ' places queued for build' +
|
||||
(terrainSample ? '' : ' (terrain pending)'));
|
||||
});
|
||||
});
|
||||
@@ -3511,7 +3535,7 @@ function geoWorkerGet(lane) {
|
||||
w.onmessage = function (e) {
|
||||
var res = e.data || {};
|
||||
if (res.progress) {
|
||||
console.log('[clouds3d] ' + lane + ' worker ' + res.kind + ': ' +
|
||||
dbgLog('[clouds3d] ' + lane + ' worker ' + res.kind + ': ' +
|
||||
res.done + '/' + res.total);
|
||||
return;
|
||||
}
|
||||
@@ -3698,13 +3722,13 @@ function runCarBuild(done) {
|
||||
if (res.joins) carJoinCount = res.joins;
|
||||
if (res.maxChainKm) carMaxChainKm = res.maxChainKm;
|
||||
applyCarBuild(gl, res);
|
||||
console.log('[clouds3d] car build: ' + carCountM + ' + ' + carCountB +
|
||||
dbgLog('[clouds3d] car build: ' + carCountM + ' + ' + carCountB +
|
||||
' ribbon verts, ' + carGeo.motorway.cnts.length + '+' +
|
||||
carGeo.secondary.cnts.length + ' chains, ' +
|
||||
carPtsCountM + ' motorway + ' + carPtsCountB + ' side lights, longest ~' +
|
||||
Math.round(carMaxChainKm) + ' km, ' +
|
||||
Math.round(performance.now() - t0) + ' ms off-thread');
|
||||
console.log('[clouds3d] car slots: motorway ' + (carPtsCountM / 2) +
|
||||
dbgLog('[clouds3d] car slots: motorway ' + (carPtsCountM / 2) +
|
||||
' slots on ' + Math.round(res.mLen * KM_PER_TILE) + ' km (want ' +
|
||||
Math.round(res.mLen / CAR_M_DASH) + ', dash ' +
|
||||
Math.round(CAR_M_DASH * KM_PER_TILE * 1000) + ' m) | side ' + (carPtsCountB / 2) +
|
||||
@@ -3815,20 +3839,20 @@ function runCityBuild(done) {
|
||||
var gl = elevGl || (clouds3dState && clouds3dState.gl);
|
||||
if (!gl || !terrainSample || !cityGeo) {
|
||||
// silent skip made the layer look dead: say what is still missing
|
||||
console.log('[clouds3d] city build skipped - ' +
|
||||
dbgLog('[clouds3d] city build skipped - ' +
|
||||
(!gl ? 'no gl context' : '') +
|
||||
(!gl || terrainSample ? '' : ', no elevation sample yet') +
|
||||
(cityGeo ? '' : ', no place nodes fetched yet'));
|
||||
done(); return;
|
||||
}
|
||||
console.log('[clouds3d] city build: ' + (cityGeo.length / 4) + ' places queued');
|
||||
dbgLog('[clouds3d] city build: ' + (cityGeo.length / 4) + ' places queued');
|
||||
var t0 = performance.now();
|
||||
geoRun({ op: 'city', places: cityGeo, terrain: terrainMsg(), cfg: cityCfg() },
|
||||
function (res) {
|
||||
if (!res || res.error) { done(); return; }
|
||||
cityBuildMs = Math.round(performance.now() - t0);
|
||||
applyCityBuild(gl, res);
|
||||
console.log('[clouds3d] settlements: ' + cityCount + ' lights from ' +
|
||||
dbgLog('[clouds3d] settlements: ' + cityCount + ' lights from ' +
|
||||
(cityGeo.length / 4) + ' places, ' + cityBuildMs + ' ms off-thread');
|
||||
done();
|
||||
});
|
||||
@@ -4021,6 +4045,11 @@ var CT_T = Math.max(10, fltNum(FLT_CFG.contrailLifeS, 300));
|
||||
var CT_HALF_W = Math.max(0.002, fltNum(FLT_CFG.contrailWidthM, 310) / 2000 / KM_PER_TILE);
|
||||
// world units: trails are gone by contrailFadeKm, ramping from 35% of it
|
||||
var CT_FADE_END = Math.max(1, fltNum(FLT_CFG.contrailFadeKm, 100) / KM_PER_TILE);
|
||||
// Night readability. A physically scaled contrail on a starlit night is a
|
||||
// faint grey thread that the pixel grid removes entirely, so the night share
|
||||
// of its opacity and a gain on the moon/star light are configurable.
|
||||
var CT_NIGHT = Math.max(0, Math.min(1, fltNum(FLT_CFG.contrailNight, 0.85)));
|
||||
var CT_NIGHT_BOOST = 1.0 + CT_NIGHT * 2.2;
|
||||
var CT_FADE_START = CT_FADE_END * 0.35;
|
||||
var CT_MAX = FLT_MAX;
|
||||
var CT_SEG = 8; // curve resolution per trail
|
||||
@@ -4218,7 +4247,7 @@ function fetchAirports() {
|
||||
});
|
||||
if (!airports.length) return;
|
||||
buildFlights(airports);
|
||||
console.log('[clouds3d] flights: ' + airports.length + ' airfields -> ' +
|
||||
dbgLog('[clouds3d] flights: ' + airports.length + ' airfields -> ' +
|
||||
fltData.length + ' aircraft (destinations rolled per take-off)');
|
||||
});
|
||||
}
|
||||
@@ -4388,6 +4417,7 @@ var CT_FRAG_SRC = [
|
||||
'uniform float uMoonInt;',
|
||||
'uniform float uSkyAmb;',
|
||||
'uniform float uStarAmb;',
|
||||
'uniform float uNightBoost;', // extra gain on the moon/star terms
|
||||
'uniform vec3 uSunDir;',
|
||||
'uniform vec3 uCamPos;',
|
||||
'varying float vU;',
|
||||
@@ -4426,8 +4456,9 @@ var CT_FRAG_SRC = [
|
||||
// Same multipliers as the cloud deck, so the contrail/cloud
|
||||
// brightness ratio at night is the same as in daylight.
|
||||
'vec3 light = uSunColor * uSunInt * phase * 1.25',
|
||||
' + uMoonColor * uMoonInt * 3.0',
|
||||
' + max(vec3(uSkyAmb), uStarAmb * vec3(0.75, 0.85, 1.0)) * 1.7;',
|
||||
' + (uMoonColor * uMoonInt * 3.0',
|
||||
' + max(vec3(uSkyAmb), uStarAmb * vec3(0.75, 0.85, 1.0)) * 1.7)',
|
||||
' * uNightBoost;',
|
||||
'gl_FragColor = vec4(vec3(0.95, 0.96, 1.0) * light, a);',
|
||||
'}'
|
||||
].join('\n');
|
||||
@@ -4616,7 +4647,7 @@ function buildSkyTexture(stars) {
|
||||
var b = 0.7 + 0.3 * Math.min(1, Math.pow(2.512, -mag * 0.7) * 1.3);
|
||||
data[di++] = b;
|
||||
}
|
||||
console.log('[clouds3d] stars: ' + stars.length + ' points, mean rgb ' +
|
||||
dbgLog('[clouds3d] stars: ' + stars.length + ' points, mean rgb ' +
|
||||
(mr / stars.length).toFixed(3) + '/' + (mg / stars.length).toFixed(3) + '/' +
|
||||
(mb / stars.length).toFixed(3));
|
||||
var prog = makeProgram(gl, SKYPTS_VERT, SKYPTS_FRAG);
|
||||
@@ -5513,6 +5544,7 @@ window.clouds3dRender = function(target) {
|
||||
// CT_HALF_W doubled with the trail width, so the factor
|
||||
// halves: the aircraft silhouette keeps its old size.
|
||||
var S0 = CT_HALF_W * 1.0;
|
||||
var _meshDrawn = 0;
|
||||
for (var dj = 0; dj < fltCount; dj++) {
|
||||
var briJ = fltBuf[dj * 6 + 3];
|
||||
if (briJ <= 0) continue;
|
||||
@@ -5535,6 +5567,7 @@ window.clouds3dRender = function(target) {
|
||||
gl.uniform4f(planeU.orit, Math.cos(yaw), Math.sin(yaw), pitch, 0);
|
||||
gl.uniform1f(planeU.s, scl);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, planeN);
|
||||
_meshDrawn++;
|
||||
}
|
||||
gl.depthMask(true);
|
||||
}
|
||||
@@ -5545,7 +5578,7 @@ window.clouds3dRender = function(target) {
|
||||
// and the stripe follows the curved leg: walked backwards from
|
||||
// the aircraft in fixed steps. Visible by day (sun-lit) AND by
|
||||
// night as dimmed moonlit streaks.
|
||||
var tvis = Math.max(dayf, carNight * 0.42);
|
||||
var tvis = Math.max(dayf, carNight * CT_NIGHT);
|
||||
if (tvis > 0.02) {
|
||||
if (!ctBuf) ctBuf = new Float32Array(CT_MAX * CT_SEG * 6 * 7);
|
||||
ctVerts = 0;
|
||||
@@ -5574,7 +5607,7 @@ window.clouds3dRender = function(target) {
|
||||
if (dfc > 1) dfc = 1; else if (dfc <= 0.02) continue;
|
||||
// sun-lit by day, moonlit after dusk. dayf alone made the
|
||||
// stripes vanish completely at night although the pass ran.
|
||||
var lit = Math.max(dayf, carNight * 0.34);
|
||||
var lit = Math.max(dayf, carNight * CT_NIGHT);
|
||||
var strg = gt * lit * dfc;
|
||||
// widen with distance: a fixed 310 m ribbon is sub-pixel at
|
||||
// 150 km and blends away; grow it to hold ~2-4 screen px
|
||||
@@ -5622,7 +5655,8 @@ window.clouds3dRender = function(target) {
|
||||
moonColor: gl.getUniformLocation(cpm, 'uMoonColor'),
|
||||
moonInt: gl.getUniformLocation(cpm, 'uMoonInt'),
|
||||
skyAmb: gl.getUniformLocation(cpm, 'uSkyAmb'),
|
||||
starAmb: gl.getUniformLocation(cpm, 'uStarAmb') };
|
||||
starAmb: gl.getUniformLocation(cpm, 'uStarAmb'),
|
||||
nightBoost: gl.getUniformLocation(cpm, 'uNightBoost') };
|
||||
}
|
||||
}
|
||||
if (ctProg) {
|
||||
@@ -5637,6 +5671,7 @@ window.clouds3dRender = function(target) {
|
||||
gl.uniform1f(ctU.moonInt, _moonI);
|
||||
gl.uniform1f(ctU.skyAmb, _amb * ATMO_SKY_GAIN);
|
||||
gl.uniform1f(ctU.starAmb, _star);
|
||||
gl.uniform1f(ctU.nightBoost, 1.0 + carNight * (CT_NIGHT_BOOST - 1.0));
|
||||
gl.enableVertexAttribArray(ctA.pos);
|
||||
gl.vertexAttribPointer(ctA.pos, 3, gl.FLOAT, false, 28, 0);
|
||||
gl.enableVertexAttribArray(ctA.u);
|
||||
@@ -5655,6 +5690,21 @@ window.clouds3dRender = function(target) {
|
||||
gl.depthMask(true);
|
||||
}
|
||||
}
|
||||
// Diagnostic snapshot: how many aircraft are in range, how many
|
||||
// meshes were actually drawn and how much contrail geometry made
|
||||
// it past the distance gates.
|
||||
window.__flightDbg = {
|
||||
aircraft: fltCount,
|
||||
meshDrawn: _meshDrawn,
|
||||
ctVerts: ctVerts,
|
||||
day: +dayf.toFixed(2),
|
||||
night: +carNight.toFixed(2),
|
||||
meshRangeKm: Math.round(16 * KM_PER_TILE)
|
||||
};
|
||||
if (DEBUG_LOG && now - _flightDbgT > 5000) {
|
||||
_flightDbgT = now;
|
||||
dbgLog('[clouds3d] flights:', JSON.stringify(window.__flightDbg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user