-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
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
Conversation
…files. Add dds boombox to gltf extensions example.
👍 |
examples/js/loaders/GLTFLoader.js
Outdated
@@ -1780,7 +1786,6 @@ THREE.GLTFLoader = ( function () { | |||
* @return {Promise<THREE.Texture>} | |||
*/ | |||
GLTFParser.prototype.loadTexture = function ( textureIndex ) { | |||
|
There was a problem hiding this comment.
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.
examples/js/loaders/GLTFLoader.js
Outdated
if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) { | ||
|
||
var DDSLoader = new THREE.DDSLoader; | ||
source = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ]; |
There was a problem hiding this comment.
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.
examples/js/loaders/GLTFLoader.js
Outdated
|
||
var loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader; | ||
|
||
} |
There was a problem hiding this comment.
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> | ||
|
||
There was a problem hiding this comment.
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.
examples/js/loaders/GLTFLoader.js
Outdated
var source; | ||
if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) { | ||
|
||
var DDSLoader = new THREE.DDSLoader; |
There was a problem hiding this comment.
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
?
examples/js/loaders/GLTFLoader.js
Outdated
@@ -120,7 +120,6 @@ THREE.GLTFLoader = ( function () { | |||
return; | |||
|
|||
} | |||
|
There was a problem hiding this comment.
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'], |
There was a problem hiding this comment.
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'
examples/js/loaders/GLTFLoader.js
Outdated
@@ -147,6 +146,12 @@ THREE.GLTFLoader = ( function () { | |||
|
|||
} | |||
|
|||
if ( json.extensionsUsed.indexOf( EXTENSIONS.MSFT_TEXTURE_DDS ) >= 0 ) { | |||
|
|||
extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = "MSFT_texture_dds"; |
There was a problem hiding this comment.
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();
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Nice work! I commented mainly for Three.js / GLTFLoader code style. |
examples/js/loaders/GLTFLoader.js
Outdated
|
||
loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader; | ||
|
||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. :)
There was a problem hiding this comment.
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;
}
examples/js/loaders/GLTFLoader.js
Outdated
|
||
} | ||
|
||
var DDSLoader = new THREE.DDSLoader; |
There was a problem hiding this comment.
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.
All above comments should be fixed now. |
examples/js/loaders/GLTFLoader.js
Outdated
|
||
throw new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' ); | ||
|
||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
examples/js/loaders/GLTFLoader.js
Outdated
|
||
loader = THREE.Loader.Handlers.get( sourceURI ) || textureLoader; | ||
|
||
} |
There was a problem hiding this comment.
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;
}
examples/js/loaders/GLTFLoader.js
Outdated
function GLTFTextureDDSExtension() { | ||
|
||
this.name = EXTENSIONS.MSFT_TEXTURE_DDS; | ||
this.ddsLoader = new THREE.DDSLoader(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spaces -> tabs
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 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 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. |
There was a problem hiding this 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!
Thanks! |
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 See: #21271 |
Kudos to @Bergmam |
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.