Last active
July 23, 2025 23:10
-
-
Save greggman/8e4fee18b6acae61ebfff249692ab842 to your computer and use it in GitHub Desktop.
Mipmap Diagram
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
svg { width: 100%; display: block; } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*bug-in-github-api-content-can-not-be-empty*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const range = (num, fn) => new Array(num).fill(0).map((_, i) => fn(i)); | |
const roundUp = (v, a) => Math.ceil(v / a) * a; | |
const hsl = (h, s, l) => `hsl(${h * 360 | 0}, ${s * 100}%, ${l * 100 | 0}%)`; | |
function hLine({x1, x2, y, stroke}) { | |
return [ | |
['line', {x1, x2, y1: y, y2: y, stroke}], | |
['line', {x1, x2: x1 + 1, y1: y, y2: y + 0.5, stroke}], | |
['line', {x1, x2: x1 + 1, y1: y, y2: y - 0.5, stroke}], | |
['line', {x1: x2, x2: x2 - 1, y1: y, y2: y + 0.5, stroke}], | |
['line', {x1: x2, x2: x2 - 1, y1: y, y2: y - 0.5, stroke}], | |
]; | |
} | |
function makeMap(size) { | |
const numRows = Math.ceil(Math.log2(size)); | |
const rowSize = 10; | |
const width = 100; | |
const height = (numRows) * rowSize; | |
const kBlockSize = 16; | |
const rows = range(numRows, rowNdx => { | |
const numTexels = Math.max(1, size >> rowNdx); | |
const blockSize = kBlockSize >> rowNdx; | |
const numInRow = roundUp(numTexels, blockSize); | |
const texelSize = width / numTexels; | |
const prevNumTexels = Math.max(1, size >> (rowNdx - 1)); | |
const prevTexelSize = width / prevNumTexels; | |
const rowHue = rowNdx / numRows; | |
return ['g', {transform: `translate(0 ${rowNdx * rowSize})` }, ...range(numInRow, tx => { | |
const x1 = (tx + 0.5) * texelSize; | |
const u = (tx + 0.5) / numTexels; | |
const tu = u * prevNumTexels - 0.5; | |
const sx = (Math.floor(tu) + 0.5) * prevTexelSize; | |
const ex = (Math.ceil(tu) + 0.5) * prevTexelSize; | |
const texelHue = tx < numTexels ? hsl(rowHue + (tx / blockSize | 0) * 0.78, 1, 0.8) : 'rgb(0 0 0 / 0)'; | |
return [ | |
['rect', { x: tx * texelSize, y: 0, width: texelSize, height: rowSize * 0.66, stroke: '#000', fill: texelHue }], | |
...(rowNdx > 0 && tx < numTexels ? [ | |
['line', { x1, x2: x1, y1: rowSize * 0.25, y2: rowSize * -0.5, stroke: '#000' }], | |
...hLine({ x1: sx, x2: ex, y: rowSize * -0.5, stroke: '#000' }), | |
] : []) | |
]; | |
}).flat()]; | |
}); | |
document.body.append( | |
makeElem(['svg', { viewBox: `0 0 ${width * 2} ${height}` }, | |
['g', { 'stroke-width': '0.1' }, ...rows], | |
]) | |
); | |
} | |
for (let w = 23; w > 2; --w) { | |
log(`${w}x1`); | |
makeMap(w); | |
//break; | |
} | |
function log(...args) { | |
const elem = document.createElement('pre'); | |
elem.textContent = args.join(' '); | |
document.body.appendChild(elem); | |
} | |
/** | |
* Implements JsonML *like* element creation (http://www.jsonml.org/) | |
* | |
* The major difference is this takes event handlers for `on` functions | |
* and supports nested attributes? Also allows elements. | |
*/ | |
function makeElem(elemSpec, creatorFn) { | |
const tag = elemSpec[0]; | |
if (tag instanceof Node) { | |
return tag; | |
} | |
if (tag === 'svg') { | |
const kSVG = "http://www.w3.org/2000/svg"; | |
creatorFn = tag => document.createElementNS(kSVG, tag); | |
} | |
const elem = creatorFn ? creatorFn(tag) : document.createElement(tag); | |
let firstChildNdx = 1; | |
if (typeof elemSpec[1] !== Node && typeof elemSpec[1] !== 'string' && !Array.isArray(elemSpec[1])) { | |
firstChildNdx = 2; | |
for (const [key, value] of Object.entries(elemSpec[1])) { | |
if (typeof value === 'function' && key.startsWith('on')) { | |
const eventName = key.substring(2).toLowerCase(); | |
elem.addEventListener(eventName, value, {passive: false}); | |
} else if (typeof value === 'object') { | |
for (const [k, v] of Object.entries(value)) { | |
elem[key][k] = v; | |
} | |
} else { | |
elem.setAttribute(key, value); | |
} | |
} | |
} | |
for (let ndx = firstChildNdx; ndx < elemSpec.length; ++ndx) { | |
const v = elemSpec[ndx]; | |
if (typeof v === 'string') { | |
elem.appendChild(document.createTextNode(v)); | |
} else if (v instanceof Node) { | |
elem.appendChild(v); | |
} else { | |
elem.appendChild(makeElem(v, creatorFn)); | |
} | |
} | |
return elem; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"name":"Mipmap Diagram","settings":{},"filenames":["index.html","index.css","index.js"]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment