import { PlaneGeometry, ShaderMaterial, Uniform, Mesh, PerspectiveCamera, Scene, WebGLRenderer, CanvasTexture, SRGBColorSpace } from 'three'; let _renderer; let fullscreenQuadGeometry; let fullscreenQuadMaterial; let fullscreenQuad; export function decompress( texture, maxTextureSize = Infinity, renderer = null ) { if ( ! fullscreenQuadGeometry ) fullscreenQuadGeometry = new PlaneGeometry( 2, 2, 1, 1 ); if ( ! fullscreenQuadMaterial ) fullscreenQuadMaterial = new ShaderMaterial( { uniforms: { blitTexture: new Uniform( texture ) }, vertexShader: ` varying vec2 vUv; void main(){ vUv = uv; gl_Position = vec4(position.xy * 1.0,0.,.999999); }`, fragmentShader: ` uniform sampler2D blitTexture; varying vec2 vUv; void main(){ gl_FragColor = vec4(vUv.xy, 0, 1); #ifdef IS_SRGB gl_FragColor = LinearTosRGB( texture2D( blitTexture, vUv) ); #else gl_FragColor = texture2D( blitTexture, vUv); #endif }` } ); fullscreenQuadMaterial.uniforms.blitTexture.value = texture; fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == SRGBColorSpace; fullscreenQuadMaterial.needsUpdate = true; if ( ! fullscreenQuad ) { fullscreenQuad = new Mesh( fullscreenQuadGeometry, fullscreenQuadMaterial ); fullscreenQuad.frustumCulled = false; } const _camera = new PerspectiveCamera(); const _scene = new Scene(); _scene.add( fullscreenQuad ); if ( renderer === null ) { renderer = _renderer = new WebGLRenderer( { antialias: false } ); } const width = Math.min( texture.image.width, maxTextureSize ); const height = Math.min( texture.image.height, maxTextureSize ); renderer.setSize( width, height ); renderer.clear(); renderer.render( _scene, _camera ); const canvas = document.createElement( 'canvas' ); const context = canvas.getContext( '2d' ); canvas.width = width; canvas.height = height; context.drawImage( renderer.domElement, 0, 0, width, height ); const readableTexture = new CanvasTexture( canvas ); readableTexture.minFilter = texture.minFilter; readableTexture.magFilter = texture.magFilter; readableTexture.wrapS = texture.wrapS; readableTexture.wrapT = texture.wrapT; readableTexture.name = texture.name; if ( _renderer ) { _renderer.forceContextLoss(); _renderer.dispose(); _renderer = null; } return readableTexture; }