GI and Animation

Because GI is a view-dependent process in HOOPS Luminate, computing animations with GI can introduce some flickering artefacts (the GI solution is slightly different from frame to frame). Hopefully, HOOPS Luminate comes with several tools to help you in computing high quality animations with GI.

We distinguish between two animation cases: camera animation only and objects animation.

Rendering GI with Moving Camera

When only the camera is moving in the scene, the GI solution is the same for each frame. It’s then safe to compute the GI solution once for the whole scene and then reuse it for each animation frame. This is accomplished by creating a GI cache in RED::GICM_WORLD mode through the RED::IWindow::FrameTracingGICache method.

Computing a World GI Cache

Here is how you can build a world GI cache:

// "win" is a pointer to a RED window.
// "viewpoint" is a pointer to a scene viewpoint.
RED::IWindow* iwin = win->As< RED::IWindow >();

// Publish the latest data modifications.
RC_TEST( iresmgr->EndState() );

// Render the world GI cache.
RED::Object* gi_cache;
RED::Vector< RED::Vector3 > nofilter;
RED::Vector< RED::Object* > noexclude, noblock;
bool complete = false;

while( !complete )
{
    RC_TEST( iwin->FrameTracingGICache( complete, gi_cache, viewpoint, RED::GICM_WORLD, nofilter, noexclude, noblock ) );
}

Note

The last parameter of the call to RED::IWindow::FrameTracingGICache above is an optional pointer to a list of locations in the scene from where the GI cache will be seen. It’s used during the cache creation to concentrate the computation effort on visible parts of the scene and is very helpful to filter parts of the scene which are never visible. It helps producing clean GI caches containing meaningful entries. For example, In the context of computing a cache for a camera animation, this list could include the positions of the camera along the animation path.

The GI cache can be saved on disk in a .red file for reusing it later:

Saving and Loading a GI Cache

GI caches can be directly saved in a .red file:

// "red_file" is a pointer to an already open .red file.
// "gi_cache" is a pointer to an existing GI cache.
RED::IREDFile* ifile = red_file->As< RED::IREDFile >();

RED::StreamingPolicy policy;
RC_TEST( ifile->Write( gi_cache, policy, resmgr ) );

When GI caches are present in a loaded .red file, there are accessible through the RED::IDataManager interface in the Miscellaneous objects section:

// "ctx" is the list of contexts created by loading the .red file.
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();
RED::IDataManager* idatamgr = iresmgr->GetDataManager()->As< RED::IDataManager >();

// In this example, we assume that the GI cache is located in the first context at the first position:
RC_TEST( idatamgr->GetMiscObject( gi_cache, ctx[0], 0 ) );

Once the world GI cache is available, you need to set it back before rendering:

Setting an External GI Cache

To render using a previously computed GI cache:

// "win" is a pointer to a RED window.
// "viewpoint" is a pointer to a scene viewpoint.
// "gi_cache" is a pointer to a previously computed GI cache.
RED::IWindow* iwin = win->As< RED::IWindow >();

RED::Object* vrl;
RC_TEST( iwin->GetDefaultVRL( vrl ) );

RED::IViewpointRenderList* ivrl = vrl->As< RED::IViewpointRenderList >();

RC_TEST( ivrl->SetViewpointGICache( gi_cache, viewpoint, iresmgr->GetState() ) );

Rendering GI with Moving Objects

When not only the camera, but also objects move in the scene, you can’t compute a single GI cache any longer. You need to build a GI cache for every frame in the animation. This may introduce flickering in the GI signal as the estimated GI at the same scene location can vary a little bit from frame to frame. To overcome this, HOOPS Luminate features a way to interpolate the GI over several frames, making the estimated GI more stable.

First, you need to compute all the needed GI caches for your animation (can be one GI cache per frame or simply the number of GI caches needed for the current frame) and save them to the disk.

Then, you can re-use those GI caches to compute each frame of the animation.

Interpolating GI for Flickering-Free Animations

Instead of supplying a single GI cache for rendering, you can pass as many caches as you want to enable GI interpolation:

// "win" is a pointer to a RED window.
// "viewpoint" is a pointer to a scene viewpoint.
RED::IWindow* iwin = win->As< RED::IWindow >();

RED::Object* vrl;
RC_TEST( iwin->GetDefaultVRL( vrl ) );

RED::IViewpointRenderList* ivrl = vrl->As< RED::IViewpointRenderList >();

// gi_caches is a RED vector of GI caches computed using RED::IWindow::FrameTracingGICache.
RC_TEST( ivrl->SetViewpointGICaches( gi_caches, viewpoint, iresmgr->GetState() ) );

The engine uses the same number of past and future GI caches for the interpolation. Hence, when providing n GI caches to the engine, n is necessarily an odd number with the GI cache of the current frame being located at the n/2 index in the vector.

../../../../../_images/bk_re_sw3d_gi_anim_objects.jpg

The current frame is the one in the centre; by setting three GI caches (before, current and next), the GI is interpolated over three frames instead of just using the current one, reducing the GI flickering.

However, this can introduce some artefacts as past or future moves may produce some GI leaks at the current frame.