CubeMapToSphericalPolynomialTools.ConvertCubeMapToSphericalPolynomial takes about 15s on Safari. For comparison, it takes about 3s on Chrome. Still very slow.
What happens is:
A mesh (with a PBR material) enters the frustum.
Even though it’s completely occluded, the engine calls bindForSubMesh, which decides it mustRebind. Shouldn’t the mesh be ignored?
Then we have this:
if (!ubo.useUbo || !this.isFrozen || !ubo.isSync) { useUbo=false, isFrozen=true, ubo.isSync=true.
We proceed because useUbo is false, but… should we be checking for ubo.isSync, if useUbo is false?
We then check if there’s a reflection texture, and if so, get its sphericalPolynomial property. That’s what’s slow.
The worst part is… the reason we computed the polynomials is to update ubo, which is disabled!
It seems odd that we’re reading a property (sphericalPolynomial) synchronously, while the actual computation is done in a Promise. The property returns null until it’s computed, so the whole UBO update fails anyway.
Using a promise doesn’t help anyway, b/c it still runs on the main thread… It should be in a worker.
My apologies, if I’m jumping to conclusions. There’s a lot I don’t understand, so I could be totally wrong.
Anyway, I’m working around this by converting all PBR materials to standard. I don’t use PBRs, but that’s how GLTF materials are loaded.
@alekop this should be precomputed and cached if you use an env file instead of hdr for your environment texture.
Computing on the client is a waste of resources except in scenari of configurators like the sandbox where the user could dynamically chose any HDR files or with dynamic probes and so on,
When you see ubo.updateXXX(...), the uniform buffer is updated if ubo.useUbo==true and it is the effect which is updated if ubo.useUbo==false. ubo.updateXXX(...) is not an empty operation when ubo.useUbo==false.