diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js index b11ae7424b4f78..3c0b3e7eb7347d 100644 --- a/examples/jsm/loaders/KTX2Loader.js +++ b/examples/jsm/loaders/KTX2Loader.js @@ -16,8 +16,10 @@ import { CompressedTexture, CompressedArrayTexture, CompressedCubeTexture, - Data3DTexture, + DataArrayTexture, + DataCubeTexture, DataTexture, + Data3DTexture, FileLoader, FloatType, HalfFloatType, @@ -294,25 +296,53 @@ class KTX2Loader extends Loader { if ( messageType === 'error' ) return Promise.reject( error ); + const mipmaps = faces[ 0 ].mipmaps; + let texture; - if ( container.faceCount === 6 ) { + if ( format === RGBAFormat ) { + + // THREE.DataTexture + + if ( container.faceCount === 6 ) { + + texture = new DataCubeTexture( mipmaps[ 0 ].data, format, type ); + texture.mipmaps = mipmaps.map( ( mip ) => new DataCubeTexture( mip.data, mip.width, mip.height ) ); + + } else if ( container.layerCount > 1 ) { + + texture = new DataArrayTexture( mipmaps[ 0 ].data, width, height, container.layerCount, format, type ) + texture.mipmaps = mipmaps; + + } else { - texture = new CompressedCubeTexture( faces, format, type ); + texture = new DataTexture( mipmaps[ 0 ].data, width, height, format, type ); + texture.mipmaps = mipmaps; + + } } else { - const mipmaps = faces[ 0 ].mipmaps; + // THREE.CompressedTexture + + if ( container.faceCount === 6 ) { + + texture = new CompressedCubeTexture( faces, format, type ); + + } else if ( container.layerCount > 1 ) { - texture = container.layerCount > 1 - ? new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, type ) - : new CompressedTexture( mipmaps, width, height, format, type ); + texture = new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, type ) + + } else { + + texture = new CompressedTexture( mipmaps, width, height, format, type ); + + } } texture.minFilter = faces[ 0 ].mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter; texture.magFilter = LinearFilter; - texture.generateMipmaps = false; texture.needsUpdate = true; texture.colorSpace = parseColorSpace( container ); diff --git a/examples/textures/compressed/cubemap_etc1s.ktx2 b/examples/textures/compressed/cubemap_etc1s.ktx2 new file mode 100644 index 00000000000000..42587bf0ac038b Binary files /dev/null and b/examples/textures/compressed/cubemap_etc1s.ktx2 differ diff --git a/examples/textures/compressed/cubemap_uastc.ktx2 b/examples/textures/compressed/cubemap_uastc.ktx2 new file mode 100644 index 00000000000000..812bba23adedbb Binary files /dev/null and b/examples/textures/compressed/cubemap_uastc.ktx2 differ diff --git a/examples/webgl_loader_texture_ktx2.html b/examples/webgl_loader_texture_ktx2.html index e36d69d123f038..57a7e98cc2879f 100644 --- a/examples/webgl_loader_texture_ktx2.html +++ b/examples/webgl_loader_texture_ktx2.html @@ -29,9 +29,10 @@ import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + import { TextureHelper } from 'three/addons/helpers/TextureHelper.js'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; - let camera, scene, renderer, controls, loader, material; + let camera, scene, renderer, controls, loader, helper; const SAMPLES = { 'BasisU ETC1S': '2d_etc1s.ktx2', @@ -43,6 +44,10 @@ 'RGBA16 Linear (UASTC HDR)': '2d_rgba16_uastc_hdr_linear.ktx2', 'RGBA32 Linear': '2d_rgba32_linear.ktx2', 'ASTC 6x6 (mobile)': '2d_astc_6x6.ktx2', + + // Cube + 'Cube / BasisU ETC1S': 'cubemap_etc1s.ktx2', + 'Cube / BasisU UASTC': 'cubemap_uastc.ktx2', }; const FORMAT_LABELS = { @@ -99,16 +104,6 @@ controls = new OrbitControls( camera, renderer.domElement ); - // PlaneGeometry UVs assume flipY=true, which compressed textures don't support. - const geometry = flipY( new THREE.PlaneGeometry() ); - material = new THREE.MeshBasicMaterial( { - color: 0xFFFFFF, - side: THREE.DoubleSide, - transparent: true, - } ); - const mesh = new THREE.Mesh( geometry, material ); - scene.add( mesh ); - loader = new KTX2Loader() .setTranscoderPath( 'jsm/libs/basis/' ) .detectSupport( renderer ); @@ -149,9 +144,17 @@ const texture = await loader.loadAsync( `./textures/compressed/${path}` ); texture.minFilter = THREE.NearestMipmapNearestFilter; - material.map = texture; - material.needsUpdate = true; + if ( helper ) { + + scene.remove( helper ); + helper.dispose(); + + } + helper = new TextureHelper( texture ); + scene.add( helper ); + + console.info( `class: ${ texture.constructor.name }` ); console.info( `format: ${ FORMAT_LABELS[ texture.format ] }` ); console.info( `type: ${ TYPE_LABELS[ texture.type ] }` ); console.info( `colorSpace: ${ texture.colorSpace }` ); @@ -167,21 +170,6 @@ } - /** Correct UVs to be compatible with `flipY=false` textures. */ - function flipY( geometry ) { - - const uv = geometry.attributes.uv; - - for ( let i = 0; i < uv.count; i ++ ) { - - uv.setY( i, 1 - uv.getY( i ) ); - - } - - return geometry; - - } - diff --git a/src/Three.core.js b/src/Three.core.js index f7a10261f0014e..e5dad7d1f276bc 100644 --- a/src/Three.core.js +++ b/src/Three.core.js @@ -25,6 +25,7 @@ export { FramebufferTexture } from './textures/FramebufferTexture.js'; export { Source } from './textures/Source.js'; export { DataTexture } from './textures/DataTexture.js'; export { DataArrayTexture } from './textures/DataArrayTexture.js'; +export { DataCubeTexture } from './textures/DataCubeTexture.js'; export { Data3DTexture } from './textures/Data3DTexture.js'; export { CompressedTexture } from './textures/CompressedTexture.js'; export { CompressedArrayTexture } from './textures/CompressedArrayTexture.js'; diff --git a/src/textures/DataCubeTexture.js b/src/textures/DataCubeTexture.js new file mode 100644 index 00000000000000..c4d221878a2caa --- /dev/null +++ b/src/textures/DataCubeTexture.js @@ -0,0 +1,35 @@ +import { Texture } from './Texture.js'; +import { CubeReflectionMapping } from '../constants.js'; + +class DataCubeTexture extends Texture { + + constructor( data, width, height ) { + + super( data, CubeReflectionMapping ); + + this.isDataCubeTexture = true; + this.isCubeTexture = true; + + this.image = { data: data, width: width, height: height }; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + + } + + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; + + } + +} + +export { DataCubeTexture };