cars: distribute lights by density and scale point size with render resolution
This commit is contained in:
1 parent
50c96ceae4
commit
1f621d749a
1 file changed
+16
-15
Vendored
+16
-15
@@ -3345,7 +3345,7 @@ var CAR_M_DASH = carMetres(CAR_TUN.dashM || 620);
|
|||||||
// density sits below the motorway peak and the gaussian falloff shapes it
|
// density sits below the motorway peak and the gaussian falloff shapes it
|
||||||
// further by distance to the nearest motorway.
|
// further by distance to the nearest motorway.
|
||||||
var CAR_M_SPEED = 0.055 * CAR_SPEED, CAR_M_DENS = 0.85 * CAR_DENS;
|
var CAR_M_SPEED = 0.055 * CAR_SPEED, CAR_M_DENS = 0.85 * CAR_DENS;
|
||||||
var CAR_B_DASH = CAR_M_DASH * 1.15, CAR_B_SPEED = 0.017 * CAR_SPEED, CAR_B_DENS = 1.0 * CAR_DENS;
|
var CAR_B_DASH = CAR_M_DASH * 2.8, CAR_B_SPEED = 0.017 * CAR_SPEED, CAR_B_DENS = 0.75 * CAR_DENS;
|
||||||
var carGeo = null; // { motorway: packedChains, secondary: packedChains }
|
var carGeo = null; // { motorway: packedChains, secondary: packedChains }
|
||||||
var carVboM = null, carCountM = 0;
|
var carVboM = null, carCountM = 0;
|
||||||
var carVboB = null, carCountB = 0;
|
var carVboB = null, carCountB = 0;
|
||||||
@@ -4284,16 +4284,15 @@ function buildCarGeometry(chainsM, chainsB, ts, cfg, places) {
|
|||||||
// spreadKm is the sigma of the motorway distribution.
|
// spreadKm is the sigma of the motorway distribution.
|
||||||
function densScale(x, z) {
|
function densScale(x, z) {
|
||||||
var st = settleAt(x, z);
|
var st = settleAt(x, z);
|
||||||
if (!distField) return Math.min(1, 0.72 + 0.45 * st);
|
if (!distField) return Math.min(1, 0.16 + 0.84 * st);
|
||||||
var i = Math.max(0, Math.min(ts.gw - 1, Math.round((x + ts.halfX) / ts.s)));
|
var i = Math.max(0, Math.min(ts.gw - 1, Math.round((x + ts.halfX) / ts.s)));
|
||||||
var j = Math.max(0, Math.min(ts.gh - 1, Math.round((ts.halfY - z) / ts.s)));
|
var j = Math.max(0, Math.min(ts.gh - 1, Math.round((ts.halfY - z) / ts.s)));
|
||||||
var d = distField[j * ts.gw + i] * ts.s; // world units to a motorway
|
var d = distField[j * ts.gw + i] * ts.s; // world units to a motorway
|
||||||
var t = d / cfg.CAR_SIGMA;
|
var t = d / cfg.CAR_SIGMA;
|
||||||
var mw = cfg.CAR_FLOOR + (1 - cfg.CAR_FLOOR) * Math.exp(-t * t);
|
var mw = cfg.CAR_FLOOR + (1 - cfg.CAR_FLOOR) * Math.exp(-t * t);
|
||||||
// Flat enough that a side road 60 km from the A-net still carries
|
// Side roads are sparse unless they are near the A-net or a town.
|
||||||
// clearly visible traffic; the motorway gaussian only adds a modest
|
// Motorways/settlements get the bulk; remote secondary roads stay faint.
|
||||||
// boost on top instead of dominating the whole field.
|
return Math.min(1, 0.12 + 0.58 * mw + 0.62 * st);
|
||||||
return Math.min(1, 0.72 + 0.28 * mw + 0.45 * st);
|
|
||||||
}
|
}
|
||||||
function build(polys, withField, dash) {
|
function build(polys, withField, dash) {
|
||||||
var li, i, segs = 0, totalLen = 0;
|
var li, i, segs = 0, totalLen = 0;
|
||||||
@@ -4315,7 +4314,7 @@ function buildCarGeometry(chainsM, chainsB, ts, cfg, places) {
|
|||||||
// shorter than the spacing still gets a vehicle), so the capacity
|
// shorter than the spacing still gets a vehicle), so the capacity
|
||||||
// must count both - otherwise a network of many short side roads
|
// must count both - otherwise a network of many short side roads
|
||||||
// overflows the buffer and the tail of it is silently dropped.
|
// overflows the buffer and the tail of it is silently dropped.
|
||||||
var pArr = new Float32Array((Math.ceil(totalLen / dash) + polys.length + 2) * 20);
|
var pArr = new Float32Array((Math.ceil(totalLen / (dash * 0.55)) + polys.length + 2) * 20);
|
||||||
var pi = 0, pn = 0;
|
var pi = 0, pn = 0;
|
||||||
for (li = 0; li < polys.length; li++) {
|
for (li = 0; li < polys.length; li++) {
|
||||||
var pts = polys[li];
|
var pts = polys[li];
|
||||||
@@ -4337,7 +4336,7 @@ function buildCarGeometry(chainsM, chainsB, ts, cfg, places) {
|
|||||||
var ya = terrainH(ts, a.x, a.z) * cfg.ELEV_SCALE_UNITS + CAR_Y;
|
var ya = terrainH(ts, a.x, a.z) * cfg.ELEV_SCALE_UNITS + CAR_Y;
|
||||||
var yb = terrainH(ts, b.x, b.z) * cfg.ELEV_SCALE_UNITS + CAR_Y;
|
var yb = terrainH(ts, b.x, b.z) * cfg.ELEV_SCALE_UNITS + CAR_Y;
|
||||||
var dens = withField ? densScale((a.x + b.x) / 2, (a.z + b.z) / 2)
|
var dens = withField ? densScale((a.x + b.x) / 2, (a.z + b.z) / 2)
|
||||||
: Math.min(1, 0.55 + 0.65 * settleAt((a.x + b.x) / 2, (a.z + b.z) / 2));
|
: Math.min(1, 0.88 + 0.25 * settleAt((a.x + b.x) / 2, (a.z + b.z) / 2));
|
||||||
verts[vi++] = a.x + nx; verts[vi++] = ya; verts[vi++] = a.z + nz;
|
verts[vi++] = a.x + nx; verts[vi++] = ya; verts[vi++] = a.z + nz;
|
||||||
verts[vi++] = a.d; verts[vi++] = 1; verts[vi++] = tx; verts[vi++] = tz; verts[vi++] = dens;
|
verts[vi++] = a.d; verts[vi++] = 1; verts[vi++] = tx; verts[vi++] = tz; verts[vi++] = dens;
|
||||||
verts[vi++] = a.x - nx; verts[vi++] = ya; verts[vi++] = a.z - nz;
|
verts[vi++] = a.x - nx; verts[vi++] = ya; verts[vi++] = a.z - nz;
|
||||||
@@ -4355,7 +4354,8 @@ function buildCarGeometry(chainsM, chainsB, ts, cfg, places) {
|
|||||||
var f = next - acc;
|
var f = next - acc;
|
||||||
if (f < 0) f = 0;
|
if (f < 0) f = 0;
|
||||||
var qx = a.x + dx * f, qz = a.z + dz * f;
|
var qx = a.x + dx * f, qz = a.z + dz * f;
|
||||||
if (inView(qx, qz) && pi + 20 <= pArr.length) {
|
var slotWeight = withField ? Math.max(0.12, Math.min(1.25, (dens - 0.10) / 0.72)) : 1.18;
|
||||||
|
if (inView(qx, qz) && pi + 20 <= pArr.length && slotWeight > 0.14) {
|
||||||
// one shared slide phase per chain: every vehicle of
|
// one shared slide phase per chain: every vehicle of
|
||||||
// a chain moves in lockstep, so a wrap lands exactly
|
// a chain moves in lockstep, so a wrap lands exactly
|
||||||
// on the slot the neighbour just left - continuous
|
// on the slot the neighbour just left - continuous
|
||||||
@@ -4375,7 +4375,7 @@ function buildCarGeometry(chainsM, chainsB, ts, cfg, places) {
|
|||||||
pArr[pi++] = clen;
|
pArr[pi++] = clen;
|
||||||
pn++;
|
pn++;
|
||||||
}
|
}
|
||||||
next += dash;
|
next += dash / slotWeight;
|
||||||
}
|
}
|
||||||
acc += L;
|
acc += L;
|
||||||
}
|
}
|
||||||
@@ -6457,6 +6457,7 @@ window.clouds3dRender = function(target) {
|
|||||||
// aircraft): the mean over the per-light thresholds.
|
// aircraft): the mean over the per-light thresholds.
|
||||||
var carNight = lightFactor(window.__currentSunAlt || 0);
|
var carNight = lightFactor(window.__currentSunAlt || 0);
|
||||||
if (carProg && (carVboM || carVboB) && carNight > 0.01) {
|
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));
|
var tCurve = Math.max(0, Math.min(1, (carNight - 0.10) / 0.40));
|
||||||
tCurve = tCurve * tCurve * (3 - 2 * tCurve); // smoothstep
|
tCurve = tCurve * tCurve * (3 - 2 * tCurve); // smoothstep
|
||||||
// rush-hour shaping: busy evening/early morning, quiet 23:00-04:00
|
// rush-hour shaping: busy evening/early morning, quiet 23:00-04:00
|
||||||
@@ -6494,7 +6495,7 @@ window.clouds3dRender = function(target) {
|
|||||||
gl.uniform1f(carUniforms.night, carNight);
|
gl.uniform1f(carUniforms.night, carNight);
|
||||||
// dot radius the light needs per unit distance to still reach
|
// dot radius the light needs per unit distance to still reach
|
||||||
// CAR_MIN_PX diameter (0.5774 = tan(fovY/2) of the 60 deg vertical fov)
|
// CAR_MIN_PX diameter (0.5774 = tan(fovY/2) of the 60 deg vertical fov)
|
||||||
gl.uniform1f(carUniforms.grow, CAR_BAND_PX * 0.5774 / gl.drawingBufferHeight);
|
gl.uniform1f(carUniforms.grow, CAR_BAND_PX * carPxScale * 0.5774 / gl.drawingBufferHeight);
|
||||||
gl.uniform1f(carUniforms.halfW, CAR_W);
|
gl.uniform1f(carUniforms.halfW, CAR_W);
|
||||||
gl.uniform1f(carUniforms.bright, CAR_BAND_BRIGHT);
|
gl.uniform1f(carUniforms.bright, CAR_BAND_BRIGHT);
|
||||||
gl.uniform1f(carUniforms.fadeA, CAR_FADE_A);
|
gl.uniform1f(carUniforms.fadeA, CAR_FADE_A);
|
||||||
@@ -6574,14 +6575,14 @@ window.clouds3dRender = function(target) {
|
|||||||
// world units covered by one pixel at unit distance:
|
// world units covered by one pixel at unit distance:
|
||||||
// 2*tan(fovY/2)/H = 1.1547/H for the 60 deg vertical fov
|
// 2*tan(fovY/2)/H = 1.1547/H for the 60 deg vertical fov
|
||||||
gl.uniform1f(carPtsUniforms.laneW, CAR_LANE_W);
|
gl.uniform1f(carPtsUniforms.laneW, CAR_LANE_W);
|
||||||
gl.uniform1f(carPtsUniforms.lanePx, CAR_LANE_PX);
|
gl.uniform1f(carPtsUniforms.lanePx, CAR_LANE_PX * carPxScale);
|
||||||
// world units covered by one pixel at unit distance:
|
// world units covered by one pixel at unit distance:
|
||||||
// 2*tan(fovY/2)/H = 1.1547/H for the 60 deg vertical fov
|
// 2*tan(fovY/2)/H = 1.1547/H for the 60 deg vertical fov
|
||||||
gl.uniform1f(carPtsUniforms.pxW, 1.1547 / gl.drawingBufferHeight);
|
gl.uniform1f(carPtsUniforms.pxW, 1.1547 / gl.drawingBufferHeight);
|
||||||
gl.uniform1f(carPtsUniforms.traffic, CAR_TRAFFIC);
|
gl.uniform1f(carPtsUniforms.traffic, CAR_TRAFFIC);
|
||||||
gl.uniform1f(carPtsUniforms.minPx, CAR_MIN_PX);
|
gl.uniform1f(carPtsUniforms.minPx, CAR_MIN_PX * carPxScale);
|
||||||
gl.uniform1f(carPtsUniforms.maxPx, CAR_MAX_PX);
|
gl.uniform1f(carPtsUniforms.maxPx, CAR_MAX_PX * carPxScale);
|
||||||
gl.uniform1f(carPtsUniforms.boost, CAR_BOOST);
|
gl.uniform1f(carPtsUniforms.boost, CAR_BOOST * carPxScale);
|
||||||
gl.uniform1f(carPtsUniforms.bright, CAR_BRIGHT);
|
gl.uniform1f(carPtsUniforms.bright, CAR_BRIGHT);
|
||||||
gl.uniform1f(carPtsUniforms.fadeA, CAR_FADE_A);
|
gl.uniform1f(carPtsUniforms.fadeA, CAR_FADE_A);
|
||||||
gl.uniform1f(carPtsUniforms.fadeB, CAR_FADE_B);
|
gl.uniform1f(carPtsUniforms.fadeB, CAR_FADE_B);
|
||||||
|
|||||||
Reference in new issue
Block a user