Is there a way to manually render frames in WebGL?

Unity uses window.requestAnimationFrame() to continuously render the scene, but I’m building a web project where I want to use Unity as a 3D visualizer, in which I want to control the rendering, so that if user does not change the data, the visualizer does not update at all, so that no rendering will be performed in order to save device power. I want to achieve this by manually calling

OnDemandRendering API in Unity is closer to what I want, but not quite, as it still runs the render loop, and still render frames on an interval, even though I can set it to a very low value, I’d still want to have this controllable on the top level, since Unity requesting animation frame may cause my entire web page to continuously re-render.

That’ll have to do though. Unity is a realtime renderer, the only option is to throttle it. Static image renderers exist but may not be as versatile or speedy, typically running on server hardware and returning just the image.

If your player loop (not: render loop) doesn’t “do” much then calling this say 10 times per second shouldn’t be an issue.

I know for instance that the 3d modelling suites can be automated in such a way that they return a 360° image sequence of a product on-demand for the user. This sequence, once generated, gets cached on the server of course so that rendering only occurs when either the product or the rendering process changes.

Of course with such a system comes the limitation that the user can only pan left/right, there’s no “freelook” camera. Meaning you need to know what kind of tradeoffs you are willing to make. To that end, you should trial run each possible solution and measure the things that are important, like CPU usage with OnDemandRendering.

It’ll re-render the contents of the Unity window but it won’t cause your container webpage to redraw unless you program it to do so.

Sorry, but I don’t think you understand the premise of my original question.

Visualization being a general term does not necessarily mean your specific use cases. And, no, I’m not going to render to images and caching them on a server. I’m not sure where that came from.

I have previously successfully did the exact thing on iOS, where I took control of the rendering loop callback by removing the CADisplayLink managed by Unity, and manually calling -[UnityAppController repaintDisplayLink] whenever the native UI side has updated data that requires visualization re-render, thanks to the fact that Unity ships their native shims in source code form. That change is crucial, because even with OnDemandRendering on the Unity side, without any manual code changes on the native side, Unity would still be requesting the screen to refresh at frame rate, even though redraws are skipped on the Unity side per renderFrameInterval, so the CPU cannot rest when the user has no input on the app or does not change the data that would invalidate the visualization. The power consumption level becomes unacceptable for a viewer/editor app that for most of its runtime is sedentary.

Unity being a “realtime renderer” doesn’t really matter here, since user won’t be directly interact with the Unity view itself, so if Player Loop does not have to run, then it shouldn’t run to not prevent the CPU from resting due to unnecessary work.

// This is where Unity re-renders the screen. Copied straight from the Xcode project. 
- (void)repaintDisplayLink
{
    if (!_didResignActive)
    {
        UnityDisplayLinkCallback(_displayLink.timestamp);
        [self repaint];
    }
}

I have examined the JavaScript shims that Unity ships for WebGL player, and I’m not seeing anything similar, hence my question directed to Unity WebGL staff.

Unity utilizes Window.requestAnimationFrame() browser API to sync with the display. This API will cause the browser to prepare a repaint of the webpage content, and how much overhead a call of this wastes when no repaint is actually necessary is entirely up to the browser’s implementations, and I’d assume in worst conditions everything will be repainted, hence the aforementioned power consumption issue.

If you say that by calling Window.requestAnimationFrame(), Unity will not cause the webpage to redraw, then I’d like to see where you get that information from.

Just to give closure on this in case anyone find this interesting:

I chose to continue to use Unity for this project, but somewhat begrudgingly. The convenience of being able to share the same assets and same code through a package in different projects pushed me over the fence, but as I expected, requestAnimationFrame() fires every frame and calls the Unity WASM functions, and once game objects are visible, each animation frame fire uses a not insignificant amount of time per frame, even when the objects are stationary, so the game loop overhead is there.