A gLTF model of a baseball park I’m using has 3 image textures. On desktop (macOS Chrome and Safari) the model loads correctly and the seats, grass, and dirt look correct. However, with iOS, the model doesn’t always look correct because one or more textures is black. Sometimes the dirt appears black. Sometimes the grass appears black. Sometimes the seats appear black. But, sometimes the entire model looks correct!
Occasionally, the app will crash with a “problem repeatedly occurred” error.
I can’t really figure out how to make this issue more reproducible but it feels like sometimes loading several tabs causes the issue.
I did some testing on saucelabs as I don’t have access to an iphone with iOS 15 and I don’t see the bug using the lower res textures. Important to note that this shading failure behaviour isn’t present on iphones running iOS 14.
Thanks @donmccurdy, that seems to help. We still see it happen occasionally when we load additional GLB models into the scene (ones that already used 2048x2048 textures), but we’ll do some digging independently now that the codesandbox seems to work better (@aidenhjj and I are working together on this project).
Do you have any thoughts on why the shading issue happens only on iOS? Looking through past topics on this forum, it looks like there are always platform specific idiosyncrasies, but wondering if there was a more technical reason to help us better understand the problem.
It sounds like the device is running out of GPU memory or VRAM, and the last texture(s) to load are going dark. Memory on mobile devices can be very constrained, and even a few 4K textures may be too much. There’s also the recent Safari 15 release, which has a bunch of WebGL updates and could have some bugs.
If the problem is related to memory, then using textures with smaller resolution (PNG and JPEG compression don’t help!) or GPU texture compression like KTX2/Basis would help keep the memory footprint lower.
I having the same problem at a customer project, after updating to iOS/iPadOS 15. The web app runs perfectly fine on macOS and iOS/iPadOS 14.
The problem of missing textures can get resolved by rebooting the device. But after a certain amount of time the textures are missing again. So it seems that Safari on iOS 15 has an annoying memory bug.
Hm this sounds like something that may need to be reported to Apple (or Webkit) unfortunately. There were significant changes in the WebGL implementation with this most recent release.
I am having the same or a similar issue using a 3d viewer wordpress plugin, that uses three.js
I use some 3d models that have transparent png textures mapped on to them and exported them with blender v2.92.0 as glTF files. They all appear correct on windows, mac os, android and ios14. On ios15 however the 3d-models themself are working fine but the mapped textures sometimes appear black or don’t appear at all. check out this screenshot for reference: glTF issue on iOS15 - Album on Imgur
I am wondering if there is something else I can try when exporting the 3d models from blender to make them work correctly on ios15. Any help is greatly appreciated!
I’m having the same issue. My app works fine with any iOS(14 and below) and Android devices but only shows black on models and gets crashed in both Chrome and Safari on iOS15.
I tested with smaller textures(decreased from 2k to 512) and it got back to work. So, I think it is an memory issue.
By the way, I tried to downgrade the same in your code sandbox, and the stadium looks perfect, nothing missing. You should give it a try.
Update3:
I fixed this issue in a sort of way(or workaround).
I suspect there’s some wrong with iOS15’s GPU memory management which affects texture uploading to the GPU. So, I throttled textures instantiations (set a timeout for each texture, 10~ 20 512*512 textures total), and the black texture issue never recured.
Update: the gpu compression tip was very helpful. You can take a folder of gltf files and do something like this to convert the textures to ktx2 format:
#!/bin/bash
# make and make install https://github.com/BinomialLLC/basis_universal
for d in */ ; do
pushd $d
for file in *; do
echo $file
if [[ $file == *.jpg ]]; then
basisu -ktx2 $file
rm $file
else
if [[ $file == *.gltf ]]; then
sed -i -e "s/\.jpg/\.ktx2/g" $file
sed -i -e "s/image\/jpeg/image\/ktx2/g" $file
fi
fi
done
popd
done
To load the gltfs in three.js, you have to do a couple of other things, included here just in case someone finds it helpful:
import { LoadingManager } from "three";
import { GLTF, GLTFLoader, KTX2Loader } from "three-stdlib";
const transcoderUrl = <url where you've hosted these files https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis>
// load universal basis gpu compressed textures
const texLoader = new KTX2Loader();
const texLoadManager = new LoadingManager();
texLoadManager.addHandler(/\.ktx2$/, texLoader);
const loader = new GLTFLoader(texLoadManager);
texLoader.setTranscoderPath(transcoderUrl);
const { gl } = useThree();
texLoader.detectSupport(gl);
...
loader.load(modelUrl, etc, etc);
We were able to load large gltfs with 8k textures using this approach.
I use ImageLoader to manage textures manully so it’s easily to wrap a setTimeout to each image request. If you use loaders such as gltf loader, I’m not sure how to control the texture loading frequency.
Understood… Unfortunately in my case i don’t have access to the textures as a saparate object but i receive a glb with textures already built in.
Thank you anyway
I’m trying to follow your steps (but in angular) but i get the error DataCloneError: The object can not be cloned when the code hit the load function
Here is my code
const texLoader = new KTX2Loader();
const texLoadManager = new LoadingManager();
texLoadManager.addHandler(/\.ktx2$/, texLoader);
const loader = new GLTFLoader(texLoadManager)
texLoader.setTranscoderPath("assets/three/basis/");
texLoader.detectSupport(this.renderer);
loader
.load("assets/lenses/test.gltf", gltf => {
console.log('x', gltf)
})
Do you have any idea what could cause this?
This is the gltf folder
@tomthebearded - I’m not sure. I’ve not seen this error. Have you tested just fetching the basis/ files and the gltf files? I wonder if the filename links to the textures in the gltf file got corrupted somehow.
Thank you for the quick response… i’ve update the threejs version and now when the code reaches the load function it doesn’t seem to do anything.
I’ll try to re-create the gltf with the basis tool.
Ok now i can load the model but the texture are missing
For some reason it’s searching files with a duplicate extension .ktx2.ktx2. I don’t know why, if i inspect the gltf there is only one ktx2 per file.
The gltf file has a json component - you should be able to just open it in a text editor and search for those file names - it looks to me that you’ve mangled the fillenames in the gltf itself.