Rendering the Scene

Once you have created a scene and populated it with all the mesh instances, light sources, etc. that exist in your game world, you need to carry out a rendering job to create the final lighting data for that scene. This page provides an overview of the concepts and procedures involved in setting up and carrying out a rendering job.

About jobs, targets and passes

Rendering involves three principal types of objects:

Rendering workflows and job types

Beast offers you the choice of three very different workflows for rendering your scene. Each of these workflows is reflected by its own kind of rendering job.

Simple rendering

You can carry out a straighforward rendering job that simply bakes the lighting data for the scene as you have created it. This type of job terminates automatically when all passes have been rendered for all targets.

To create a simple rendering job, call the ILBCreateJob() function. When you call this function, you need to provide an XML file that configures a variety of settings about the algorithms that will be used in the rendering, the way instances are sampled, etc.

  • If you use physical materials in your scene, most configuration is done through the functions in the Beast API. Fewer settings are read from the XML configuration. In many cases, unless you need to set a specific set of parameters for your project, you can simply pass an empty string to ILBCreateJob() in order to use all default values.
  • If you use "classic" Beast materials in your scene, you will probably want to set at least a few important parameters in this XML configuration to control the type of global illumination algorithms used. For a sample configuration that contains some of the most important settings, see Sample XML Configuration File for Classic Material Rendering.

For a detailed reference that contains all available settings, see XML Reference.

Standalone eRnsT

You can create a rendering job that launches the standalone eRnsT viewer to give your artists an interactive preview of the lighting in your scene. The job will continue to run until you explicitly destroy it, or until the user closes the eRnsT viewer. As long as the job continues to run, the eRnsT viewer will show the contents of your scene. Your artists will be able to change the lighting in the scene and tweak other Beast configuration parameters. You can retrieve the changes they make in your code, and update your game level accordingly.

For details on how to use the standalone eRnsT viewer, see also Using the eRnsT Viewer.

To create an eRnsT job, call the ILBCreateErnstJob() function. When you call this function, you need to provide an XML file that configures a variety of settings about the global illumination algorithms that will be used in the rendering, the way instances are sampled, etc. For a sample configuration that contains some of the most important settings, see Sample XML Configuration File for Classic Material Rendering. For a detailed reference that contains all available settings, see XML Reference.

Note that some restrictions apply to standalone eRnsT jobs:

  • Only texture targets, atlased texture targets and vertex targets are supported.
  • Point clouds are not supported.
  • Standalone eRnsT jobs do not make use of render passes at all. The eRnsT viewer allows you to view the scene fully shaded, with lighting only, or with unlit materials. For physically based rendering in baking mode, illumination only is the only supported mode.

Live eRnsT

You can create a rendering job that integrates the eRnsT real-time rendering engine directly into your own level editor, to give your artists immediate feedback on the changes they make. As the rendering job is carried out, Beastprovides you with progressive updates of rendered data for the targets you have created. You can retrieve the updated data in your code, and use it to update a render view or the textures and lighting data you display in your level editor. See the Maya plug-in for a live workflow example.

During a live eRnsT session, your Beast scene is completely editable. If your designers make a change in the level editor, such as adding or removing a light or object in the level, you can change the light sources and mesh instances contained in your Beast scene to reflect the changes made in the level editor. Beast will automatically determine when the targets in your scene need to be re-baked.

  • The only exception to this is if you use "classic" materials. In a scene with physical materials, all aspects of the scene can be modified on the fly, including the parameter values used by the shaders. In a scene with "classic" materials, the materials and their parameters cannot be altered after the materials are created.

To create a live eRnsT job, call the ILBCreateLiveErnstJob() function. This function does not accept an XML configuration file like the other kinds of rendering jobs. Instead, you can configure the job by calling a set of functions provided by the Beast API:

Update types

The type of updates you receive from a live eRnsT job depend on the type of targets you create in the scene:

  • If your scene does not contain a camera target, eRnsT will provide you with progressive updates for each texture target or vertex target in the scene. These updates begin with low-fidelity approximate renderings, and gradually improve in resolution as the eRnsT job continues to render the scene in the background.
  • If your scene does contain a camera target, eRnsT will provide you with updated renderings of that camera's point of view. It will no longer provide you with updated light maps for your texture and vertex targets.

    If you choose to retrieve renderings of the scene from a camera target, you can choose how those renderings should be created by calling the ILBCameraTargetSetRenderMode() function, and passing a value from the ILBCameraRenderModeType enumeration. You can retrieve fully shaded per-pixel renderings (ILB_LEC_CAMERA_PER_PIXEL_LIGHTING); in this case, the texture targets and vertex targets in the scene are not used at all. Alternatively, you can have the eRnsT job calculate lightmaps for the texture targets and vertex targets in the scene, refining them progressively with more details, and create the camera renderings based on those lightmaps (ILB_LEC_CAMERA_LIGHT_MAP_LIGHTING).

