summaryrefslogtreecommitdiff
path: root/cnn_v3/tools/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'cnn_v3/tools/index.html')
-rw-r--r--cnn_v3/tools/index.html147
1 files changed, 147 insertions, 0 deletions
diff --git a/cnn_v3/tools/index.html b/cnn_v3/tools/index.html
new file mode 100644
index 0000000..eba532e
--- /dev/null
+++ b/cnn_v3/tools/index.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html lang="en">
+<!-- CNN v3 WebGPU tool — see shaders.js + tester.js -->
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>CNN v3 Tool</title>
+<style>
+*{box-sizing:border-box;margin:0;padding:0}
+body{background:#1a1a1a;color:#e0e0e0;font-family:'Courier New',monospace;display:flex;flex-direction:column;height:100vh}
+.hdr{padding:8px 14px;border-bottom:1px solid #404040;display:flex;align-items:center;gap:16px;flex-shrink:0}
+h1{font-size:14px}.sub{font-size:10px;color:#555}
+.body{flex:1;display:flex;overflow:hidden;gap:1px;background:#404040}
+.left,.right{background:#2a2a2a;overflow-y:auto;display:flex;flex-direction:column;gap:10px;padding:10px;flex-shrink:0}
+.left{width:284px}.right{width:370px}
+.main{flex:1;display:flex;justify-content:center;align-items:center;padding:14px;overflow:auto;position:relative}
+.panel{border:1px solid #333;border-radius:3px;overflow:hidden}
+.ph{background:#1e1e1e;padding:5px 8px;font-size:10px;font-weight:bold;color:#888;cursor:pointer;display:flex;justify-content:space-between;user-select:none}
+.ph:hover{color:#ddd}
+.panel.collapsed .pc{display:none}
+.pc{padding:9px;font-size:11px}
+.dz{border:2px dashed #444;padding:12px 8px;text-align:center;cursor:pointer;font-size:10px;font-weight:bold;background:#222;border-radius:3px;color:#4a9eff;transition:border-color .15s,background .15s}
+.dz:hover,.dz.dragover{border-color:#4a9eff;background:#1a2535}
+.dz.ok{border-color:#28a745;color:#28a745}.dz.err{border-color:#ff4a4a;color:#ff4a4a}
+button{padding:4px 9px;font-size:10px;cursor:pointer;background:#1a1a1a;color:#e0e0e0;border:1px solid #404040;border-radius:2px}
+button:hover{border-color:#666;background:#252525}
+button.act{background:#4a9eff;border-color:#4a9eff;color:#111}
+button:disabled{opacity:.4;cursor:default}
+button:disabled:hover{border-color:#404040;background:#1a1a1a}
+input[type=range]{width:100%;accent-color:#4a9eff}
+label{font-size:10px;color:#888}
+.row{display:flex;gap:6px;align-items:center}
+.row label{flex-shrink:0;width:82px}
+.row span{font-size:10px;min-width:34px;text-align:right}
+table{width:100%;border-collapse:collapse}
+th{text-align:left;padding:2px 4px;font-size:9px;color:#555;border-bottom:1px solid #333}
+td{padding:2px 4px;font-size:9px}
+tr:hover td{background:#1e1e1e}
+.bf{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);display:flex;gap:10px;align-items:center;background:rgba(28,28,28,.95);padding:6px 12px;border-radius:3px;border:1px solid #404040;z-index:100}
+.sep{width:1px;height:16px;background:#444}
+canvas{max-width:100%;max-height:100%;image-rendering:pixelated;box-shadow:0 4px 12px rgba(0,0,0,.5)}
+.main.dragover::after{content:'Drop PNG/video';position:absolute;inset:14px;display:flex;align-items:center;justify-content:center;border:3px dashed #4a9eff;background:rgba(74,158,255,.08);font-size:20px;color:#4a9eff;pointer-events:none;z-index:10}
+.vzbtns{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px}
+.chgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:3px}
+.chcell{background:#111;border:1px solid #333;overflow:hidden;display:flex;flex-direction:column}
+.chcell-lbl{font-size:8px;padding:2px;background:#1e1e1e;color:#666;text-align:center}
+.chcell canvas{width:100%;display:block;image-rendering:pixelated;cursor:pointer}
+.fgrid{display:grid;grid-template-columns:1fr auto;gap:3px 8px;align-items:center;margin-top:4px}
+.fgrid label{font-size:10px;color:#888}
+.fgrid span{font-size:10px}
+.ftr{background:#222;border-top:1px solid #404040;font-size:11px;display:flex;flex-direction:column;flex-shrink:0}
+.ftr-top{padding:6px 14px 0;display:flex;justify-content:space-between}
+.st{color:#4a9eff}.sh{color:#555;font-size:10px}
+.con{background:#111;padding:4px 14px;font-size:10px;color:#555;max-height:72px;overflow-y:auto;border-top:1px solid #333}
+.cl{margin:1px 0}.cl.err{color:#f44}.cl.info{color:#4a9eff}
+.mtog{display:flex;gap:4px}
+video{display:none}
+</style>
+</head>
+<body>
+<div class="hdr"><h1>CNN v3 Testing Tool</h1><span class="sub">U-Net + FiLM · WebGPU</span></div>
+<video id="vid" muted loop></video>
+<div class="body">
+ <div class="left">
+ <input type="file" id="wFile" accept=".bin" style="display:none">
+ <input type="file" id="fFile" accept=".bin" style="display:none">
+
+ <div class="dz" id="wDrop" onclick="document.getElementById('wFile').click()">Drop cnn_v3_weights.bin</div>
+ <div class="dz" id="fDrop" onclick="document.getElementById('fFile').click()">Drop cnn_v3_film_mlp.bin (optional)</div>
+
+ <div class="panel">
+ <div class="ph" onclick="togglePanel(this)">Input Mode <span>▼</span></div>
+ <div class="pc">
+ <div class="mtog">
+ <button id="mSimple" class="act" onclick="tester.setMode('simple')">Simple (photo)</button>
+ <button id="mFull" onclick="tester.setMode('full')">Full (G-buffer)</button>
+ </div>
+ <div id="fullHelp" style="display:none;margin-top:6px;font-size:9px;color:#555;line-height:1.6">
+ Drop PNGs: *albedo*/color · *normal* · *depth* · *matid*/index · *shadow* · *transp*/alpha
+ </div>
+ </div>
+ </div>
+
+ <div class="panel">
+ <div class="ph" onclick="togglePanel(this)">Weights Info <span>▼</span></div>
+ <div class="pc" id="wInfo"><p style="color:#444;text-align:center">No weights loaded</p></div>
+ </div>
+
+ <div class="panel">
+ <div class="ph" onclick="togglePanel(this)">FiLM Conditioning <span>▼</span></div>
+ <div class="pc">
+ <div style="font-size:9px;color:#444;margin-bottom:5px" id="fSt">No FiLM MLP — identity (γ=1, β=0)</div>
+ <div class="fgrid">
+ <label>beat_phase</label><span id="vBP">0.00</span>
+ <input type="range" id="sBP" min="0" max="1" step=".01" value="0" oninput="tester.fslide('vBP',this)">
+ <label>beat_norm</label><span id="vBN">0.00</span>
+ <input type="range" id="sBN" min="0" max="1" step=".01" value="0" oninput="tester.fslide('vBN',this)">
+ <label>audio_int</label><span id="vAI">0.00</span>
+ <input type="range" id="sAI" min="0" max="1" step=".01" value="0" oninput="tester.fslide('vAI',this)">
+ <label>style_p0</label><span id="vP0">0.00</span>
+ <input type="range" id="sP0" min="-2" max="2" step=".05" value="0" oninput="tester.fslide('vP0',this)">
+ <label>style_p1</label><span id="vP1">0.00</span>
+ <input type="range" id="sP1" min="-2" max="2" step=".05" value="0" oninput="tester.fslide('vP1',this)">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="main" id="mainDrop">
+ <div class="bf">
+ <div style="display:flex;gap:5px" id="vCtrl">
+ <button id="btnPP" disabled onclick="tester.togglePlay()">Play</button>
+ <button id="btnBk" disabled onclick="tester.stepFrame(-1)">◄</button>
+ <button id="btnFw" disabled onclick="tester.stepFrame(1)">►</button>
+ </div>
+ <div class="sep"></div>
+ <label>Blend</label>
+ <input type="range" id="blend" min="0" max="1" step=".01" value="1" style="width:70px" oninput="tester.setBlend(this.value)">
+ <span id="blendV">1.0</span>
+ <div class="sep"></div>
+ <button onclick="tester.savePNG()">Save PNG</button>
+ </div>
+ <canvas id="canvas"></canvas>
+ </div>
+
+ <div class="right">
+ <div class="panel" style="flex:1;display:flex;flex-direction:column;min-height:0">
+ <div class="ph">Layer Visualization</div>
+ <div class="pc" id="layerViz" style="flex:1;overflow:auto">
+ <p style="color:#444;text-align:center">Load image + weights</p>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="ftr">
+ <div class="ftr-top">
+ <span class="st" id="status">Drop PNG/video on canvas · drop .bin weights on left</span>
+ <span class="sh">[SPACE] Original [D] Diff×10</span>
+ </div>
+ <div class="con" id="con"></div>
+</div>
+
+<script src="shaders.js"></script>
+<script src="tester.js"></script>
+</body>
+</html>