Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTX2Loader: Add WebGPU support. #25867

Merged
merged 2 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions examples/jsm/loaders/KTX2Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,37 @@ class KTX2Loader extends Loader {

detectSupport( renderer ) {

this.workerConfig = {
astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ),
etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ),
etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ),
dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ),
bptcSupported: renderer.extensions.has( 'EXT_texture_compression_bptc' ),
pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
|| renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
};
if ( renderer.isWebGPURenderer === true ) {

const adapter = renderer._adapter;

if ( renderer.capabilities.isWebGL2 ) {
this.workerConfig = {
astcSupported: adapter.features.has( 'texture-compression-astc' ),
etc1Supported: false,
etc2Supported: adapter.features.has( 'texture-compression-etc2' ),
dxtSupported: adapter.features.has( 'texture-compression-bc' ),
bptcSupported: false,
pvrtcSupported: false
};

// https://github.com/mrdoob/three.js/pull/22928
this.workerConfig.etc1Supported = false;
} else {

this.workerConfig = {
astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ),
etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ),
etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ),
dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ),
bptcSupported: renderer.extensions.has( 'EXT_texture_compression_bptc' ),
pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' )
|| renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
};

if ( renderer.capabilities.isWebGL2 ) {

// https://github.com/mrdoob/three.js/pull/22928
this.workerConfig.etc1Supported = false;

}

}

Expand Down
61 changes: 41 additions & 20 deletions examples/webgpu_sandbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import * as THREE from 'three';
import { timerLocal, vec2, uv, texture, mix, checker, normalLocal, positionLocal, color, oscSine, attribute, MeshBasicNodeMaterial, PointsNodeMaterial, LineBasicNodeMaterial } from 'three/nodes';

import { DDSLoader } from 'three/addons/loaders/DDSLoader.js';
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';

import WebGPU from 'three/addons/capabilities/WebGPU.js';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
Expand All @@ -39,7 +39,7 @@

init();

function init() {
async function init() {

if ( WebGPU.isAvailable() === false ) {

Expand All @@ -55,6 +55,15 @@
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x222222 );

//

renderer = new WebGPURenderer( { requiredFeatures: [ 'texture-compression-bc', 'texture-compression-astc' ] } );
Copy link
Collaborator Author

@Mugen87 Mugen87 Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also something that might cause troubles. You have to specify the required features (e.g. texture compression formats) when WebGPURenderer is created.

That means a viewer application would have to know in advance what type of assets are going to be imported so it can request the respective features (which is of course unrealistic). I wonder now if it's best to always request all supported features (that includes texture compression formats) every time WebGPURenderer is created. Something like the following in WebGPURenderer.init():

const gpuAdapter = await navigator.gpu.requestAdapter();

const features = [];

for ( const name of featureNames ) {

    if ( gpuAdapter.features.has( name ) ) {

        features.push( name );

    }

}

const deviceDescriptor = {
    requiredFeatures: features
};

const device = await adapter.requestDevice( deviceDescriptor );

renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );
await renderer.init();

// textures

const textureLoader = new THREE.TextureLoader();
Expand All @@ -67,10 +76,11 @@
textureDisplace.wrapS = THREE.RepeatWrapping;
textureDisplace.wrapT = THREE.RepeatWrapping;

// compressed texture
const ktxLoader = new KTX2Loader()
.setTranscoderPath( 'jsm/libs/basis/' )
.detectSupport( renderer );

const ddsLoader = new DDSLoader();
const dxt5Texture = ddsLoader.load( './textures/compressed/explosion_dxt5_mip.dds' );
const ktxTexture = await ktxLoader.loadAsync( './textures/compressed/sample_uastc_zstd.ktx2' );

// box mesh

Expand Down Expand Up @@ -114,7 +124,6 @@
const geometryPlane = new THREE.PlaneGeometry();
const materialPlane = new MeshBasicNodeMaterial();
materialPlane.colorNode = texture( createDataTexture() ).add( color( 0x0000FF ) );
materialPlane.opacityNode = texture( dxt5Texture ).a;
materialPlane.transparent = true;

const plane = new THREE.Mesh( geometryPlane, materialPlane );
Expand All @@ -124,14 +133,15 @@
// compressed texture

const materialCompressed = new MeshBasicNodeMaterial();
materialCompressed.colorNode = texture( dxt5Texture );
materialCompressed.colorNode = texture( ktxTexture );
materialCompressed.emissiveNode = oscSine().mix( color( 0x663300 ), color( 0x0000FF ) );
materialCompressed.alphaTestNode = oscSine();
materialCompressed.transparent = true;

const boxCompressed = new THREE.Mesh( geometryBox, materialCompressed );
boxCompressed.position.set( - 2, 1, 0 );
scene.add( boxCompressed );
const geo = flipY( new THREE.PlaneGeometry() );
const planeCompressed = new THREE.Mesh( geo, materialCompressed );
planeCompressed.position.set( - 2, 1, 0 );
scene.add( planeCompressed );

// points

Expand Down Expand Up @@ -171,14 +181,6 @@
line.position.set( 2, 1, 0 );
scene.add( line );

//

renderer = new WebGPURenderer( { requiredFeatures: [ 'texture-compression-bc' ] } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

window.addEventListener( 'resize', onWindowResize );

}
Expand All @@ -194,8 +196,12 @@

function animate() {

box.rotation.x += 0.01;
box.rotation.y += 0.02;
if ( box ) {

box.rotation.x += 0.01;
box.rotation.y += 0.02;

}

renderer.render( scene, camera );

Expand Down Expand Up @@ -232,6 +238,21 @@

}

/** 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>
</body>
</html>