Restrictions

Note that some restrictions apply to live eRnsT jobs:

  • Atlased texture targets are not supported.
  • Point clouds are not supported.
  • Live eRnsT jobs do not make use of render passes at all. The lightmaps generated always contain the lighting only.

Physical render settings

The Beast API provides two functions that you can use to control the quality of the rendering.

The first controls the quality using a single parameter, similar to a JPEG quality setting:

The other option gives more detailed control over sample quantity and variance:

ILBSetJobRenderSamples(ILBJobHandle job, int minSamples, int maxSamples, float varianceThreshold);

In addition, you can also control physical rendering using the following eRnsT API functions, which provide control over the artistic qualities of the rendering:

ILBSetErnstGIDepth(ILBJobHandle job, int minDepth, int maxDepth);
ILBSetErnstGIDiffuseBoost(ILBJobHandle job, float boost);
ILBSetErnstGIEmissiveScale(ILBJobHandle job, float scale);

To render a scene

Regardless of the rendering workflow you choose to use, the process of setting up and running a rendering job always involves the same basic steps:

  1. Create a new ILBJobHandle, and initialize it according to the rendering workflow you want to use. See Rendering the Scene above.
  2. Create your render targets, which determine the type of output you want to create: texture lightmaps, vertex lighting, a still image, etc. For details, see Creating Render Targets.
  3. Add bake instances to your targets, to specify the objects in your scene for which the output data will be created. For details, see Creating Render Targets.
  4. Create your render passes, which determine what kind of information you want to render. For details, see Creating Render Passes. Note that passes are not used for eRnsT jobs.
  5. Associate each pass to one or more targets by calling ILBAddPassToTarget() as many times as necessary. Note that not all types of targets accept all types of render passes. For details, see Creating Render Targets.
  6. Launch the job. For details, see Launching Jobs.
  7. Monitor the progress and status of the job. For simple rendering jobs, the only update you get is when the job is over, though you can query the progress and state of the job at any time. Standalone eRnsT jobs and live eRnsT jobs periodically generate updates that your code may need to respond to. For details, see Monitoring Jobs and Retrieving Updates.
  8. When the job is finished, retrieve the final data generated for each target/pass combination. For details, see Retrieving the Rendered Output. After you have retrieved the data, you can destroy the job by calling ILBDestroyJob() to free the memory used by the job and its output. Don't destroy the job before you retrieve its data, because all framebuffers will be cleared automatically.

For example, the following code demonstrates how to set up and launch a simple rendering job:

std::string xmlFileName = "../../data/settings.xml";

// 1. Create the job.
ILBJobHandle job;
ILBCreateJob(bmh, _T("TestJob"), scene, xmlFileName.c_str(), &job);

// 2. Create render targets.
ILBTargetHandle cameraTarget;
ILBCreateCameraTarget(job, _T("cameraTarget"), camera, 640, 480, &cameraTarget);
ILBTargetHandle textureTarget;
ILBCreateTextureTarget(job, _T("textureTarget"), 512, 512, &textureTarget);

// 3. Add the floor instance to the texture target.
ILBTargetEntityHandle entity;
ILBAddBakeInstance(textureTarget, floorInstance, &entity);

// 4. Create a render pass.
ILBRenderPassHandle fullShadingPass;
ILBCreateFullShadingPass(job, _T("fullShading"), &fullShadingPass);

// 5. Add the render pass to the targets.
ILBAddPassToTarget(textureTarget, fullShadingPass);
ILBAddPassToTarget(cameraTarget, fullShadingPass);

// 6. Launch the job.
ILBStartJob(job, ILB_SR_KEEP_OPEN, ILB_RD_FORCE_LOCAL);

// 7. Monitor the job and get progress updates.
ILBBool isRunning = true;
ILBBool completed = false;
int32 oldProgress = 0;
while (isRunning) {
    ILBWaitJobDone(job, 0xffffffff);
    ILBIsJobRunning(job, &isRunning);
    if (isRunning) {
        ILBBool newProgress;
        ILBBool newActivity;
        ILBJobHasNewProgress(job, &newActivity, &newProgress);
        if (newProgress) {
            ILBStringHandle taskName;
            int32 progress;
            ILBGetJobProgress(job, &taskName, &progress);
            // Handle progress update.
            oldProgress = progress;
        }
    }
}

// Handle the result of the job.
ILBJobStatus status;
ILBGetJobResult(job, &status);
if (status != ILB_JS_SUCCESS) {
    switch(status) {
        ...
    }
    return false;
}

// 8. Retrieve baked output.
...

// 9. Destroy the job.
ILBDestroyJob(job);

Related API functions

API functions related to the creation and setup of render jobs are declared in the beastjob.h file.