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

Add .dds support to GLTFLoader #13820

Merged
merged 6 commits into from
Apr 12, 2018
Merged

Add .dds support to GLTFLoader #13820

merged 6 commits into from
Apr 12, 2018

Conversation

Bergmam
Copy link

@Bergmam Bergmam commented Apr 10, 2018

I implemented support for using the GLTFLoader with .gltf-files containing the MSFT_texture_dds extension (https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Vendor/MSFT_texture_dds/README.md)

If the GLTF-file loaded by the GLTFLoader contains the extension, the loader will now import DDSLoader.js and load the correct .dds files as specified by the extension.

I also added another version of the Boombox gltf model that uses the extension with .dds image files, as well as extended the webgl_loader_gltf_extensions example to showcase the GLTFLoader functionality on the new Boombox model.

…files. Add dds boombox to gltf extensions example.
@olleman42
Copy link

👍

@@ -1780,7 +1786,6 @@ THREE.GLTFLoader = ( function () {
* @return {Promise<THREE.Texture>}
*/
GLTFParser.prototype.loadTexture = function ( textureIndex ) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think no need to remove an empty line here.

if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

var DDSLoader = new THREE.DDSLoader;
source = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];
Copy link
Collaborator

Choose a reason for hiding this comment

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

I want to display warning or error if DDSLoader isn't imported.


var loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader;

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's move var loader out from if else for the consistency with other parts.

var loader;

if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

    loader = DDSLoader;

} else {

    loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader;

}

<script src="js/loaders/GLTFLoader.js"></script>

Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to add tab here.

var source;
if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

var DDSLoader = new THREE.DDSLoader;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we reuse one DDSLoader for all dds textures like textureLoader?

@@ -120,7 +120,6 @@ THREE.GLTFLoader = ( function () {
return;

}

Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to remove an empty line here.

@@ -71,7 +72,7 @@
cameraPos: new THREE.Vector3( 0.02, 0.01, 0.03 ),
objectRotation: new THREE.Euler( 0, Math.PI, 0 ),
addLights: true,
extensions: [ 'glTF', 'glTF-pbrSpecularGlossiness', 'glTF-Binary' ],
extensions: [ 'glTF', 'glTF-pbrSpecularGlossiness', 'glTF-Binary', 'glTF-dds'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

You need a space after 'glTF-dds'

@@ -147,6 +146,12 @@ THREE.GLTFLoader = ( function () {

}

if ( json.extensionsUsed.indexOf( EXTENSIONS.MSFT_TEXTURE_DDS ) >= 0 ) {

extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = "MSFT_texture_dds";
Copy link
Collaborator

Choose a reason for hiding this comment

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

How about making GLTFTextureDDSExtension() for the consistency with other extensions? And if you instantiate DDSLoader there, it can be reused.

function GLTFTextureDDSExtension() {

    this.name = EXTENSIONS.MSFT_TEXTURE_DDS;
    this.loader = new THREE.DDSLoader();

}

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1. I would also throw the error at this point in the constructor if DDSLoader doesn't exist.

Copy link
Author

Choose a reason for hiding this comment

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

Now initializing THREE.DDSLoader in GLTFTextureDDSExtension, also added throwing an error if it does not exist

@takahirox
Copy link
Collaborator

Nice work! I commented mainly for Three.js / GLTFLoader code style.


loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader;

}
Copy link
Collaborator

@donmccurdy donmccurdy Apr 10, 2018

Choose a reason for hiding this comment

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

If THREE.Loader.Handlers.get( sourceURI ) returns a loader, it should override even the DDSLoader extension. Loader.Handlers is an escape hatch for getting images from drag-and-drop events, workers, or other custom sources. You can assume that it will return a DDSLoader for .dds files, if the developer is using it properly.

Copy link
Author

Choose a reason for hiding this comment

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

I changed it to

if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

				loader = THREE.Loader.Handlers.get( sourceURI ) || parser.extensions[EXTENSIONS.MSFT_TEXTURE_DDS].ddsLoader

			}

Please verify if correct or if I misunderstood. :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

The logic looks right, yes. Might trim it a little:

var loader = THREE.Loader.Handlers.get( sourceURI );

if ( ! loader ) {

  loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]
    ? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
    : textureLoader;

}


}

var DDSLoader = new THREE.DDSLoader;
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: we use () on constructors.

@Bergmam
Copy link
Author

Bergmam commented Apr 11, 2018

All above comments should be fixed now.


throw new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' );

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This error would need to be thrown in the constructor of GLTFTextureDDSExtension, I think it will error out before it gets here otherwise.

Copy link
Author

Choose a reason for hiding this comment

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

My bad, forgot to move it after I implemented GLTFTextureDDSExtention function. Fixed now :)


loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader;

}
Copy link
Collaborator

Choose a reason for hiding this comment

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

The logic looks right, yes. Might trim it a little:

var loader = THREE.Loader.Handlers.get( sourceURI );

if ( ! loader ) {

  loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]
    ? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
    : textureLoader;

}

function GLTFTextureDDSExtension() {

this.name = EXTENSIONS.MSFT_TEXTURE_DDS;
this.ddsLoader = new THREE.DDSLoader();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: spaces -> tabs

@donmccurdy
Copy link
Collaborator

donmccurdy commented Apr 12, 2018

Looks good! Demo.

This is in the category of extensions that are harder to do outside the loader, because without it the loader will still request the (backup) uncompressed versions of textures, so I am OK with merging it into three.js despite its being a vendor extension. We will not necessarily support other MSFT_ extensions, and may remove this one when a Khronos or EXT_ alternative becomes available.

The only remaining issue from my perspective is this: with this change, the loader will always request compressed textures when the extension is present. On devices that don't support DDS (mobile) we should be falling back to uncompressed textures or alternative compression instead. I believe the way to test for this would be renderer.extensions.get('WEBGL_compressed_texture_s3tc')...

Do other three.js loaders have an API for this? If not, I'd propose:

var useDDS = !! renderer.extensions.get( 'WEBGL_compressed_texture_s3tc' );
loader
  .setExtensionEnabled( 'MSFT_texture_dds', useDDS )
  .load( 'foo.glb', () => {...} );

EDIT: The above can likely be addressed in another PR, too.

Copy link
Collaborator

@donmccurdy donmccurdy left a comment

Choose a reason for hiding this comment

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

Actually, I think I'd rather deal with enable/disable flags in a later PR. Approved!

@mrdoob mrdoob added this to the r92 milestone Apr 12, 2018
@mrdoob mrdoob merged commit 83ec0a1 into mrdoob:dev Apr 12, 2018
@mrdoob
Copy link
Owner

mrdoob commented Apr 12, 2018

Thanks!

@donmccurdy
Copy link
Collaborator

As an FYI, I'm recommending that we remove DDS support from future versions of GLTFLoader — we have cross-platform compressed texture support available through the KHR_texture_basisu extension now, and would like to steer users toward that for greater compatibility. Thanks again for this PR, bridging the 2.5 year gap to this point.

See: #21271

@takahirox
Copy link
Collaborator

Kudos to @Bergmam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants