Opened 3 years ago
Closed 3 years ago
#8511 closed enhancement (fixed)
Make GLTF save volume image rendering
Reported by: | Tom Goddard | Owned by: | Tom Goddard |
---|---|---|---|
Priority: | moderate | Milestone: | |
Component: | Input/Output | Version: | |
Keywords: | Cc: | ||
Blocked By: | Blocking: | ||
Notify when closed: | Platform: | all | |
Project: | ChimeraX |
Description
Would like the GLTF writer to save volume image rendering as a stack of transparent planes. Currently it does not save the textures.
Change History (3)
comment:1 by , 3 years ago
comment:2 by , 3 years ago
GLTF only handles 2D textures. So the volume needs to use 2D texture rendering and not use colormapping on the GPU
volume projectionMode 2d-z colormapOnGpu false
The implementation for 2D rendering uses a single drawing for all the planes with a texture for each plane using Drawing.multitexture. So GLTF export has to look for multitexture and then separate the planes into separate GLTF mesh primitives.
GLTF by default does back face culling. For volume texture planes need to set the GLTF material doubleSided attribute to true.
The texture values can be read in ChimeraX from OpenGL with glGetTexImage(). It will require making the OpenGL context current. A routine could be added to the Texture class to read the values.
I made all these fixes and rendered a 512x512x16 DICOM slab and it looked beautiful in both BabylonJS and Unity on the Quest 2. I have not yet committed the changes. Still testing.
comment:3 by , 3 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Done.
It can be pretty slow to save a GLTF with a volume image I think because reading the textures back from the GPU is slow. I added two-sided lighting for textured models in the GLTF export so GLTF viewers don't do backface culling.
The GLTF save code has a bit that will save a Drawing texture if it finds an attribute "image_array" on the texture. But it does not appear that any ChimeraX code sets such an attribute. I suspect this was to save photos. A photo can be opened using format "photo" (e.g. open face.png format photo) producing an ImageSurface instance defined in image_formats/open_image.py and it has an _image_array attribute. I'm guessing that code changed and the GLTF writer was originally trying to save such images.
The volume image rendering makes a Texture and a Texture has a "data" attribute with the image array, but it is set to None as soon as the OpenGL texture is loaded. So the Texture in general does not have the original image data.