Intro
Hey everybody! I have been working on performance issues and the goal is to minimize “black screen scene loading time” when some assets has been already loaded but not rendered due to the fact that the scene didn’t finish its loading state (I hope you understand).
Problem Description
And I have a .gltf skybox model which is loading using ImportMeshAsync()
method. I chain it with then()
method in which I try to invoke animation using beginAnimation()
to smoothly animate visibility of my skybox mesh. And after that again I do chain with then()
method loading another meshes etc. (The goal is to display skybox as fast as possible because I have custom preloader which manipulates DOM while babylonjs’ chunk is still loading).
The trouble is the animation is not invoked until every single resource in the chain has complete its loading state.
Variants of fix
I can fix that by saving result of beginAnimation()
to any variable and then await it using await variable.waitAsync()
in then
method. But in that case my next resources are not starting to load till my animation is complete (despite it’s just a function, not a file which I load from any server, etc.).
I fixed this using beforeRenderObservable-like animation and I pretty like this solution but I would highly appreciate for explanations for animations if it’s possible. Maybe I am wrong somewhere.
Minimal reproduction
In the playground linked below I did a minimal reproduction of my issue. (You can use throttling if needed to lower loading speed of models in playground).
P.S. The real code if interested
Production-like code
. . .
SceneLoader.ImportMeshAsync(
"",
"./models/",
"nebula_skybox_test.gltf",
scene,
onProgress,
".gltf"
)
.then(({ meshes }) => {
console.log("NEBULA HERE");
const rootMesh = meshes[0];
this.createParticleSystem(rootMesh, scene);
rootMesh.scaling.scaleInPlace(500);
const nebulaSkyboxMesh = meshes.find(
({ name }) => name === "Nebula Skybox_Material_0"
);
nebulaSkyboxMesh.parent = null;
console.log(nebulaSkyboxMesh);
nebulaSkyboxMesh.visibility = 0;
// TODO: Animation doesn't work while loading is not completely finished. Need to make a topic on forum.
// const nebulaVisibilityAnimation = new Animation(
// "nebula-visibility",
// "visibility",
// 120,
// Animation.ANIMATIONTYPE_FLOAT,
// Animation.ANIMATIONLOOPMODE_CONSTANT,
// false
// );
// const keyFrames: IAnimationKey[] = [];
// keyFrames.push({
// frame: 0,
// value: 0,
// });
// keyFrames.push({
// frame: 120,
// value: 1,
// });
// nebulaVisibilityAnimation.setKeys(keyFrames);
// nebulaSkyboxMesh.animations = [];
// nebulaSkyboxMesh.animations.push(nebulaVisibilityAnimation);
// const anim = scene.beginAnimation(nebulaSkyboxMesh, 0, 120);
// const test = await anim.waitAsync();
// console.log(test);
const observer = this.scene.onBeforeRenderObservable.add(() => {
console.log(nebulaSkyboxMesh.visibility);
const deltaTime = this.scene.getEngine().getDeltaTime() / 1000;
if (nebulaSkyboxMesh.visibility < 1) {
nebulaSkyboxMesh.visibility += 0.5 * deltaTime;
} else {
nebulaSkyboxMesh.visibility = 1;
this.scene.onBeforeRenderObservable.remove(observer);
}
});
})
.then(() => {
. . .