Skip to content

Commit

Permalink
Add TextureHelper.
Browse files Browse the repository at this point in the history
  • Loading branch information
donmccurdy committed Sep 6, 2023
1 parent 99fd5d6 commit b4b6522
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 42 deletions.
122 changes: 122 additions & 0 deletions examples/jsm/helpers/TextureHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import {
Mesh,
ShaderMaterial,
BoxGeometry
} from 'three';

class TextureHelper extends Mesh {

constructor( texture, width = 1, height = 1, depth = 1 ) {

const material = new ShaderMaterial( {

type: 'TextureHelperMaterial',

uniforms: {

map: { value: texture },

},

vertexShader: [

'varying vec3 vUvw;',

'void main() {',

' vUvw = vec3( uv, 0.0 );', // TODO: Populate 'w' for cube, 3D, and array textures.

' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',

'}',

].join( '\n' ),

fragmentShader: [

'precision highp float;',

'precision highp sampler2DArray;',

'precision highp sampler3D;',

'uniform {samplerType} map;',

'varying vec3 vUvw;',

'vec4 textureHelper( in sampler2D map ) { return texture( map, vUvw.xy ); }',

'vec4 textureHelper( in sampler2DArray map ) { return texture( map, vUvw ); }',

'vec4 textureHelper( in sampler3D map ) { return texture( map, vUvw ); }',

'vec4 textureHelper( in samplerCube map ) { return texture( map, vUvw ); }',

'void main() {',

' gl_FragColor = linearToOutputTexel( textureHelper( map ) );',

'}'

].join( '\n' ).replace( '{samplerType}', getSamplerType( texture ) )

} );

// TODO: Display as stack of images.
const geometry = new BoxGeometry( width, height, depth );
if ( texture.flipY === false ) flipY( geometry );

super( geometry, material );

this.texture = texture;
this.type = 'TextureHelper';

}

dispose() {

this.geometry.dispose();
this.material.dispose();

}

}

function getSamplerType( texture ) {

if ( texture.isCubeTexture ) {

return 'samplerCube';

} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {

return 'sampler2DArray';

} else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) {

return 'sampler3D';

} else {

return 'sampler2D';

}

}

/** 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;

}

export { TextureHelper };
2 changes: 1 addition & 1 deletion examples/jsm/loaders/KTX2Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ async function createRawTexture( container ) {

if ( container.faceCount === 6 ) {

texture = new DataCubeTexture( mipmaps[ 0 ].data );
texture = new DataCubeTexture( mipmaps );

} else if ( container.layerCount > 1 ) {

Expand Down
Binary file added examples/textures/compressed/3d_etc1s.ktx2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added examples/textures/compressed/3d_rgba32_lut.ktx2
Binary file not shown.
Binary file added examples/textures/compressed/3d_rgba8.ktx2
Binary file not shown.
Binary file added examples/textures/compressed/3d_rgba8_linear.ktx2
Binary file not shown.
Binary file added examples/textures/compressed/3d_uastc.ktx2
Binary file not shown.
57 changes: 16 additions & 41 deletions examples/webgl_loader_texture_ktx2.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,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, plane, cube, material;
let camera, scene, renderer, controls, loader, helper;

const SAMPLES = {
// 2D
Expand All @@ -48,6 +49,15 @@
'2D / RGBA32 Linear': '2d_rgba32_linear.ktx2',
'2D / ASTC 6x6 (mobile)': '2d_astc_6x6.ktx2',

// 3D
'3D / BasisU ETC1S': '3d_etc1s.ktx2',
'3D / BasisU UASTC': '3d_uastc.ktx2',
'3D / RGBA8 sRGB': '3d_rgba8.ktx2',
'3D / RGBA8 Linear': '3d_rgba8_linear.ktx2',
'3D / RGBA16 Linear': '3d_rgba16_linear.ktx2',
'3D / RGBA32 Linear': '3d_rgba32_linear.ktx2',
'3D / RGBA32 LUT': '3d_rgba32_lut.ktx2',

// Cube
'Cube / RGBA8 sRGB': 'cubemap_rgba8.ktx2',
'Cube / RGBA8 Linear': 'cubemap_rgba8_linear.ktx2',
Expand Down Expand Up @@ -104,7 +114,6 @@
window.addEventListener( 'resize', onWindowResize );

scene = new THREE.Scene();
scene.background = new THREE.Color( 0x202020 );

camera = new THREE.PerspectiveCamera( 60, width / height, 0.1, 100 );
camera.position.set( 0, 0, 2.5 );
Expand All @@ -113,20 +122,6 @@

controls = new OrbitControls( camera, renderer.domElement );

// Default UVs assume flipY=true, which compressed textures don't support.
const planeGeometry = flipY( new THREE.PlaneGeometry() );
const cubeGeometry = flipY( new THREE.BoxGeometry() );
material = new THREE.MeshBasicMaterial( {
color: 0xFFFFFF,
side: THREE.DoubleSide,
transparent: true,
} );
plane = new THREE.Mesh( planeGeometry, material );
cube = new THREE.Mesh( cubeGeometry, material );
cube.visible = false;
scene.add( plane );
scene.add( cube );

loader = new KTX2Loader()
.setTranscoderPath( 'jsm/libs/basis/' )
.detectSupport( renderer );
Expand Down Expand Up @@ -169,19 +164,15 @@
texture.minFilter = THREE.NearestMipmapNearestFilter;
texture.needsUpdate = true;

if ( path.startsWith( 'cube' ) ) {
if ( helper ) {

texture.mapping = THREE.CubeUVReflectionMapping;
scene.remove( helper );
helper.dispose();

}

scene.background = null;

material.map = texture;
material.needsUpdate = true;

plane.visible = path.startsWith( '2d' );
cube.visible = path.startsWith( 'cube' ) || path.startsWith( 'array' );
helper = new TextureHelper( texture );
scene.add( helper );

console.info( `class: ${ texture.constructor.name }` );
console.info( `format: ${ FORMAT_LABELS[ texture.format ] }` );
Expand All @@ -196,22 +187,6 @@

// NOTE: Call `loader.dispose()` when finished loading textures.


}

/** 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;

}

</script>
Expand Down

0 comments on commit b4b6522

Please sign in to comment.