| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> |
| <title>Shader Deblocking</title> |
| <style> |
| html, body { |
| margin: 0; |
| padding: 0; |
| height: 100%; |
| background: #202020; |
| color: #e0e0e0; |
| font-family: Consolas, "Courier New", monospace; |
| overflow: hidden; |
| overscroll-behavior: none; /* stop Android pull-to-refresh / iOS rubber-banding */ |
| } |
| #canvas { |
| display: block; |
| width: 100vw; |
| height: 100vh; /* fallback for older browsers */ |
| height: 100dvh; /* dynamic viewport height: correct under the mobile URL bar */ |
| touch-action: none; /* we handle drag/pinch ourselves; stop browser pan/zoom */ |
| } |
| /* Text overlays sit on top of the GL canvas. The native sample drew an |
| 8x8 bitmap font into the framebuffer; in the browser plain HTML/CSS is |
| simpler and crisper. */ |
| .overlay { |
| position: fixed; |
| left: calc(8px + env(safe-area-inset-left)); |
| pointer-events: none; |
| white-space: pre; |
| font-size: 13px; |
| line-height: 1.35; |
| text-shadow: 0 0 3px #000, 0 0 3px #000; |
| } |
| /* #info top-left; #help stacked just below it (kept away from the bottom |
| button bar, which can wrap to multiple rows on a narrow phone). */ |
| #info { top: calc(8px + env(safe-area-inset-top)); } |
| #help { top: calc(70px + env(safe-area-inset-top)); color: #b0b0b0; font-size: 12px; } |
| /* On-screen control bar — keeps the sample fully usable on touch devices. */ |
| #buttons { |
| position: fixed; |
| left: 50%; |
| bottom: calc(10px + env(safe-area-inset-bottom)); |
| transform: translateX(-50%); |
| display: flex; |
| flex-wrap: nowrap; /* single horizontal row along the bottom */ |
| gap: 6px; |
| justify-content: center; |
| max-width: calc(100vw - 12px); |
| overflow-x: auto; /* scroll rather than stack if a screen is too narrow */ |
| pointer-events: auto; |
| } |
| #buttons button { |
| background: #303030; |
| color: #e0e0e0; |
| border: 1px solid #555; |
| font-family: inherit; |
| font-size: 13px; |
| padding: 10px 8px; |
| min-height: 44px; /* iOS HIG minimum tap target */ |
| white-space: nowrap; /* keep each label on one line */ |
| flex: 0 0 auto; |
| border-radius: 5px; |
| cursor: pointer; |
| touch-action: manipulation; /* kill the 300ms double-tap delay/zoom */ |
| } |
| /* Guard :hover so it doesn't "stick" after a tap on touch devices. */ |
| @media (hover: hover) { #buttons button:hover { background: #3a3a3a; } } |
| #buttons button:active { background: #454545; } /* immediate touch feedback */ |
| #buttons button.active { background: #2a5d2a; border-color: #3a8a3a; } |
| /* Pulldown sits BELOW the debug text (#info 3 lines + #help), left-aligned, so |
| it never overlaps/obscures the overlay text on a narrow phone screen. */ |
| #controls { |
| position: fixed; |
| top: calc(112px + env(safe-area-inset-top)); |
| left: calc(8px + env(safe-area-inset-left)); |
| pointer-events: auto; |
| font-size: 13px; |
| } |
| #controls select { |
| background: #303030; |
| color: #e0e0e0; |
| border: 1px solid #555; |
| font-family: inherit; |
| font-size: 16px; /* >=16px stops iOS auto-zoom on focus */ |
| padding: 8px 10px; |
| min-height: 44px; |
| touch-action: manipulation; |
| } |
| #error { |
| position: fixed; |
| left: 50%; |
| top: 50%; |
| transform: translate(-50%, -50%); |
| color: #ff8080; |
| font-size: 15px; |
| max-width: 80vw; |
| text-align: center; |
| display: none; |
| } |
| </style> |
| </head> |
| <body> |
| <canvas id="canvas"></canvas> |
| |
| <div id="info" class="overlay">Loading…</div> |
| <div id="help" class="overlay"></div> |
| |
| <div id="buttons"> |
| <button id="btnMode">Quad</button> |
| <button id="btnDeblock">Deblock</button> |
| <button id="btnEdges">Edges</button> |
| <button id="btnFilter">Trilinear</button> |
| <button id="btnReset">Reset</button> |
| </div> |
| |
| <div id="controls"> |
| <label for="asset">Texture: </label> |
| <select id="asset"> |
| <option value="assets/kodim01.ktx2">kodim01.ktx2</option> |
| <option value="assets/kodim03.ktx2">kodim03.ktx2</option> |
| <option value="assets/kodim23.ktx2" selected>kodim23.ktx2</option> |
| <option value="assets/tng.ktx2">tng.ktx2 (8x8, mipped)</option> |
| <option value="assets/tng2.ktx2">tng2.ktx2 (8x8, mipped, 1000h)</option> |
| <option value="assets/tng3.ktx2">tng3.ktx2 (12x12, mipped)</option> |
| <option value="assets/frymire.ktx2">frymire.ktx2</option> |
| <option value="assets/frymire2.ktx2">frymire2.ktx2</option> |
| </select> |
| </div> |
| |
| <div id="error"></div> |
| |
| <!-- Shared Basis Universal transcoder (transcode-only WASM build), same one |
| used by the other webgl/ samples. main.js boots it via BASIS(). --> |
| <script src="../transcoder/build/basis_transcoder.js"></script> |
| <script src="main.js"></script> |
| </body> |
| </html> |