For some assets there is a frame rate drop due to geometry & material data getting pushed to the GPU the first time it gets rendered
The question about how to avoid the frame rate drop has been asked before, but the answer I saw in those posts was to preload textures and such if possible. What happens if we we don’t know about the models beforehand? Has anyone found a way to get mesh data to the renderer in a manner that doesn’t lead to frame rate dropping?
Context: I’m making a Chess app over WebRTC where a player’s avatar is not known until the user connects to that player. On load, the avatar could have the stuttering issue which I’d like to mitigate as it’s especially jarring in VR. Here’s an asset courtesy of Wolf3D that the renderer slows down for https://s3.amazonaws.com/readyplayerbaker/avatars_baked/953199c4-d244-4529-8feb-b2ed67a81099.glb
Fact is you can’t avoid the framedrop completely. Even if your model uses no textures, shader programs have to be compiled and buffer data have to be uploaded to the GPU.
You can try to modify GLTFLoader
to use ImageBitmapLoader
although the support of ImageBitmap
is still limited (e.g. it does not work with Safari). This can noticeably mitigate GPU upload overhead (without preloading data) however it won’t help if you asset contains no textures.
Can’t properly test right now, but opening it locally with a gltf viewer it tells
GLTFLoader: 500.388671875ms
Not sure why gltf takes 500 ms here or what gltf still stores as json or what this measurement includes. For large assets you can also balance load over several render cycles, but that’s mostly useful for really large assets which yours not really is. But avoiding sudden bulk uploads helps in order to avoid visible lags.
This can cause the most noticeable lag (but also large textures or geometries), but if these avatars all share the same program there shouldn’t be a compilation (again).
Thank you both for the responses!
Curious for if/when I use large assets, how would one go about loading them over several render cycles?
I made some core changes but you should be able to do it another just little less handy way too, for example simply hide the new asset materials (visible to false), and after each render cycle you show one after another. You can also use a placeholder material for the not-yet shown ones. Resources get uploaded the first time they’re about to get rendered.
For textures it works similar, you just distribute their upload across frames, ideally you organize it by visibility, so visible parts get loaded first. It’s also important to avoid non power of 2 textures as they get resized and will definitely cause lag.
It’s a difference if you would load 60 different assets into your scene at once or across 60 frames. I do it partially more lazy and sometimes more eager, as it’s more stable to skip few frames in between (ideally pick low cost frames) but when there are much more assets about to appear and there is no current workload they get pushed in advance. But that’s rather something for large scenes you can manage spatially.
Material programs, like for avatars should be shared generally, they won’t get recompiled as long as their code is the same, so materials using them don’t cause any compilation lag.
Ah thanks for the thorough explanation. I haven’t tested the delay on loading a second avatar but it seems like anything after the first should load faster (assuming both are from Wolf3D). And in this case I could preload one in the beginning for a frame