Take the cone down and turn it blue

Lower alpha through the whole fill (0.34 -> 0.19 at the strings, falling with
depth) and the core is a LIT BLUE rather than near-white, which is what was
washing it out. The stroked edges come down and turn blue with it.

Worth recording, because it will come up again: the cone's opacity and how well
you can tell above-the-plane from below-the-plane are the same dial. The plane is
flat -- a body above it is drawn clean on top, a body below is seen through it --
so the distinction just IS the cone's alpha. Fainter cone and sharper split pull
against each other; the fainter cone wins and the cut line carries the signal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-03 16:04:04 +02:00
1 parent 8f16d085f0
commit b44fcd8465
3 files changed
+14 -6

No files matched your search

+5
View File
@@ -443,6 +443,11 @@ that holds that height all the way out instead of sloping to the ground — that
makes the rest possible. Sloping, it lay flat on the grass across the whole far half, so there was makes the rest possible. Sloping, it lay flat on the grass across the whole far half, so there was
nothing for it to cut exactly where the crowd stands. nothing for it to cut exactly where the crowd stands.
- **The cone's opacity and the over/under read are the SAME dial, and they pull against each other.**
The plane is flat: a body above it is drawn clean on top, a body below is seen THROUGH it — so how
clearly you can tell the two apart just is how opaque the cone is. Oliver asked for a fainter,
bluer cone AND a clearer split; the first wins, and the CUT LINE carries the signal instead. Do not
try to "fix" the split by raising the cone alpha again — that is the thing he asked to come down.
- **The fill is TWO gradients**, matching the reference Oliver sent: a horizontal one across the - **The fill is TWO gradients**, matching the reference Oliver sent: a horizontal one across the
width (near-white down the centre line, falling to the weapon's blue at the edges) and a depth one width (near-white down the centre line, falling to the weapon's blue at the edges) and a depth one
along the length. Canvas has no 2D gradient, so the wedge is filled in eight slices along its along the length. Canvas has no 2D gradient, so the wedge is filled in eight slices along its
+1 -1
View File
@@ -179,6 +179,6 @@
</div> </div>
</div> </div>
</div> </div>
<script type="module" src="main.js?v=105"></script> <script type="module" src="main.js?v=106"></script>
</body> </body>
</html> </html>
+8 -5
View File
@@ -631,13 +631,16 @@ function drawBeamWedge(dirX, dirZ, ox, oy, oz, alpha, from) {
const wa = wAt(ua), wb = wAt(ub), wm = wAt(um); const wa = wAt(ua), wb = wAt(ub), wm = wAt(um);
const a1 = corner(ua, -wa), a2 = corner(ua, wa), b2 = corner(ub, wb), b1 = corner(ub, -wb); const a1 = corner(ua, -wa), a2 = corner(ua, wa), b2 = corner(ub, wb), b1 = corner(ub, -wb);
const el = corner(um, -wm), er = corner(um, wm); // the across axis, at this slice's width const el = corner(um, -wm), er = corner(um, wm); // the across axis, at this slice's width
const k = (0.34 - 0.24 * um) * alpha; // depth: strongest at the strings // Lower opacity and BLUER. It was near-white down the core at almost double this alpha, which
// veiled the whole cone evenly — and once everything under it is equally washed out, the split
// stops reading: you cannot tell the part above the plane from the part below.
const k = (0.19 - 0.13 * um) * alpha; // depth: strongest at the strings
const g = ctx.createLinearGradient(el.x, el.y, er.x, er.y); const g = ctx.createLinearGradient(el.x, el.y, er.x, er.y);
g.addColorStop(0, `rgba(${r},${g_},${b},${k * 0.55})`); // edge: the weapon's blue g.addColorStop(0, `rgba(${r},${g_},${b},${k * 0.5})`); // edge: the weapon's blue
g.addColorStop(0.34, `rgba(${r},${g_},${b},${k})`); g.addColorStop(0.34, `rgba(${r},${g_},${b},${k})`);
g.addColorStop(0.5, `rgba(215,238,255,${k * 1.5})`); // core: near-white, the hot line g.addColorStop(0.5, `rgba(118,188,255,${k * 1.35})`); // core: a LIT blue, not white
g.addColorStop(0.66, `rgba(${r},${g_},${b},${k})`); g.addColorStop(0.66, `rgba(${r},${g_},${b},${k})`);
g.addColorStop(1, `rgba(${r},${g_},${b},${k * 0.55})`); g.addColorStop(1, `rgba(${r},${g_},${b},${k * 0.5})`);
ctx.fillStyle = g; ctx.fillStyle = g;
ctx.beginPath(); ctx.moveTo(a1.x, a1.y); ctx.lineTo(a2.x, a2.y); ctx.lineTo(b2.x, b2.y); ctx.lineTo(b1.x, b1.y); ctx.beginPath(); ctx.moveTo(a1.x, a1.y); ctx.lineTo(a2.x, a2.y); ctx.lineTo(b2.x, b2.y); ctx.lineTo(b1.x, b1.y);
ctx.closePath(); ctx.fill(); ctx.closePath(); ctx.fill();
@@ -645,7 +648,7 @@ function drawBeamWedge(dirX, dirZ, ox, oy, oz, alpha, from) {
// ...and the OUTER LINES. The reference reads as a plane because its edges are drawn, not just // ...and the OUTER LINES. The reference reads as a plane because its edges are drawn, not just
// implied by where the fill stops. // implied by where the fill stops.
const c1 = corner(u0, -w0), c2 = corner(u0, w0), c3 = corner(1, w1), c4 = corner(1, -w1); const c1 = corner(u0, -w0), c2 = corner(u0, w0), c3 = corner(1, w1), c4 = corner(1, -w1);
ctx.strokeStyle = `rgba(190,225,255,${0.5 * alpha})`; ctx.strokeStyle = `rgba(120,190,255,${0.45 * alpha})`;
ctx.lineWidth = 1; ctx.lineWidth = 1;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(c2.x, c2.y); ctx.lineTo(c3.x, c3.y); ctx.moveTo(c2.x, c2.y); ctx.lineTo(c3.x, c3.y);