Skip to content

Commit

Permalink
textures are getting compressed and displayed, still needs a lot of work
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekucera committed Jan 28, 2025
1 parent 200e549 commit c51439f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 56 deletions.
37 changes: 13 additions & 24 deletions src/extensions/renderer/canvas/webgl/atlas.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,29 +214,25 @@ export class Atlas {
bufferIfNeeded(gl) {
if(this.needsBuffer) {
this.needsBuffer = false;
console.log(this.atlasManager);
if(this.atlasManager && this.atlasManager.canCompress()) {
// TODO handle error from this promise
return this.atlasManager
.compressAtlas(this)
.then(eventData => {
// How to get the correct width/height?????
const { data, width, height, webglFormat } = eventData;
console.log("what is this data? ", data);
.then(result => {
const { compressedData, width, height, format } = result;
const texture = this._getTexture(gl);
texture.bufferCompressed(data, width, height, webglFormat);
texture.bufferCompressed(compressedData, width, height, format);
})
.catch((err) => console.log("BAD", err));
.catch((err) => console.log('error from compression', err));
} else {
const texture = this._getTexture();
const texture = this._getTexture(gl);
texture.bufferCanvas(this.canvas);
return Promise.resolve();
}
}
return Promise.resolve();
}


/**
* TODO, this is a wierd API
*/
Expand All @@ -247,8 +243,6 @@ export class Atlas {
this.texture.bufferCompressed(data);
}



dispose() {
if(this.texture) {
this.texture.deleteTexture();
Expand Down Expand Up @@ -384,7 +378,7 @@ export class AtlasCollection {
const markedKeys = this._getKeysToCollect();

if(markedKeys.size === 0 && !forceGC) {
console.log("nothing to garbage collect");
console.log('nothing to garbage collect');
return;
}

Expand Down Expand Up @@ -767,8 +761,7 @@ export class AtlasManager {

compressAtlas(atlas) {
if(this.basisAvailable) {
const { basisManager } = this;
return basisManager.compress(atlas.canvas);
return this.basisManager.compress(atlas.canvas);
} else {
return Promise.reject('basis not available');
}
Expand Down Expand Up @@ -803,7 +796,7 @@ class BasisWorkerManager {

this.worker.postMessage({
type: MessageTo.INIT,
jsUrl: this.opts.webglBasisJsURL,
jsUrl: this.opts.webglBasisJsURL,
wasmUrl: this.opts.webglBasisWasmURL,
flags
});
Expand All @@ -814,14 +807,13 @@ class BasisWorkerManager {

return new Promise((resolve, reject) => {
const off = this.on(MessageFrom.ENCODE_COMPLETE, (event) => {
console.log("got message back from basis worker: ", event.data);
const data = event.data;
const { data } = event;
if(data.tag === tag) {
off();
if(data.success) {
resolve(data);
resolve(data.result);
} else {
reject(data);
reject(data.err);
}
}
});
Expand All @@ -847,15 +839,13 @@ class BasisWorkerManager {
else
typeToHandlers.set(type, [handler]);

const off = () => {
return function off() {
const array = typeToHandlers.get(type);
const index = array.indexOf(handler);
if(index > -1) {
array.splice(index, 1); //
array.splice(index, 1);
}
};

return off;
}

once(type, handler) {
Expand All @@ -865,5 +855,4 @@ class BasisWorkerManager {
});
}


}
37 changes: 21 additions & 16 deletions src/extensions/renderer/canvas/webgl/basis-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,14 @@ function encode(pngBuffer, tag) {
encodePngToKTX2(basisModule, pngBuffer)
.then(ktx2 => encodeKTX2ToGPU(basisModule, ktx2))
.then(result => {
console.log('success encoding');
self.postMessage({
type: MessageFrom.ENCODE_COMPLETE,
success: true,
tag,
data: result.data,
webglFormat: result.format.webgl
result,
});
})
.catch(err => {
console.log('error encoding', err);
self.postMessage({
type: MessageFrom.ENCODE_COMPLETE,
success: false,
Expand Down Expand Up @@ -120,7 +117,9 @@ function encodePngToKTX2(basisModule, pngBuffer) {
basisEncoder.setFormatMode(formatMode);
basisEncoder.setRDOUASTC(false);
basisEncoder.setMipGen(true);
basisEncoder.setPackUASTCFlags(1); // range [0, 3], lower is much faster

// texture quality, range [0, 3], lower quality is faster to compress
basisEncoder.setPackUASTCFlags(2);

const startTime = performance.now(); // eslint-disable-line no-undef

Expand All @@ -136,10 +135,7 @@ function encodePngToKTX2(basisModule, pngBuffer) {
basisEncoder.delete();

if (numOutputBytes == 0) {
console.log('encodeBasisTexture() failed!');
return Promise.reject(new Error('encoding png to ktx2 failed'));
} else {
console.log('encodeBasisTexture() succeeded, output size ' + numOutputBytes);
}

return Promise.resolve(actualKTX2FileData);
Expand All @@ -152,6 +148,9 @@ function encodeKTX2ToGPU(basisModule, ktx2FileData) {
const { KTX2File, flags } = basisModule;

const ktx2File = new KTX2File(new Uint8Array(ktx2FileData));
const width = ktx2File.getWidth();
const height = ktx2File.getHeight();

try {
if(!ktx2File.isValid()) {
return Promise.reject(new Error('Invalid or unsupported .ktx2 file'));
Expand All @@ -166,14 +165,21 @@ function encodeKTX2ToGPU(basisModule, ktx2FileData) {
}

const destSize = ktx2File.getImageTranscodedSizeInBytes(0, 0, 0, format.basis);
const data = new Uint8Array(destSize);
const compressedData = new Uint8Array(destSize);

const res = ktx2File.transcodeImageWithFlags(data, 0, 0, 0, format.basis, 0, -1, -1);
const decodeFlags = basisModule.basisu_decode_flags.cDecodeFlagsHighQuality.value;
const res = ktx2File.transcodeImageWithFlags(compressedData, 0, 0, 0, format.basis, decodeFlags, -1, -1);
if(!res) {
return Promise.reject(new Error('transcodeImage failed'));
}

return Promise.resolve({ data, format });
return Promise.resolve({
compressedData,
format: format.webgl,
width,
height
});

} finally {
ktx2File.close();
ktx2File.delete();
Expand All @@ -192,7 +198,6 @@ const webglFormat = {
COMPRESSED_RGB_ETC1_WEBGL: 0x8D64
};


/**
* Note: we assume the texture has alpha
* @see webgl-util.js getGPUTextureCompressionSupport
Expand All @@ -201,25 +206,25 @@ function getCompressionFormat(basisModule, flags) {
const basisFormat = basisModule.transcoder_texture_format;
if(flags.astc) {
return {
basis: basisFormat.cTFASTC_4x4_RGBA,
basis: basisFormat.cTFASTC_4x4_RGBA.value,
webgl: webglFormat.COMPRESSED_RGBA_ASTC_4x4_KHR
};
} else if(flags.bc7) {
return {
basis: basisFormat.cTFBC7_RGBA,
basis: basisFormat.cTFBC7_RGBA.value,
webgl: webglFormat.COMPRESSED_RGBA_BPTC_UNORM
};
} else if(flags.dxt) {
return {
basis: basisFormat.cTFBC3_RGBA,
basis: basisFormat.cTFBC3_RGBA.value,
webgl: webglFormat.COMPRESSED_RGBA_S3TC_DXT5_EXT
};
// } else if((pvrtcSupported) && (!pvrtcDisabled) && (is_square_pow2)) {// TODO ?
// return format.cTFPVRTC1_4_RGBA;
// }
} else if(flags.etc) {
return {
basis: basisFormat.cTFETC1_RGB,
basis: basisFormat.cTFETC1_RGB.value,
webgl: webglFormat.COMPRESSED_RGB_ETC1_WEBGL
};
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,13 +684,14 @@ export class ElementDrawingWebGL {
}

const atlases = this.atlasManager.getAtlases();
const promises = new Array(atlases.length);
// const promises = new Array(atlases.length);

// must buffer before activating texture units
for(let i = 0; i < atlases.length; i++) {
promises[i] = atlases[i].bufferIfNeeded(gl);
atlases[i].bufferIfNeeded(gl);
// promises[i] = atlases[i].bufferIfNeeded(gl);
// TODO temporary
promises[i].then(() => this.r.redraw());
// promises[i].then(() => this.r.redraw());
}

// Activate all the texture units that we need
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ function renderWebgl(r, options, renderTarget) {
eleDrawing.endFrame();

if(r.data.gc) {
console.log("Garbage Collect!");
console.log('Garbage Collect!');
r.data.gc = false;
eleDrawing.gc();
}
Expand Down
21 changes: 9 additions & 12 deletions src/extensions/renderer/canvas/webgl/webgl-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,6 @@
*/


export function getGPUTextureCompressionSupport(gl) {
const dxt = Boolean(gl.getExtension('WEBGL_compressed_texture_s3tc'));
const etc = Boolean(gl.getExtension('WEBGL_compressed_texture_etc' ));
const astc = Boolean(gl.getExtension('WEBGL_compressed_texture_astc'));
const bc7 = Boolean(gl.getExtension('EXT_texture_compression_bptc' ));
return { dxt, etc, astc, bc7 };
}

export function isPowerOf2(n) {
return (n != 0) && (n & (n - 1) == 0);
}

export function compileShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
Expand Down Expand Up @@ -57,6 +45,15 @@ export function createTextureCanvas(r, width, height) {
return canvas;
}


export function getGPUTextureCompressionSupport(gl) {
const dxt = Boolean(gl.getExtension('WEBGL_compressed_texture_s3tc'));
const etc = Boolean(gl.getExtension('WEBGL_compressed_texture_etc' ));
const astc = Boolean(gl.getExtension('WEBGL_compressed_texture_astc'));
const bc7 = Boolean(gl.getExtension('EXT_texture_compression_bptc' ));
return { dxt, etc, astc, bc7 };
}

/**
* Returns the current pan & zoom values, scaled by the pixel ratio.
*/
Expand Down

0 comments on commit c51439f

Please sign in to comment.