Any way to forcibly prevent new render frames?

So, I already have autoRender off, but I can’t depend on renderNextFrame staying false while a model is being loaded. Anyone know of a way to forcibly freeze the screen or override renderNextFrame to prevent any rendering for a certain period of time?

I don’t understand what you mean here. Why can’t you depend on it?

There’s code in various locations that will set renderNextFrame to true. But, under certain situations I don’t want any new frames. The ideal solution would be to create a boolean and have those locations all check this boolean to see whether their allowed to set renderNextFrame to true before doing so, just wondering if there’s an easier way to prevent new renders.

idk, maybe there’s a way to set renderNextFrame back to false right before the renderer updates.

You can do some basic reference counter and use a global event.

eg On some script (untested):

this.app.on('render:lock', function() {this.renderLockCount++; this.app.autoRender = false;}, this);
this.app.on('render:unlock', function() {this.renderLockCount--; if(this.renderLockCount === 0){this.app.autoRender = true;}, this);

And for every load request, you can fire render:lock, and when it’s finished loading, fire render:unlock.

1 Like

Hmm, okay. Thanks for the code example. So, the project I’m working in behaves a little bit differently. It’s a product configurator, so autoRender is never used and renderNextFrame is used very frequently for anything that would update the visuals. That’s why I’m in this situation where I have a ton of different places that use renderNextFrame.

I don’t have the full context of your project so these would be the general approach I would take:

  • Only have one place where autoRender is set to true that checks for all conditions
  • Have a list of clear conditions that may be counters on assets still to be loaded, flags that need to be true etc
  • Use global events to update status of each sub system that may prevent a render

TLDR, have these different places that can prevent rendering use events notify a central system so that it can work out whether it should render or not.

1 Like

Thanks @yaustar that definitely sounds like the most optimal solution. Having renderNextFrame everywhere and trying to override it is just turning into a mess, a good refactoring is in order. I appreciate the help.

For anyone coming across this thread with a similar dilema, here’s the end result of what I did.

renderCenter.js script

/*jshint esversion: 6 */
var RenderCenter = pc.createScript('renderCenter');

// initialize code called once per entity
RenderCenter.prototype.initialize = function() {
    // If no blocking assets AND renderRequested, screen will be rendered
    this.renderRequested = false;
    this.blockingAssets = 0;
    // forceRender and forceFreeze OVERRIDE the above behavior (for special situations), if both are true forceFreeze takes precedent
    this.forceRender = false;
    this.forceFreeze = false;
    // --- Events ---------------------------------------------------------------------
    // asset blocking - prevent 'render:requestRender' events from going through when asset is currently loading
    // Call on asset load start when updating visuals is not wanted
    this.app.on('render:block', () => this.blockingAssets++, this);
    // Call on asset load completion; automatically initiates render when no blocking assets are left
    this.app.on('render:unblock', () => { this.blockingAssets--; this.renderRequested = true; }, this);
    // Call on anything that makes a visual update
    this.app.on('render:requestRender', () => this.renderRequested = true, this);
    // For special situations..
    this.app.on('render:forceRender', () => this.forceRender = true, this);
    this.app.on('render:unforceRender', () => this.forceRender = false, this);
    this.app.on('render:forceFreeze', () => this.forceFreeze = true, this);
    this.app.on('render:unforceFreeze', () => this.forceFreeze = false, this);
};

// update code called every frame
RenderCenter.prototype.update = function(dt) {
    if ((this.renderRequested && this.blockingAssets < 1) || (this.forceRender && !this.forceFreeze)) {
        this.app.renderNextFrame = true;
        // Only reset when finally rendered, this way once there are no more blockingAssets, the render goes through
        this.renderRequested = false;
    }
};

Requesting render (ie after a visual like color or position changes)
BEFORE

    // Push frame
    this.app.renderNextFrame = true;

AFTER

    // Request frame
    this.app.fire('render:requestRender');

Asset Blocking (ie prevent the screen from rendering until all models are done loading)
Here’s an example of asset blocking being used. onLoad() cannot be relied on to always be called, so had to use the asset error event to make sure the screen doesn’t get frozen on the very real possibility of an asset load randomly failing.

Forcibly Freezing (used to prevent rendering in situations that weren’t asset-blocking related)
Below is an example where entities were being replaced by disabling one entity and enabling another (had to be done in this order due to iOS Safari WebGL texture count limits). Screen is forcibly frozen while that switch is happening.
image
image

2 Likes