Building a geometry - part 4 - Adding reflection probesnew

After loading a geometry (Building a geometry - part 1 - Loading a source scene), setting up GI and AO data (Building a geometry - part 2 - Setting up a GI cache) and activating lights (Building a geometry - part 3 - Adding lights), it is time to add reflections to the scene.

The reflections in REDart are mainly done using reflection probes set in the scene. These are specific REDart objects and can't be loaded directly from the original source graph. This tutorial will show how to create probes and render environment maps from them.

Creating probes an adding them to the geometry

A reflection probe can be easily created using the RPL::Factory. The RPL::IReflectionProbe interface allows to set several parameters.

A probe is defined by:

Sphere and box reflection probes details

Reflection probes can be of two types: sphere or box. Sphere probes have "infinite" reflections. They are suited for single objects. Box probes are suited for interior room.

RPL::IGeometry* igeometry = g_geometry->As< RPL::IGeometry >();

// Create a first reflection probe in the main room of the first floor.
RED::Object* probe = RPL::Factory::CreateInstance( CID_RPLReflectionProbe );
if( probe == NULL )
  RC_TEST( RED_ALLOC_FAILURE );

RPL::IReflectionProbe* iprobe = probe->As< RPL::IReflectionProbe >();

RED::Matrix transform;
transform.SetTranslation( RED::Vector3( 0.0, -1.0, 1.75 ) );
RED::Vector3 effectMin( -9.0, -3.7, -1.75 );
RED::Vector3 effectMax( 9.6, 4.2, 2.15 );
RED::Vector3 falloffMin( -9.3, -3.74, -1.8 );
RED::Vector3 falloffMax( 9.63, 4.8, 2.2 );
RC_TEST( iprobe->InitializeBox( transform, effectMin, effectMax, falloffMin, falloffMax ) );

RC_TEST( igeometry->AddReflectionProbe( probe ) );

For a house with multiple rooms like in this tutorial, several box probes are placed in each area. The probe is positionned at the center of the room. The size of the box fits the size of the room. The falloff goes through the wall to blend between adjacent rooms at the door positions.

Positions and area of the three reflection probes.

Generating reflection probes maps

Once the probes are created and the areas are set, we need to render and set their environment maps. This can be done with a single call to RPL::IAssetManager::GenerateReflectionProbeMaps.

RED::Vector< RED::Object* > envMaps;
RED::Vector< RED::Object* > envMapsIndex;

RED::Object* probe;
RPL::IReflectionProbe* iprobe;
RED::Object* map;
RED::Object* mapIndex;

// Deactivate all the reflection probes before starting.
// We want only one depth of reflections.
// For multiple depths, call the generate function multiple times with reflections activated.
for( int i = 0; i < count; ++i )
{
  probe = igeometry->GetReflectionProbe( i );
  iprobe = probe->As< RPL::IReflectionProbe >();

  iprobe->SetActive( false );
}

// Generate all the reflection probes.
for( int i = 0; i < count; ++i )
{
  probe = igeometry->GetReflectionProbe( i );
  iprobe = probe->As< RPL::IReflectionProbe >();

  RC_TEST( iassetmgr->GenerateReflectionProbeMaps( map, mapIndex, probe, 1024, false, g_sundir, REDartProgressCB, NULL ) );

  RC_TEST( envMaps.push_back( map ) );
  RC_TEST( envMapsIndex.push_back( mapIndex ) );
}

// Reactivate the reflections.
for( int i = 0; i < count; ++i )
{
  probe = igeometry->GetReflectionProbe( i );
  iprobe = probe->As< RPL::IReflectionProbe >();

  iprobe->SetActive( true );
}

// Setting the reflection maps in the probe object.
for( int i = 0; i < count; ++i )
{
  RED::Object* probe = igeometry->GetReflectionProbe( i );
  RPL::IReflectionProbe* iprobe = probe->As< RPL::IReflectionProbe >();
  RC_TEST( iprobe->SetEnvironmentMap( envMaps[i], envMapsIndex[i] ) );
}

Note:

The RPL::IAssetManager::GenerateReflectionProbeMaps method works on the current state of the world. Please make sure that the geometry is well placed on the planet and the world is running correctly when calling it.

The method returns two maps: an atlas containing multiple reflections for multiple sun positions and the map containing atlas indexing data.

Saving and loading reflection probes maps

Once multiple reflection probes maps have been rendered, we can easily save them into one single file:

// Saving the reflection maps.
if( count > 0 )
{
  RC_TEST( iassetmgr->SaveReflectionProbesMaps( envMaps, envMapsIndex, "../Resources/House_Reflection.red" ) );
}

The loading of the file is as simple as the saving:

// Loading the reflection probes.
RED::Vector< RED::Object* > envMap;
RED::Vector< RED::Object* > envMapAtlas;
RC_TEST( iassetmgr->LoadReflectionProbesMaps( envMap, envMapAtlas, "../Resources/House_Reflection.red" ) );

count = igeometry->GetReflectionProbesCount();

if( count != envMap.size() )
  RC_TEST( RED_FAIL );

// Setting the reflection maps in the probe object.
for( int i = 0; i < count; ++i )
{
  RED::Object* probe = igeometry->GetReflectionProbe( i );
  RPL::IReflectionProbe* iprobe = probe->As< RPL::IReflectionProbe >();
  RC_TEST( iprobe->SetEnvironmentMap( envMap[i], envMapAtlas[i] ) );
}

Each map is finally set to its associated reflection probe object.

Your browser does not support the HTML5 canvas tag.

The house without and with reflections