-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
GLTFExporter grows files 5x from import #23587
Comments
A couple thoughts here, choose your own adventure — I feel like the behavior of the three.js editor — exporting all images as PNG — is probably 'right' for its use case. It's the only way to export losslessly, and the only way to avoid compounding compression artifacts with repeated import/edit/export steps. Compression can be applied at the end of the edit process, with a variety of other tools. Are you hoping for a fix that allows model-viewer to keep the previous behavior, re-compressing any image that was originally a JPEG? Or something else? I'm afraid I don't see a quick workaround that doesn't feel pretty hacky, at the moment. Perhaps this is a more complicated answer than you're looking for, but — there are a lot of similar but more subtle issues caused by import/edit/export with GLTFExporter as well:
Because of all of those issues, I'm working on a different approach with https://gltf.report/ —
The idea here is that edits can still be displayed instantly, but repeated import/edit/export steps don't have any side effects. The glTF-Transform-Render code still needs quite a bit more testing, though. I'm pretty close to having |
Another option is to add the following code back and store the result in
I'm not sure |
That's wrong anyway. |
This doesn't feel great to have in GLTFLoader, to me – it's more bookkeeping that needs to be maintained for a narrow use case. Similar to the 'associations' mappings we're maintaining (e.g. #22750); it would be really nice if GLTFLoader could be more focused on just efficiently loading glTF files into "normal" three.js objects. Also, knowing the texture has alpha isn't enough — if the texture is a normal map you probably want to export it as PNG rather than JPEG, even without alpha. So this starts to turn into custom logic in GLTFLoader and GLTFExporter that is only relevant for that specific workflow. And if it was a JPEG before, re-compressing as JPEG (rather than using the original data) degrades the quality.
Definitely this is the right way to build a model editor. 👍🏻 But since |
@donmccurdy Thanks for the detail; agreed the behavior before was hacky and the right solution is a library like glTF Transform. However, what we had before was usable (in my experience there's actually very little loss from recompressing a JPEG to a JPEG, especially if the quality setting is the same, since the DCT ends up being pretty close to reversible). I have an idea for a small change to the exporter that would infer mime type from the file extension (if present). I realize it's still a hack, but it's vastly better than 5x expansion without recourse. I'll put up a PR for discussion. I'd love to switch over to a proper method, but that will take time. I need some way to work around this in the meanwhile, and at least the file extension will be a bit more reliable than |
Also recently thought a lot about this, and generally how to get at least "something that looks right" and at best "something that also has the right size" back from an import/export loop. Similar to what @donmccurdy is proposing, my main line of thinking was to cache the original buffers (if memory permits) on import and then, if possible, re-using them on export. I would have probably built that as import and export extensions to three. This would be contstrained to the current glTF Import/Export flow (e.g. no other formats would immediately do this and for other formats it might be harder), but it solves for a lot of cases of "I'm re-arranging a number of files that have already been nicely compressed and want to have a new file". In any way, this kind of clashes with the ideal of removing things from CPU memory once they're uploaded to the GPU, but at least from my end I think that hit would be preferrable over "expanding" data on export (readback from GPU and turn everything to PNG). (And a side note, in UnityGLTF I also added a heuristic on export to determine if files should be PNG or JPEG, but that's easier there since there's import-time metadata from the editor to guide that decision.) |
@elalish is the file extension accessible, e.g. after loading from ImageBitmap? That does sound more reliable if so. @hybridherbst - if that workflow is possible through extensions then it's likely a decent workaround as well! I'm hesitant to preserve that extra data directly in GLTFLoader though. |
That's a myth! |
Indeed it's not. Would anyone be tremendously opposed to adding a |
I think Texture seems the wrong place to add a mimeType field. If there are special behavior requirements, to avoid the complexity tracking that @donmccurdy mentioned, I think the best approach really is hooking the loader to store original textures for later along with anything else application specific. Then add an option to GLTFExporter that allows granular selection of how you want each texture exported. Flags could be set for each texture: I've extended these classes for other reasons and the technique has been stable through many versions of three.js releases. |
@donmccurdy I had thought I could use |
Maybe it is better to always export textures as WebP? WebP is now supported in 92-96% of browsers. |
Unfortunately I don't think we'd want WebP as the default — it's not an official Khronos extension in glTF, and will prevent people from loading the model in Blender. Plus we'd still have to decide whether to use WebP's lossless mode or not, similar to the PNG vs. JPEG decision here. If you want to convert glTF files to use WebP that'll be possible with this PR though. |
dont they all just have blob urls? so you could just |
The Blob URLs are revoked after loading, but yes -- if you were to disable that and use them in GLTFExporter (to access the ArrayBuffer) I think it'd work. |
Describe the bug
JPEG textures in an input GLB get exported as PNG, causing such models to grow enormously in size.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The exported model should be pretty close to the same size as the original. I understand it won't be identical, which is fine, but this is pretty unusable.
Cause
#23385 is sort of the culprit, but really it was #23228 where the RGBFormat was removed and this was the only way we had to tell if a texture had been a JPG or a PNG. @Mugen87 @donmccurdy This is blocking model-viewer's update to r137/r138 because it affects our editor the same as yours. Can anyone think of a quick work-around?
The text was updated successfully, but these errors were encountered: