mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.4k stars 35.28k forks source link

CompressedTextures: Add support for serialization/deserialization. #17974

Open jespertheend opened 4 years ago

jespertheend commented 4 years ago
Description of the problem

When calling toJson() on an object that contains a CompressedTexture, an error gets thrown:

Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
    at Object.getDataURL (js.js?v=000:4184)
    at CompressedTexture.toJSON (js.js?v=000:4398)
    at MeshStandardMaterial.toJSON (js.js?v=000:10171)
    at serialize (js.js?v=000:7295)
    at Mesh.toJSON (js.js?v=000:7349)
    at Object3D.toJSON (js.js?v=000:7363)
    at Scene.toJSON (js.js?v=000:7363)
    at Scene.toJSON (js.js?v=000:7507)

My specific use case is that I load textures in the basis universal format, and I call toJSON() to export my entire scene to a file in order to debug it in the threejs editor.

I don't think it's easy to convert a compressed texture to a data url. But I'll try to make a pull request that at leasts gives a warning and exports it without the texture. Instead of throwing an error.

Three.js version

r110

Browser

Chrome

OS

MacOS

Mugen87 commented 4 years ago

I guess #17745 should already implement a better error handling. It would be great if you can give it a try 👍

jespertheend commented 4 years ago

Hmm it seems like the issue is a bit more complex than I thought, but I think I can make this work. Do you know by any chance if there are situations where it is actually possible to serialize CompressedTextures? Or would it be ok to just generate a warning whenever you try to serialize any CompressedTexture? I don't want to break existing functionality.

Mugen87 commented 4 years ago

Do you know by any chance if there are situations where it is actually possible to serialize CompressedTextures?

I'm not aware of anything like that. That would mean you have to decode the compressed texture on JS side and then transform it into something that can be serialized via getDataURL(). Better to log a warning like so.

donmccurdy commented 4 years ago

Do you know by any chance if there are situations where it is actually possible to serialize CompressedTextures?

It should be possible to implement that, but the behavior might not be what you want. For example, after loading a Basis texture, the original data is transcoded into something compatible with the device's GPU. If you serialize that, you'll be serializing data that's only compatible with certain GPUs, and other devices won't be able to use it at all.

So in terms of saving or transmitting textures, it's not ideal. :/

jespertheend commented 4 years ago

@donmccurdy ah yes, I was expecting that. The original basis data is lost once it is transcoded to a format that the gpu supports. My plan was not to include the texture in the serialized data. But rather to show a warning in the console and continue with the serialization of the object, instead of throwing an error.

jespertheend commented 4 years ago

This should do it #17978