Upload index.html
Browse files- index.html +20 -26
index.html
CHANGED
|
@@ -1166,17 +1166,16 @@ function drawBackground(light) {
|
|
| 1166 |
// horizontal slices with the same undulation offsets as before β wobble + soft
|
| 1167 |
// edges, zero filters at runtime.
|
| 1168 |
const RAY_SEGS = 18; // vertical resolution of each beam's spine (at build time)
|
| 1169 |
-
const RAY_SLICES =
|
| 1170 |
const RAY_SPRITE_SCALE = 0.5; // sprites stored at half resolution β softer + cheaper
|
| 1171 |
const RAY_PAD = 60; // room for the blur to spill past the beam edge
|
| 1172 |
let raySpritesBuiltFor = null;
|
| 1173 |
-
let
|
| 1174 |
|
| 1175 |
function buildRaySprites() {
|
| 1176 |
const S = RAY_SPRITE_SCALE;
|
| 1177 |
const yTop0 = -10, ySpan = H * 0.95 + 10; // beam vertical extent (same as before)
|
| 1178 |
|
| 1179 |
-
let maxTw = 0, maxTh = 0;
|
| 1180 |
for (const r of rays) {
|
| 1181 |
const shift = r.tilt * H;
|
| 1182 |
const topW = r.w * 0.45, botW = r.w * 1.9;
|
|
@@ -1248,42 +1247,37 @@ function buildRaySprites() {
|
|
| 1248 |
const sc = spr.getContext("2d");
|
| 1249 |
sc.drawImage(full, 0, 0, bw, bh, 0, 0, spr.width, spr.height);
|
| 1250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1251 |
r.sprite = spr;
|
| 1252 |
r.tw = spr.width; r.th = spr.height; // sprite pixel size
|
| 1253 |
r.bw = bw; // beam width in CSS px (dest size)
|
| 1254 |
r.xMinL = xMinL; // leftmost local x of the beam body
|
| 1255 |
-
if (spr.width > maxTw) maxTw = spr.width;
|
| 1256 |
-
if (spr.height > maxTh) maxTh = spr.height;
|
| 1257 |
}
|
| 1258 |
|
| 1259 |
-
// shared tint canvas: per frame we recolor each white sprite here with the current
|
| 1260 |
-
// light.ray color, so beams still shift hue through day β dusk β night like before
|
| 1261 |
-
tintCanvas = document.createElement("canvas");
|
| 1262 |
-
tintCanvas.width = Math.max(1, maxTw);
|
| 1263 |
-
tintCanvas.height = Math.max(1, maxTh);
|
| 1264 |
-
tctx = tintCanvas.getContext("2d");
|
| 1265 |
-
|
| 1266 |
raySpritesBuiltFor = W + "x" + H;
|
| 1267 |
}
|
| 1268 |
|
| 1269 |
function drawRays(t, light) {
|
| 1270 |
-
if (!
|
| 1271 |
const [rr, rg, rb] = light.ray;
|
| 1272 |
-
const tintRGB = `rgb(${rr},${rg},${rb})`;
|
| 1273 |
const yTop0 = -10, ySpan = H * 0.95 + 10;
|
| 1274 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1275 |
for (const r of rays) {
|
| 1276 |
-
//
|
| 1277 |
-
//
|
| 1278 |
-
tctx.clearRect(0, 0, r.tw, r.th);
|
| 1279 |
-
tctx.globalCompositeOperation = "source-over";
|
| 1280 |
-
tctx.drawImage(r.sprite, 0, 0);
|
| 1281 |
-
tctx.globalCompositeOperation = "source-in";
|
| 1282 |
-
tctx.fillStyle = tintRGB;
|
| 1283 |
-
tctx.fillRect(0, 0, r.tw, r.th);
|
| 1284 |
-
|
| 1285 |
-
// 2) blit horizontal slices with the undulation offset at each depth β same wave
|
| 1286 |
-
// math as before, so the beams shimmer exactly like they always have
|
| 1287 |
const off = Math.sin(t * r.speed * 6 + r.x) * 55; // slow drift of the whole beam
|
| 1288 |
for (let i = 0; i < RAY_SLICES; i++) {
|
| 1289 |
const vT = i / RAY_SLICES, vB = (i + 1) / RAY_SLICES, vM = (vT + vB) / 2;
|
|
@@ -1293,7 +1287,7 @@ function drawRays(t, light) {
|
|
| 1293 |
Math.sin(vM * r.uLen + t * r.uSpd + r.uPh) * r.uAmp +
|
| 1294 |
Math.sin(vM * r.vLen - t * r.vSpd + r.vPh) * r.vAmp;
|
| 1295 |
const dx = r.x + off + wave * grow; // undulating center x at this depth
|
| 1296 |
-
ctx.drawImage(
|
| 1297 |
0, (ya + 10 + RAY_PAD) * RAY_SPRITE_SCALE, r.tw, (yb - ya) * RAY_SPRITE_SCALE,
|
| 1298 |
dx + r.xMinL - RAY_PAD, ya, r.bw, yb - ya);
|
| 1299 |
}
|
|
|
|
| 1166 |
// horizontal slices with the same undulation offsets as before β wobble + soft
|
| 1167 |
// edges, zero filters at runtime.
|
| 1168 |
const RAY_SEGS = 18; // vertical resolution of each beam's spine (at build time)
|
| 1169 |
+
const RAY_SLICES = 10; // horizontal slices per beam used for the wobble (per frame) β reduced from 24
|
| 1170 |
const RAY_SPRITE_SCALE = 0.5; // sprites stored at half resolution β softer + cheaper
|
| 1171 |
const RAY_PAD = 60; // room for the blur to spill past the beam edge
|
| 1172 |
let raySpritesBuiltFor = null;
|
| 1173 |
+
let rayTintRGB = null; // the light.ray color used when building tinted sprites (perf: rebuild only on big shifts)
|
| 1174 |
|
| 1175 |
function buildRaySprites() {
|
| 1176 |
const S = RAY_SPRITE_SCALE;
|
| 1177 |
const yTop0 = -10, ySpan = H * 0.95 + 10; // beam vertical extent (same as before)
|
| 1178 |
|
|
|
|
| 1179 |
for (const r of rays) {
|
| 1180 |
const shift = r.tilt * H;
|
| 1181 |
const topW = r.w * 0.45, botW = r.w * 1.9;
|
|
|
|
| 1247 |
const sc = spr.getContext("2d");
|
| 1248 |
sc.drawImage(full, 0, 0, bw, bh, 0, 0, spr.width, spr.height);
|
| 1249 |
|
| 1250 |
+
// PERF: pre-tint the sprite with the current light.ray color (no per-frame tinting)
|
| 1251 |
+
if (rayTintRGB) {
|
| 1252 |
+
const [tr, tg, tb] = rayTintRGB;
|
| 1253 |
+
sc.globalCompositeOperation = "source-in";
|
| 1254 |
+
sc.fillStyle = `rgb(${tr},${tg},${tb})`;
|
| 1255 |
+
sc.fillRect(0, 0, spr.width, spr.height);
|
| 1256 |
+
}
|
| 1257 |
+
|
| 1258 |
r.sprite = spr;
|
| 1259 |
r.tw = spr.width; r.th = spr.height; // sprite pixel size
|
| 1260 |
r.bw = bw; // beam width in CSS px (dest size)
|
| 1261 |
r.xMinL = xMinL; // leftmost local x of the beam body
|
|
|
|
|
|
|
| 1262 |
}
|
| 1263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1264 |
raySpritesBuiltFor = W + "x" + H;
|
| 1265 |
}
|
| 1266 |
|
| 1267 |
function drawRays(t, light) {
|
| 1268 |
+
if (!raySpritesBuiltFor || raySpritesBuiltFor !== W + "x" + H) buildRaySprites();
|
| 1269 |
const [rr, rg, rb] = light.ray;
|
|
|
|
| 1270 |
const yTop0 = -10, ySpan = H * 0.95 + 10;
|
| 1271 |
|
| 1272 |
+
// PERF: only rebuild tinted sprites when the light color shifts significantly (delta > 14)
|
| 1273 |
+
if (!rayTintRGB || Math.abs(rayTintRGB[0] - rr) + Math.abs(rayTintRGB[1] - rg) + Math.abs(rayTintRGB[2] - rb) > 14) {
|
| 1274 |
+
rayTintRGB = [rr, rg, rb];
|
| 1275 |
+
buildRaySprites(); // rebuild with the new tint
|
| 1276 |
+
}
|
| 1277 |
+
|
| 1278 |
for (const r of rays) {
|
| 1279 |
+
// blit horizontal slices with the undulation offset at each depth β same wave
|
| 1280 |
+
// math as before, so the beams shimmer exactly like they always have
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1281 |
const off = Math.sin(t * r.speed * 6 + r.x) * 55; // slow drift of the whole beam
|
| 1282 |
for (let i = 0; i < RAY_SLICES; i++) {
|
| 1283 |
const vT = i / RAY_SLICES, vB = (i + 1) / RAY_SLICES, vM = (vT + vB) / 2;
|
|
|
|
| 1287 |
Math.sin(vM * r.uLen + t * r.uSpd + r.uPh) * r.uAmp +
|
| 1288 |
Math.sin(vM * r.vLen - t * r.vSpd + r.vPh) * r.vAmp;
|
| 1289 |
const dx = r.x + off + wave * grow; // undulating center x at this depth
|
| 1290 |
+
ctx.drawImage(r.sprite,
|
| 1291 |
0, (ya + 10 + RAY_PAD) * RAY_SPRITE_SCALE, r.tw, (yb - ya) * RAY_SPRITE_SCALE,
|
| 1292 |
dx + r.xMinL - RAY_PAD, ya, r.bw, yb - ya);
|
| 1293 |
}
|