One commited on
Commit
7dd9db5
·
verified ·
1 Parent(s): d3c2f4c

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +36 -15
index.html CHANGED
@@ -1013,7 +1013,7 @@ function buildScene() {
1013
  const nGrassTufts = Math.max(50, Math.floor(W / 9));
1014
  for (let i = 0; i < nGrassTufts; i++) {
1015
  const gx = rand(8, W - 8);
1016
- const gy = sandAt(gx) + rand(-3, 7);
1017
  const baseHue = rand(95, 155);
1018
  const blades = 2 + ((Math.random() * 4) | 0); // 2..5 blades per tuft
1019
  for (let b = 0; b < blades; b++) {
@@ -1051,7 +1051,7 @@ function buildScene() {
1051
  const nFgClusters = Math.max(8, Math.floor(W / 120));
1052
  for (let i = 0; i < nFgClusters; i++) {
1053
  const cx = rand(-10, W + 10);
1054
- const clusterBaseY = sandAt(cx) + rand(4, H * 0.05); // rooted just in front of the sand bed
1055
  const baseHue = rand(46, 76); // v12.1: yellowish-green — pops against the mid-ground green grass
1056
  const nBlades = 3 + ((Math.random() * 4) | 0); // 3..6 blades per clump
1057
  for (let b = 0; b < nBlades; b++) {
@@ -1064,7 +1064,7 @@ function buildScene() {
1064
  phase: rand(0, Math.PI * 2),
1065
  speed: rand(0.8, 1.6), // slower, heavier sway than the tiny mid-ground grass
1066
  hue: baseHue + rand(-10, 10),
1067
- width: rand(1.75, 3.5), // 50%: half thickness (was 3.5..7)
1068
  // v16: organic rest-curve + segmented blade outline (like seaweed)
1069
  cA1: rand(-8, 8), // primary bend amplitude (larger for foreground)
1070
  cF1: rand(2, 4), // frequency along blade length
@@ -1288,21 +1288,41 @@ function buildRaySprites() {
1288
  const sc = spr.getContext("2d");
1289
  sc.drawImage(full, 0, 0, bw, bh, 0, 0, spr.width, spr.height);
1290
 
1291
- // PERF: pre-tint the sprite with the current light.ray color (no per-frame tinting)
1292
- if (rayTintRGB) {
1293
- const [tr, tg, tb] = rayTintRGB;
1294
- sc.globalCompositeOperation = "source-in";
1295
- sc.fillStyle = `rgb(${tr},${tg},${tb})`;
1296
- sc.fillRect(0, 0, spr.width, spr.height);
1297
- }
1298
-
1299
- r.sprite = spr;
1300
  r.tw = spr.width; r.th = spr.height; // sprite pixel size
1301
  r.bw = bw; // beam width in CSS px (dest size)
1302
  r.xMinL = xMinL; // leftmost local x of the beam body
1303
  }
1304
 
1305
  raySpritesBuiltFor = W + "x" + H;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1306
  }
1307
 
1308
  function drawRays(t, light) {
@@ -1310,11 +1330,12 @@ function drawRays(t, light) {
1310
  const [rr, rg, rb] = light.ray;
1311
  const yTop0 = -10, ySpan = H * 0.95 + 10;
1312
 
1313
- // PERF: only rebuild tinted sprites when the light color shifts significantly (delta > 35)
1314
- // Higher threshold = fewer expensive canvas rebuilds during slow dusk/dawn transitions
 
1315
  if (!rayTintRGB || Math.abs(rayTintRGB[0] - rr) + Math.abs(rayTintRGB[1] - rg) + Math.abs(rayTintRGB[2] - rb) > 35) {
1316
  rayTintRGB = [rr, rg, rb];
1317
- buildRaySprites(); // rebuild with the new tint
1318
  }
1319
 
1320
  for (const r of rays) {
 
1013
  const nGrassTufts = Math.max(50, Math.floor(W / 9));
1014
  for (let i = 0; i < nGrassTufts; i++) {
1015
  const gx = rand(8, W - 8);
1016
+ const gy = sandAt(gx) + rand(2, 9); // moved DOWN so every blade roots at/below the sand line — no floating bits, closes the gap fish wedged into
1017
  const baseHue = rand(95, 155);
1018
  const blades = 2 + ((Math.random() * 4) | 0); // 2..5 blades per tuft
1019
  for (let b = 0; b < blades; b++) {
 
1051
  const nFgClusters = Math.max(8, Math.floor(W / 120));
1052
  for (let i = 0; i < nFgClusters; i++) {
1053
  const cx = rand(-10, W + 10);
1054
+ const clusterBaseY = sandAt(cx) + rand(8, H * 0.06); // moved down (a touch lower than the mid-ground grass) so it sits planted in front
1055
  const baseHue = rand(46, 76); // v12.1: yellowish-green — pops against the mid-ground green grass
1056
  const nBlades = 3 + ((Math.random() * 4) | 0); // 3..6 blades per clump
1057
  for (let b = 0; b < nBlades; b++) {
 
1064
  phase: rand(0, Math.PI * 2),
1065
  speed: rand(0.8, 1.6), // slower, heavier sway than the tiny mid-ground grass
1066
  hue: baseHue + rand(-10, 10),
1067
+ width: rand(2, 4), // kept slightly thicker than the mid-ground grass (1.4..2.8)
1068
  // v16: organic rest-curve + segmented blade outline (like seaweed)
1069
  cA1: rand(-8, 8), // primary bend amplitude (larger for foreground)
1070
  cF1: rand(2, 4), // frequency along blade length
 
1288
  const sc = spr.getContext("2d");
1289
  sc.drawImage(full, 0, 0, bw, bh, 0, 0, spr.width, spr.height);
1290
 
1291
+ // PERF: store the blurred WHITE beam. Tinting is done separately in applyRayTint()
1292
+ // so that a light-color change only needs a cheap source-in fill instead of
1293
+ // re-running this expensive blur rasterization (which caused transition hitching).
1294
+ r.baseSprite = spr;
 
 
 
 
 
1295
  r.tw = spr.width; r.th = spr.height; // sprite pixel size
1296
  r.bw = bw; // beam width in CSS px (dest size)
1297
  r.xMinL = xMinL; // leftmost local x of the beam body
1298
  }
1299
 
1300
  raySpritesBuiltFor = W + "x" + H;
1301
+ applyRayTint(); // ensure every ray has a blittable sprite immediately
1302
+ }
1303
+
1304
+ // Cheaply re-tint the cached blurred sprites with the current light.ray color.
1305
+ // No blur / no shape rasterization — just a source-in fill over the stored beam,
1306
+ // so this stays fast even during slow dusk/dawn transitions.
1307
+ function applyRayTint() {
1308
+ for (const r of rays) {
1309
+ if (!r.baseSprite) continue;
1310
+ if (!r.tintCanvas) {
1311
+ r.tintCanvas = document.createElement("canvas");
1312
+ r.tintCanvas.width = r.tw; r.tintCanvas.height = r.th;
1313
+ }
1314
+ const tc = r.tintCanvas.getContext("2d");
1315
+ tc.clearRect(0, 0, r.tw, r.th);
1316
+ tc.drawImage(r.baseSprite, 0, 0);
1317
+ if (rayTintRGB) {
1318
+ const [tr, tg, tb] = rayTintRGB;
1319
+ tc.globalCompositeOperation = "source-in";
1320
+ tc.fillStyle = `rgb(${tr},${tg},${tb})`;
1321
+ tc.fillRect(0, 0, r.tw, r.th);
1322
+ tc.globalCompositeOperation = "source-over";
1323
+ }
1324
+ r.sprite = r.tintCanvas;
1325
+ }
1326
  }
1327
 
1328
  function drawRays(t, light) {
 
1330
  const [rr, rg, rb] = light.ray;
1331
  const yTop0 = -10, ySpan = H * 0.95 + 10;
1332
 
1333
+ // PERF: re-tint the cached blurred sprites only when the light color shifts enough.
1334
+ // Re-tinting is cheap (a source-in fill) — no blur re-rasterization — so this runs
1335
+ // smoothly even during slow dusk/dawn transitions instead of hitching on rebuilds.
1336
  if (!rayTintRGB || Math.abs(rayTintRGB[0] - rr) + Math.abs(rayTintRGB[1] - rg) + Math.abs(rayTintRGB[2] - rb) > 35) {
1337
  rayTintRGB = [rr, rg, rb];
1338
+ applyRayTint(); // cheap re-tint of the cached blurred sprites (no blur re-run)
1339
  }
1340
 
1341
  for (const r of rays) {