diff --git a/examples/src/examples/loaders/gltf-export.example.mjs b/examples/src/examples/loaders/gltf-export.example.mjs index ead30bc215b..88e9d8dcf46 100644 --- a/examples/src/examples/loaders/gltf-export.example.mjs +++ b/examples/src/examples/loaders/gltf-export.example.mjs @@ -31,6 +31,13 @@ await new Promise((resolve) => { pc.WasmModule.getInstance('DracoDecoderModule', () => resolve()); }); +// initialize basis to allow to load compressed textures +pc.basisInitialize({ + glueUrl: rootPath + '/static/lib/basis/basis.wasm.js', + wasmUrl: rootPath + '/static/lib/basis/basis.wasm.wasm', + fallbackUrl: rootPath + '/static/lib/basis/basis.js' +}); + const assets = { helipad: new pc.Asset( 'helipad-env-atlas', @@ -42,7 +49,7 @@ const assets = { model: new pc.Asset('model', 'container', { url: rootPath + '/static/assets/models/bitmoji.glb' }), board: new pc.Asset('statue', 'container', { url: rootPath + '/static/assets/models/chess-board.glb' }), boombox: new pc.Asset('statue', 'container', { url: rootPath + '/static/assets/models/boom-box.glb' }), - color: new pc.Asset('color', 'texture', { url: rootPath + '/static/assets/textures/seaside-rocks01-color.jpg' }) + color: new pc.Asset('color', 'texture', { url: rootPath + '/static/assets/textures/seaside-rocks01-color.basis' }) }; const gfxOptions = { @@ -115,7 +122,7 @@ assetListLoader.load(() => { // mesh with a basic material const basicMaterial = new pc.BasicMaterial(); - basicMaterial.color.set(0.5, 1.0, 0.7); + basicMaterial.color.set(1.6, 2.7, 1.9); basicMaterial.colorMap = assets.color.resource; const capsule = new pc.Entity('capsule'); diff --git a/src/extras/exporters/core-exporter.js b/src/extras/exporters/core-exporter.js index e64e719883c..dc485ccd7a7 100644 --- a/src/extras/exporters/core-exporter.js +++ b/src/extras/exporters/core-exporter.js @@ -3,7 +3,7 @@ import { Texture } from '../../platform/graphics/texture.js'; import { BlendState } from '../../platform/graphics/blend-state.js'; import { drawQuadWithShader } from '../../scene/graphics/quad-render-utils.js'; import { RenderTarget } from '../../platform/graphics/render-target.js'; -import { FILTER_LINEAR, ADDRESS_CLAMP_TO_EDGE } from '../../platform/graphics/constants.js'; +import { FILTER_LINEAR, ADDRESS_CLAMP_TO_EDGE, isCompressedPixelFormat, PIXELFORMAT_RGBA8 } from '../../platform/graphics/constants.js'; const textureBlitVertexShader = /* glsl */` attribute vec2 vertex_position; @@ -88,12 +88,13 @@ class CoreExporter { // for other image sources, for example compressed textures, we extract the data by rendering the texture to a render target const device = texture.device; const { width, height } = this.calcTextureSize(texture.width, texture.height, options.maxTextureSize); + const format = isCompressedPixelFormat(texture.format) ? PIXELFORMAT_RGBA8 : texture.format; const dstTexture = new Texture(device, { name: 'ExtractedTexture', width, height, - format: texture.format, + format: format, cubemap: false, mipmaps: false, minFilter: FILTER_LINEAR, @@ -113,26 +114,31 @@ class CoreExporter { device.setBlendState(BlendState.NOBLEND); drawQuadWithShader(device, renderTarget, shader); - // read back the pixels - // TODO: use async API when ready - const pixels = new Uint8ClampedArray(width * height * 4); - device.readPixels(0, 0, width, height, pixels); - - dstTexture.destroy(); - renderTarget.destroy(); - - // copy pixels to a canvas - const newImage = new ImageData(pixels, width, height); - const canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - const newContext = canvas.getContext('2d'); - if (!newContext) { - return Promise.resolve(undefined); - } - newContext.putImageData(newImage, 0, 0); + // async read back the pixels of the texture + return dstTexture.read(0, 0, width, height, { + renderTarget: renderTarget, + immediate: true + }).then((textureData) => { + + dstTexture.destroy(); + renderTarget.destroy(); + + const pixels = new Uint8ClampedArray(width * height * 4); + pixels.set(textureData); - return Promise.resolve(canvas); + // copy pixels to a canvas + const newImage = new ImageData(pixels, width, height); + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const newContext = canvas.getContext('2d'); + if (!newContext) { + return Promise.resolve(undefined); + } + newContext.putImageData(newImage, 0, 0); + + return Promise.resolve(canvas); + }); } calcTextureSize(width, height, maxTextureSize) {