[SOLVED] Application will stutter in the Intro Animation

Yes, I used tiny cubes with all the materials assigned to them. They just show for the one frame. The other assets I load because they are quite large in geometry and will not cause any performance hit when loaded into the scene at a later time.

image

1 Like

Just thinking that it wouldnā€™t be too hard to write a script that pops a list of materials on the screen for one frame only :thinking:

Probably could do that on a layer on a camera that renders before the main one so that it gets overdrawn?

Well that might work aswell. Unfortunately I am by no means proficient in JS nor PlayCanvas and this is a big learning experience for me rn, so I donā€™t really know how to tackle a script like that, especially with switching rendered cameras.

I may look into the demos and examples at a later date and probably come up with some makeshift solution though :smiley:

Okay uargh Iā€™m the kind of person to say ā€œIā€™ll do it laterā€ but will do it right away anyways :rofl:

Hereā€™s my script I use to render another camera in the first frame and then swapping to my main camera afterwards.

The Prerender-Camera renders the layers world and prerender. All the cubes with the materials are on the layer prerender, which my main camera doesnā€™t render.

@yaustar Maybe you can take a quick look at the script and let me know if you think that this is an appropriate solution.

var Preloader = pc.createScript('preloader');

// initialize code called once per entity
Preloader.prototype.initialize = function() {
    this.activeCamera = this.entity.findByName('CameraPrerender');
    this.loadAssets();
};

Preloader.prototype.setCamera = function (cameraName) {
    // Disable the currently active camera
    this.activeCamera.enabled = false;

    // Enable the newly specified camera
    this.activeCamera = this.entity.findByName(cameraName);
    this.activeCamera.enabled = true;
};

Preloader.prototype.loadAssets = function() {
    var self = this;
    
    // Find all the assets that have been tagged 'level'
    // In this example, they are in the 'assets-to-load' folder
    var assets = this.app.assets.findByTag('material');
    var assetsLoaded = 0;
    var assestTotal = assets.length;
        
    // Callback function when an asset is loaded
    var onAssetReady = function() {
        assetsLoaded += 1;        
        
        // Once we have loaded all the assets
        if (assetsLoaded === assestTotal) {
            self.onAssetsLoaded();
        }        
    };
    
    // Start loading all the assets
    for(var i = 0; i < assets.length; i++) {
        if (assets[i].resource) {
            onAssetReady();
        } else {
            assets[i].ready(onAssetReady);
            this.app.assets.load(assets[i]);
        }
    }
    
    if (!assets.length) {
        this.onAssetsLoaded();
    }    
};

Preloader.prototype.onAssetsLoaded = function() {
    // Display Materials on a seperate layer
    this.setCamera('CameraPrerender');
    this.app.root.findByName('materialprerender').enabled=true;
    this.app.root.findByName('Gelaende').enabled=true;
    this.app.root.findByName('Schriftzug_Neu').enabled=true;
    setTimeout(function(){
        // Swap to main camera and enjoy =)
        this.setCamera('CameraViewer');
        this.app.root.findByName('materialprerender').enabled=false;
        this.app.root.findByName('Gelaende').enabled=false;
        this.app.root.findByName('Schriftzug_Neu').enabled=false;
    }.bind(this), 1);
};

Also hereā€™s a link to the updated public version so anyone can take a look at it at a later date:

Iā€™m personally thinking about doing something more generic but thereā€™s nothing inherently wrong with your solution.

Well if youā€™d like, Iā€™d love to hear what you mean by more generic :smiley:

Other than that, I wanted to say thank you again for the help and your time!

The ideal would be to call a function or an event that passes a list of material assets to show on screen. At which point, it would render tiny little dots in the corner/edge of the screen for frame only.

This way, it can be used in a wider variety of apps like open world streaming metaverses or games.

Oh okay, Iā€™ll look into that ā€œlaterā€.
Didnā€™t know you were able to render material assets themselves.

Iā€™ll update this thread once Iā€™ve figured something out!

Dealing with the shader compilation issue again here. I think there should be an easier way to force compile the shaders for the given set of materials. If we have a specific list of material assets loaded and ready, we should be able to tell the engine ā€œhey, compile the shader using these materials and tell me when you are doneā€. Its a pretty common issue and using single frame setup seems like a hacky workaround for something that should be part of an API.

1 Like

I spoke with @mvaligursky about this before and canā€™t remember if he staid there would be some issue with it due to not knowing fully what shader paths are needed until itā€™s actually in the scene itā€™s going to be used in.

He can probably comment when heā€™s back from OOO

2 Likes

Itā€™s complicated. The generated shader (in case of a StandardMaterial) depends on many additional things which impact the way it gets generated, and those are not known ahead of time. An examples here are:

  • vertex format (we generate different shader if mesh has tangents for example) - so we need to know what mesh is used
  • texture formats - some textures might need decoding (RGBM/RGBE/RGBP) and so we need to know what materials is used
  • global lighting settings / envLighting texture format that needs encoding, mesh instance that specifies lightmaps and similar.

We cannot generate the shader till we know all those (and some more). And so we cannot easily do this ahead of time.

There was a functionality that let you play the game, which collects all ā€˜optionsā€™ the shaders use, and this allowed shaders to be precompiled if used. This was never functioning really well and this is temporarily not supported - even though I plan to add support for something similar in the future.

Iā€™ve started splitting the rendering into two passes - first that walks over the primitives and triggers shader compilation - so that all shaders compile in parallel. But so far this is done per render pass, and not globally. Iā€™m planning to make this global at some point (maybe), and at this point we might have an API that only triggers shader compilation, without the rendering. But none of this is simple to do at all.

4 Likes