@@ -13,11 +13,13 @@ const shaderSources = [
13
13
/**
14
14
* @param {object } param
15
15
* @param {HTMLCanvasElement } param.$world
16
- * @param {HTMLCanvasElement } param.$sheet
16
+ * @param {string } [param.glyphFont]
17
+ * @param {{glyph: string}[] } param.tiles
17
18
*/
18
19
export default async function demo ( {
19
20
$world,
20
- $sheet,
21
+ glyphFont = 'sans' ,
22
+ tiles,
21
23
} ) {
22
24
const gl = ( ( ) => {
23
25
const gl = $world . getContext ( 'webgl2' ) ;
@@ -145,6 +147,9 @@ export default async function demo({
145
147
// If you actually want to work with pre-multiplied alpha textures then you probably want
146
148
gl . blendFunc ( gl . ONE , gl . ONE_MINUS_SRC_ALPHA ) ;
147
149
150
+ // NOTE: must be a power of 2
151
+ const tileSize = 128 ;
152
+
148
153
const sheetTex = gl . createTexture ( ) ;
149
154
const sheetTexUnit = gl . TEXTURE0 ;
150
155
const sheetTexTarget = gl . TEXTURE_2D ;
@@ -154,7 +159,6 @@ export default async function demo({
154
159
// The biggest immediate difference would be less concern around translating
155
160
// texel coordinates (the divide-by-sheetBounds in the fragment shader.)
156
161
157
- let tileSize = 0 ;
158
162
let maxTileID = 0 ;
159
163
160
164
const perspective = mat4 . identity ( new Float32Array ( 16 ) ) ;
@@ -166,7 +170,7 @@ export default async function demo({
166
170
let locData = new Float32Array ( 0 )
167
171
let tileData = new Uint16Array ( 0 ) ;
168
172
169
- sizeToParent ( $sheet , drawSheet ) ;
173
+ drawSheet ( ) ;
170
174
sizeToParent ( $world ) ;
171
175
172
176
/** @returns {Promise<number> } */
@@ -276,35 +280,13 @@ export default async function demo({
276
280
277
281
}
278
282
279
- function updateSheetTex ( ) {
280
- gl . uniform2ui ( uni . sheetBounds ,
281
- Math . floor ( $sheet . width / tileSize ) ,
282
- Math . floor ( $sheet . height / tileSize ) ) ;
283
-
284
- gl . activeTexture ( sheetTexUnit ) ;
285
- gl . bindTexture ( sheetTexTarget , sheetTex ) ;
286
-
287
- gl . texImage2D ( sheetTexTarget , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED_BYTE , $sheet ) ;
288
- gl . generateMipmap ( sheetTexTarget ) ;
289
-
290
- gl . texParameteri ( sheetTexTarget , gl . TEXTURE_MIN_FILTER , gl . LINEAR_MIPMAP_LINEAR ) ;
291
- gl . texParameteri ( sheetTexTarget , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
292
-
293
- gl . texParameteri ( sheetTexTarget , gl . TEXTURE_WRAP_S , gl . CLAMP_TO_EDGE ) ;
294
- gl . texParameteri ( sheetTexTarget , gl . TEXTURE_WRAP_T , gl . CLAMP_TO_EDGE ) ;
295
- }
296
-
297
283
function drawSheet ( ) {
298
- const sheetText = $sheet . dataset [ 'glyphs' ] || '...' ;
299
- const sheetFont = $sheet . dataset [ 'font' ] || 'sans' ;
284
+ const $sheet = new OffscreenCanvas ( tileSize , tileSize * tiles . length ) ;
300
285
301
- const glyphs = Array . from ( sheetText ) ;
286
+ const glyphs = tiles . map ( ( { glyph } ) => glyph ) ;
302
287
303
- // NOTE: we round the sheet size down to a power of 2 because GL mipmap
304
- // generation requires texture to be such size
305
- $sheet . height = Math . pow ( 2 , Math . floor ( Math . log ( $sheet . height ) / Math . log ( 2 ) ) ) ;
306
- tileSize = $sheet . height ;
307
288
$sheet . width = tileSize * glyphs . length ;
289
+ $sheet . height = tileSize ;
308
290
309
291
// TODO this is necessary to stop topline clipping, but why...
310
292
const fontSize = tileSize * 0.9 ;
@@ -318,7 +300,7 @@ export default async function demo({
318
300
for ( let adjust = 0 ; adjust <= fontSize ; adjust ++ ) {
319
301
if ( adjust == fontSize )
320
302
throw new Error ( `unable to find a usable font adjustment for fontSize:${ fontSize } ` ) ;
321
- ctx . font = `${ fontSize - adjust } px ${ sheetFont } ` ;
303
+ ctx . font = `${ fontSize - adjust } px ${ glyphFont } ` ;
322
304
const metrics = glyphs
323
305
. map ( glyph => ctx . measureText ( glyph ) )
324
306
. map ( ( {
@@ -341,7 +323,7 @@ export default async function demo({
341
323
// lay down glyphs in a 1d strip
342
324
ctx . textBaseline = 'bottom' ;
343
325
let x = 0 , y = tileSize ;
344
- for ( const glyph of sheetText ) {
326
+ for ( const glyph of glyphs ) {
345
327
const {
346
328
actualBoundingBoxLeft,
347
329
actualBoundingBoxRight,
@@ -357,7 +339,21 @@ export default async function demo({
357
339
}
358
340
}
359
341
360
- updateSheetTex ( ) ;
342
+ gl . uniform2ui ( uni . sheetBounds ,
343
+ Math . floor ( $sheet . width / tileSize ) ,
344
+ Math . floor ( $sheet . height / tileSize ) ) ;
345
+
346
+ gl . activeTexture ( sheetTexUnit ) ;
347
+ gl . bindTexture ( sheetTexTarget , sheetTex ) ;
348
+
349
+ gl . texImage2D ( sheetTexTarget , 0 , gl . RGBA , gl . RGBA , gl . UNSIGNED_BYTE , $sheet ) ;
350
+ gl . generateMipmap ( sheetTexTarget ) ;
351
+
352
+ gl . texParameteri ( sheetTexTarget , gl . TEXTURE_MIN_FILTER , gl . LINEAR_MIPMAP_LINEAR ) ;
353
+ gl . texParameteri ( sheetTexTarget , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
354
+
355
+ gl . texParameteri ( sheetTexTarget , gl . TEXTURE_WRAP_S , gl . CLAMP_TO_EDGE ) ;
356
+ gl . texParameteri ( sheetTexTarget , gl . TEXTURE_WRAP_T , gl . CLAMP_TO_EDGE ) ;
361
357
}
362
358
363
359
}
0 commit comments