mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-26 14:52:13 +00:00
feat(highway_3d): act on tester charrette — strike line, fog readability, AA
Addresses the alpha-tester 3D-highway feedback thread via the design panel's recommendations: - Strike line (panel rec 1a): now a HIT-ONLY faint "now" line — flashes green on a confirmed hit, no red miss branch (misses already show at the gem: red wash + ✗). Moved off the bottom edge to the vertical CENTRE of the string field, which was the "incorrectly placed" complaint (it read as the board's lower border and fused with open-string gems on a miss). Added a "Strike line" on/off toggle (`strikeLine`, default on). - Horizon readability (#2): the note gems + their outlines are now fog-exempt (`material.fog = false` on mStr/mGlow/mStrHitOutline/mHitBright/mWhiteOutline/ mMissOutline), so upcoming notes punch through the distance fog and stay legible as they render in — the board, lane, sustains and scenery keep their atmospheric fog, so depth is preserved. - Cinematic lighting softened: cinematic ambient 0.35 -> 0.45 so the dark stage doesn't crush note/fret legibility. - Anti-aliasing under bloom (perf rec): give the bloom EffectComposer a multisampled (WebGL2 MSAA x4) HalfFloat render target. The default target had no `samples`, so bloom-on bypassed MSAA — the "too HD / jagged on Windows, fine on Mac" report (Mac only won via Retina supersampling). This is the highest-value, smallest fix for the jaggies. plugin.json -> 3.29.0. The renderScale quality-oscillation is core (static/highway.js) and will be a separate feedBack PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b04d7fa00d
commit
5111ef9440
@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "highway_3d",
|
||||
"name": "3D Highway",
|
||||
"version": "3.28.0",
|
||||
"version": "3.29.0",
|
||||
"type": "visualization",
|
||||
"bundled": true,
|
||||
"script": "screen.js",
|
||||
|
||||
@ -1768,7 +1768,7 @@
|
||||
return _bgBandsCache;
|
||||
}
|
||||
|
||||
const BG_DEFAULTS = { style: 'particles', intensity: 0.5, reactive: true, palette: 'default', bgTheme: 'default', hwTheme: 'default', showFretOnNote: true, fretNumberGhostScope: 'chords', cameraSmoothing: 0.5, zoomSmoothing: 0.5, tiltSmoothing: 0.5, cameraLockLow: false, cameraLockZoom: 0.5, cameraMode: 'lookahead', nutHeadstockVisible: true, tuningLabelsVisible: true, nutColor: '#f5f3f0', headstockColor: '#d4b48a', textSize: 0.5, vibrancy: 0.85, glow: 0.25, customImageDataUrl: '', customImageName: '', customVideoName: '', chordDiagramVisible: true, chordDiagramSize: 0.5, chordDiagramPosition: 'tl', fretColumnMarkerCadence: 1, projectionVisible: true, inlayLabelsVisible: false, sectionLabelsOnHighway: false, sectionHudVisible: false, sectionHudPosition: 'tr', sectionHudSize: 0.5, toneHudVisible: false, toneHudPosition: 'tl', toneHudSize: 0.5, fpsVisible: false, fretDividersVisible: true, slideArrowApproachVisible: true, slideArrowNeckVisible: true, slideArrowChainPreviewVisible: true, hitFx: 0.7, sparks: true, cinematic: true, verdictMarks: true, timingFx: true, streakFx: true, bloom: true };
|
||||
const BG_DEFAULTS = { style: 'particles', intensity: 0.5, reactive: true, palette: 'default', bgTheme: 'default', hwTheme: 'default', showFretOnNote: true, fretNumberGhostScope: 'chords', cameraSmoothing: 0.5, zoomSmoothing: 0.5, tiltSmoothing: 0.5, cameraLockLow: false, cameraLockZoom: 0.5, cameraMode: 'lookahead', nutHeadstockVisible: true, tuningLabelsVisible: true, nutColor: '#f5f3f0', headstockColor: '#d4b48a', textSize: 0.5, vibrancy: 0.85, glow: 0.25, customImageDataUrl: '', customImageName: '', customVideoName: '', chordDiagramVisible: true, chordDiagramSize: 0.5, chordDiagramPosition: 'tl', fretColumnMarkerCadence: 1, projectionVisible: true, inlayLabelsVisible: false, sectionLabelsOnHighway: false, sectionHudVisible: false, sectionHudPosition: 'tr', sectionHudSize: 0.5, toneHudVisible: false, toneHudPosition: 'tl', toneHudSize: 0.5, fpsVisible: false, fretDividersVisible: true, slideArrowApproachVisible: true, slideArrowNeckVisible: true, slideArrowChainPreviewVisible: true, hitFx: 0.7, sparks: true, strikeLine: true, cinematic: true, verdictMarks: true, timingFx: true, streakFx: true, bloom: true };
|
||||
// User-selectable, persistable bg styles — must mirror settings.html's
|
||||
// VALID_STYLES. 'venue' is deliberately NOT here: it is an internal effective
|
||||
// style reached only via _venueSceneOverride (the viz-picker Venue flow), so
|
||||
@ -2115,7 +2115,7 @@
|
||||
// means (fall back to default rather than silently flipping to
|
||||
// false). Add new boolean keys to BG_DEFAULTS and they pick this
|
||||
// up via the dispatch below.
|
||||
const _BG_BOOL_KEYS = new Set(['reactive', 'showFretOnNote', 'cameraLockLow', 'inlayLabelsVisible', 'sectionLabelsOnHighway', 'sectionHudVisible', 'nutHeadstockVisible', 'tuningLabelsVisible', 'projectionVisible', 'chordDiagramVisible', 'fpsVisible', 'toneHudVisible', 'fretDividersVisible', 'slideArrowApproachVisible', 'slideArrowNeckVisible', 'slideArrowChainPreviewVisible', 'sparks', 'cinematic', 'verdictMarks', 'timingFx', 'streakFx', 'bloom']);
|
||||
const _BG_BOOL_KEYS = new Set(['reactive', 'showFretOnNote', 'cameraLockLow', 'inlayLabelsVisible', 'sectionLabelsOnHighway', 'sectionHudVisible', 'nutHeadstockVisible', 'tuningLabelsVisible', 'projectionVisible', 'chordDiagramVisible', 'fpsVisible', 'toneHudVisible', 'fretDividersVisible', 'slideArrowApproachVisible', 'slideArrowNeckVisible', 'slideArrowChainPreviewVisible', 'sparks', 'strikeLine', 'cinematic', 'verdictMarks', 'timingFx', 'streakFx', 'bloom']);
|
||||
function _bgCoerceBool(val, fallback) {
|
||||
if (val === 'true' || val === '1') return true;
|
||||
if (val === 'false' || val === '0') return false;
|
||||
@ -2261,6 +2261,7 @@
|
||||
window.h3dBgSetGlow = (v) => _bgWriteGlobal('glow', v);
|
||||
window.h3dBgSetHitFx = (v) => _bgWriteGlobal('hitFx', v);
|
||||
window.h3dBgSetSparks = (v) => _bgWriteGlobal('sparks', !!v);
|
||||
window.h3dBgSetStrikeLine = (v) => _bgWriteGlobal('strikeLine', !!v);
|
||||
window.h3dBgSetCinematic = (v) => _bgWriteGlobal('cinematic', !!v);
|
||||
window.h3dBgSetVerdictMarks = (v) => _bgWriteGlobal('verdictMarks', !!v);
|
||||
window.h3dBgSetTimingFx = (v) => _bgWriteGlobal('timingFx', !!v);
|
||||
@ -3561,6 +3562,7 @@
|
||||
let glowMul = BG_DEFAULTS.glow;
|
||||
let _hitFx = BG_DEFAULTS.hitFx;
|
||||
let _sparks = BG_DEFAULTS.sparks;
|
||||
let _strikeFx = BG_DEFAULTS.strikeLine;
|
||||
let _cinematic = BG_DEFAULTS.cinematic;
|
||||
let _verdictMarks = BG_DEFAULTS.verdictMarks;
|
||||
let _timingFx = BG_DEFAULTS.timingFx;
|
||||
@ -6170,6 +6172,13 @@
|
||||
transparent: true, opacity: 1.0, depthWrite: false,
|
||||
}));
|
||||
mHitBrightArrays = mHitBright.map(m => [m, m, m, m, mEdgeTransparent, mEdgeTransparent]);
|
||||
// Readability (#2 / charrette): the note gems + their outlines punch THROUGH
|
||||
// the distance fog so upcoming notes stay legible as they render in at the
|
||||
// horizon. The board, lane, sustains and background scenery keep their
|
||||
// atmospheric fog — only the note-defining materials are exempted, so the
|
||||
// highway still reads as deep while the notes never dissolve into the haze.
|
||||
[mWhiteOutline, mMissOutline].forEach(m => { if (m) m.fog = false; });
|
||||
[mStr, mGlow, mStrHitOutline, mHitBright].forEach(arr => arr && arr.forEach(m => { if (m) m.fog = false; }));
|
||||
// Outline materials render at a lower renderOrder than the body.
|
||||
// The body is rendered on top with opacity:1 on hit/miss, which
|
||||
// fully covers the outline center — only the fringe that extends
|
||||
@ -7385,6 +7394,7 @@
|
||||
glowMul = _bgReadSetting(panelKey, 'glow');
|
||||
_hitFx = _bgReadSetting(panelKey, 'hitFx');
|
||||
_sparks = _bgReadSetting(panelKey, 'sparks');
|
||||
_strikeFx = _bgReadSetting(panelKey, 'strikeLine');
|
||||
_cinematic = _bgReadSetting(panelKey, 'cinematic');
|
||||
_verdictMarks = _bgReadSetting(panelKey, 'verdictMarks');
|
||||
_timingFx = _bgReadSetting(panelKey, 'timingFx');
|
||||
@ -7834,7 +7844,7 @@
|
||||
// Toggle via the 'cinematic' setting so it's directly comparable.
|
||||
function _applyCinematic() {
|
||||
if (!ambLight || !dirLight) return;
|
||||
ambLight.intensity = _cinematic ? 0.35 : 0.85;
|
||||
ambLight.intensity = _cinematic ? 0.45 : 0.85;
|
||||
dirLight.intensity = _cinematic ? 1.15 : 0.8;
|
||||
}
|
||||
// #5 early/late: tint the hit feedback by timing — on-time green, early cyan,
|
||||
@ -7892,7 +7902,12 @@
|
||||
try {
|
||||
const sz = canvasSize(highwayCanvas) || { w: 1280, h: 720 };
|
||||
const w = Math.max(2, sz.w | 0), h = Math.max(2, sz.h | 0);
|
||||
const comp = new EC.EffectComposer(ren);
|
||||
// Multisampled (WebGL2 MSAA) HalfFloat target so anti-aliasing
|
||||
// survives the bloom path — EffectComposer's default target has no
|
||||
// `samples`, which is why bloom-on looked jagged (worst on non-Retina
|
||||
// DPR1 displays that have no supersampling cushion).
|
||||
const _bloomRT = new T.WebGLRenderTarget(w, h, { type: T.HalfFloatType, samples: 4 });
|
||||
const comp = new EC.EffectComposer(ren, _bloomRT);
|
||||
comp.addPass(new RP.RenderPass(scene, cam));
|
||||
_bloomPass = new UB.UnrealBloomPass(new T.Vector2(w, h), 0.65, 0.5, 0.82); // strength, radius, threshold (high → only emissive blooms)
|
||||
comp.addPass(_bloomPass);
|
||||
@ -7949,13 +7964,17 @@
|
||||
p.position.set(board.center, S_BASE - NH / 2 - 2 * K, -blAhead / 2);
|
||||
fretG.add(p);
|
||||
|
||||
// Strike line (#1): a thin glowing bar at the hit line (Z=0). Idle dim;
|
||||
// flashes green on a hit / red on a miss (driven each frame in the render loop).
|
||||
// Strike line (#1): a thin glowing "now" bar at the hit line (Z=0). Idle
|
||||
// faint; flashes green on a HIT only (driven each frame in the render loop).
|
||||
// Misses are shown at the gem (red wash + ✗), NOT here — a single missed
|
||||
// string never reds-out the whole bar (charrette panel rec 1a).
|
||||
// Placed at the vertical CENTRE of the string field (not the bottom edge,
|
||||
// which read as the fretboard's lower border and fused with open-string gems).
|
||||
{
|
||||
const slGeo = new T.BoxGeometry(bw, NH * 0.42, 0.7 * K);
|
||||
const slMat = new T.MeshBasicMaterial({ color: 0x2a3a52, transparent: true, opacity: 0.0, depthWrite: false, blending: T.AdditiveBlending });
|
||||
_strikeLine = new T.Mesh(slGeo, slMat);
|
||||
_strikeLine.position.set(board.center, S_BASE - NH / 2, 0);
|
||||
_strikeLine.position.set(board.center, (sY(0) + sY(nStr - 1)) / 2, 0);
|
||||
_strikeLine.renderOrder = 6;
|
||||
fretG.add(_strikeLine);
|
||||
}
|
||||
@ -14494,12 +14513,17 @@
|
||||
_sparkUpdate(_jdt);
|
||||
_streakHeat += (Math.min(1, _streakHits / 16) - _streakHeat) * 0.08; // #7 ease heat
|
||||
if (_strikeLine) {
|
||||
const hf = _ndHitFlash * _hitFx, mf = _ndMissFlash * _hitFx;
|
||||
const lit = Math.max(hf, mf);
|
||||
const m = _strikeLine.material;
|
||||
m.opacity = 0.10 + (_streakFx ? 0.12 * _streakHeat : 0) + 0.85 * Math.min(1, lit);
|
||||
if (lit > 0.002) m.color.setHex(hf >= mf ? 0x22ff88 : 0xff0066);
|
||||
else m.color.setHex(0x2a3a52);
|
||||
if (_strikeFx) {
|
||||
_strikeLine.visible = true;
|
||||
// Hit-only celebration: faint idle, flashes green on a confirmed
|
||||
// hit. No red/miss branch — misses live at the gem (charrette 1a).
|
||||
const hf = _ndHitFlash * _hitFx;
|
||||
const m = _strikeLine.material;
|
||||
m.opacity = 0.06 + (_streakFx ? 0.10 * _streakHeat : 0) + 0.85 * Math.min(1, hf);
|
||||
m.color.setHex(hf > 0.002 ? 0x22ff88 : 0x2a3a52);
|
||||
} else {
|
||||
_strikeLine.visible = false;
|
||||
}
|
||||
_ndHitFlash *= 0.82; _ndMissFlash *= 0.82;
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,6 +602,16 @@
|
||||
class="accent-accent mt-0.5">
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex items-start justify-between gap-3">
|
||||
<label for="h3d-strikeline" class="text-xs font-medium text-gray-400">
|
||||
Strike line
|
||||
<span class="block text-[10px] text-gray-500 font-normal">A faint line across the hit point that flashes green when you nail a note. Hit-only — misses show on the note itself.</span>
|
||||
</label>
|
||||
<input type="checkbox" id="h3d-strikeline" checked
|
||||
onchange="window.h3dBgSetStrikeLine && window.h3dBgSetStrikeLine(this.checked)"
|
||||
class="accent-accent mt-0.5">
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex items-start justify-between gap-3">
|
||||
<label for="h3d-cinematic" class="text-xs font-medium text-gray-400">
|
||||
Cinematic lighting
|
||||
|
||||
Loading…
Reference in New Issue
Block a user