Creating Render Passes

Render passes define what kind of lighting data should be baked for a set of linked targets.

Types of render passes

Beast offers several different types of render passes, described in the following sections. Each of these types is pre-set to bake a different kind of information about the way its linked targets are lit.

Each type of pass is created by calling a different API function. For some passes, you can further configure the type of data produced by setting parameter values in the function you call to initialize the pass, or by calling additional API functions. These functions are all listed in the following sections.

In addition, different numbers of data channels may be used for the different passes to store the final output data of the pass in the framebuffer or vertexbuffer generated by the rendering job. Each section below indicates the number of output channels generated by each pass, and the significance of those channels.

Full shading pass

The full shading pass bakes the fully rendered appearance of the mesh instance, including the diffuse channel of its material, lighting contributions, shadows, etc.

To create a full shading pass, call the ILBCreateFullShadingPass() function.

Output. The full shading pass creates five channels for each pixel in the output framebuffer or each vertex in the output vertexbuffer:

(RGBA)Z

where Z represents the depth channel.

Illumination pass

The illumination pass bakes only the effects of the lighting on each instance, not including the diffuse color or texture of its material. This allows you to create textures or vertex data that reflect only the effect of the incoming light that hits each instance. You can blend this data at runtime with the color texture of the mesh.

To create an illumination pass, call the ILBCreateIlluminationPass() function.

  • In your call to ILBCreateIlluminationPass(), you need to provide an element from the ILBIlluminationMode enumeration to indicate what type of light contributions should be baked: direct light only (ILB_IM_DIRECT_ONLY), indirect light only (ILB_IM_INDIRECT_ONLY), all incoming light (ILB_IM_FULL), or both full lighting and indirect lighting separately (ILB_IM_FULL_AND_INDIRECT).

    The ILB_IM_FULL_AND_INDIRECT option produces the same output as both ILB_IM_FULL and ILB_IM_INDIRECT_ONLY, combined in a single pass. This could be useful if you want to do real-time direct lighting for objects close to the camera and blend to fully baked lightmaps for more distant geometry. You would then apply the indirect lighting values to the nearby objects, the full lighting values to the distant objects, and interpolate or switch between those values based on the distance of the geometry. If you choose this approach, you can also call ILBAddFullyBakedLight() to make the illumination pass write the full light contribution (direct and indirect) for a specified light source to both the full and indirect-only outputs.

Output. For ILB_IM_DIRECT_ONLY, ILB_IM_INDIRECT_ONLY and ILB_IM_FULL, the illumination pass creates five channels for each pixel in the output framebuffer, or each vertex in the output vertexbuffer:

(RGBA)Z

where Z represents the depth channel.

For ILB_IM_FULL_AND_INDIRECT, the illumination pass creates seven channels for each pixel in the output framebuffer, or each vertex in the output vertexbuffer:

(RGB)i(RGB)fZ

where:

  • RGBi represents the indirect-only lighting.
  • RGBf represents the full lighting (direct and indirect combined).
  • Z represents the depth channel.

Spherical Harmonics illumination pass

For point cloud targets, you can use a type of illumination pass that uses Spherical Harmonics to integrate the illumination around each point in the cloud.

To create this kind of illumination pass, call the ILBCreateIlluminationPassSH() function. It accepts the same arguments as the ILBCreateIlluminationPass() function described above.

Output. Three spherical harmonic bands are computed, which produces nine coefficients for each color channel. There are therefore 27 channels for each vertex (i.e. each point cloud point) in the output vertexbuffer:

(R0 ... R8, G0 ... G8, B0 ... B8)

Radiosity Normal Map (RNM) pass

The RNM pass creates radiosity normal maps, also known as directional light maps. In this lighting technique, each shaded fragment records the light incoming from three different directions that deviate from the normal of the fragment. These deviations, which are always orthogonal to each other, are known as the RNM bases. The incoming light values along each basis are stored separately. At runtime, these values can be interpolated and blended with a normal map or bump map that provides details of the surface texture of the mesh. This greatly increases the realism and believability of the final texture.

For example, if a red light is shining on a wall from the left, and a blue light is shining from the right, a bump in the middle of the wall should be shaded red on the left and blue on the right. Using the RNM technique, the lighting color to be applied to each point on the mesh is determined by taking the normal from the corresponding point in the normal map, and interpolating the incoming directional light values in the RNM maps to determine what color of light shines along that normal.

Note that in order to use the RNM pass to render a target, you must have provided tangents and bitangents for each triangle in the mesh at the time you created that mesh. See also Creating Meshes.

To create an RNM pass, call the ILBCreateRNMPass() function.

  • In your call to ILBCreateRNMPass(), you also need to provide an element from the ILBRNMBasis enumeration to indicate the alignment of the RNM basis vectors: the alignment used in Half-Life 2 (ILB_RB_HL2), the alignment used in the Unreal Engine (ILB_RB_UE3), the alignment used in Unreal in untouched order (ILB_RB_UE3_FLIPPED) or custom (ILB_RB_CUSTOM). Define custom basis vectors with a series of calls to ILBAddCustomBasisVector(), this allows you to use more basis vectors than 3 for directional lightmaps.
  • You also need to specify the number of samples to use for indirect light calculations.

    If you set this value to 0, an adaptive sampling method is used, based on a final gather with a radiance cache. In this case, the settings for the number of samples and the number of light bounces are taken from the Final Gather settings in the XML configuration file you provide for the rendering job. See also Final Gather Settings. This approach is recommended for most projects.

  • You also need to provide an element from the ILBRNMBasis enumeration to indicate the alignment of the RNM basis vectors: the alignment used in Half-Life 2 (ILB_RB_HL2), the alignment used in the Unreal Engine (ILB_RB_UE3), the alignment used in Unreal in untouched order (ILB_RB_UE3_FLIPPED), or a custom set of bases (ILB_RB_CUSTOM) that you specify in calls to ILBAddCustomBasisVector().

You can also use the following API functions to configure the RNM pass. See the function descriptions for details.

  • ILBSetLambertianClamp(): Determines whether or not the result of the pass is scaled so that the sum of the lambertian shading values of the directional components equals a clamp value.
  • ILBSetAllowNegative(): Determines whether or not the directional components can include negative coefficients and light contributions that come from below the plane of the surface.
  • ILBIncludeNormalComponent(): Determines whether or not the lighting contribution along the direction of the normal is also computed and output along with the three RNM bases.
  • ILBRNMMatchNormalIntensity(): Determines whether or not the intensity of the lighting values along the RNM bases are scaled to match the intensity along the normal.
  • ILBAddCustomBasisVector(): When using the ILB_RB_CUSTOM basis mode, this function allows you to specify a basis vector for the RNM pass. Note that your basis vectors should always be orthogonal to each other.

Output. The RNM pass creates 4 channels for each basis vector, plus 4 channels for the normal component if it is included. If you use any of the built-in bases in the ILBRNMBasis enumeration (ILB_RB_HL2, ILB_RB_UE3 or ILB_RB_UE3_FLIPPED), this produces 13 values (or 17 if the normal is included):

(RGBA)1(RGBA)2(RGBA)3(RGBA)nZ

where:

  • RGBA1 to RGBA3 represent the RGBA values for the three directions in the RNM basis.
  • RGBAn represents the RGBA values for the normal component, if included.
  • Z represents the depth channel.

If you a custom basis for your RNM pass, the number of coefficients depends on the number of basis vectors you add. You will get a set of RGBA values for each basis, plus a set of RGB values for the normal (if included), plus a value for the depth channel.

Light pass

The light pass is typically used to bake lighting data for a selected set of target instances lit by a selected set of lights in the scene.

To create a light pass, call the ILBCreateLightPass() function.

Once you have created the light pass, you need to create one or more light pass entries: objects that associate light sources in your scene with the target entities that they will apply to. Entries are created by calling ILBCreateLightPassEntry(); light sources and target entities are added by calling ILBAddLightToPass() and ILBAddTargetToPass(). (This function should not be confused with ILBAddPassToTarget(), which may be similar in name but is very different in effect.)

ILBRenderPassHandle lightPass;
ILBCreateLightPass(job, "LightPass", ILB_LP_SHADOWMAP, &lightPass);
ILBLightPassEntry lpEntry1, lpEntry2;
ILBCreateLightPassEntry(lightPass, &lpEntry1);
ILBAddTargetToPass(lpEntry1, targetEntity1);
ILBAddLightToPass(lpEntry1, lightA);
ILBCreateLightPassEntry(lightPass, &lpEntry2);
ILBAddTargetToPass(lpEntry2, targetEntity2);
ILBAddLightToPass(lpEntry2, lightB);
ILBAddLightToPass(lpEntry2, lightC);

You can also use the following API functions to configure the light pass. See the function descriptions for details.

  • If you use the ILB_LP_LIGHTMAP type of light pass, you can set the amount of lambertian reflectance to be weighted into the final result by calling ILBSetLambertianScale().
  • If you use the ILB_LP_SHADOWMAP type of light pass, you can call ILBEnableSignedDistanceField() to enable an additional rendering mode that stores for each pixel the distance to the closest shadow transition.
    NOTE:This option is available only when using "classic" materials, not physical materials.

Output. The light pass creates five channels for each pixel in the output framebuffer or each vertex in the output vertexbuffer:

(RGBA)Z

where Z represents the depth channel.

Ambient occlusion pass

Ambient occlusion is a representation of the proximity of other light-occluding bodies to each baked pixel. It creates a lightmap that represents the way the ambient (or directionless) light on each object is occluded by surrounding physical objects. You can use these ambient occlusion maps to give additional detail to your shadows.

To create an ambient occlusion pass, call the ILBCreateAmbientOcclusionPass() function.

You can also use the following API functions to configure the ambient occlusion pass. See the function descriptions for details.

  • ILBSetAOAdaptive(): Configures the pass to use adaptive sampling, which typically increases rendering speed dramatically.
    NOTE:This option is available only when using "classic" materials, not physical materials.
  • ILBSetAONumRays(): Sets the minimum and maximum number of rays that will be sent from each point in order to find occluding objects.
    NOTE:This option is available only when using "classic" materials, not physical materials.
  • ILBSetAOContrast(): Sets the contrast and scale of the lighting values in the ambient occlusion map.
  • ILBSetAOUniformSampling(): By default, occlusion samples are cosine-weighted. This function changes the sampling to be uniform instead.
  • ILBSetAOSelfOcclusion(): Determines how the pass handles self-occlusion. By default, self-occlusion is detected and reflected in the occlusion map just like any other occluding object.
  • ILBEnableAOBentNormals(): Configures the pass to generate bent normals: the direction of least occlusion from each sampled point.
    NOTE:This option is available only when using "classic" materials, not physical materials.

"Classic" materials only. Note that the ambient occlusion pass is not supported by the physically based rendering system. If you want to use the ambient occlusion pass, you need to create your scene with the "classic" material system. See Creating Classic Materials.

Output. The ambient occlusion pass creates five channels for each pixel in the output framebuffer or each vertex in the output vertexbuffer:

(RGBA)Z

where Z represents the depth channel.

Note that if you use ILBEnableAOBentNormals(), the RGB channels will instead store the X, Y and Z orientations of the bent normal in world space. The bent normal is normalized and mapped from the [-1..1] range to the [0..1] range.

Lua pass

The Lua pass allows you to customize the way lighting values are generated for each sampled point by providing your own Lua script that Beast will call to bake the lighting information.

To create a Lua pass, call the ILBCreateLuaPass() function. In your call, you need to provide the Lua script that Beast will call to generate the output values for each sampled point. For details on the structure and requirements of this script, see Lua Reference.

Output. The Lua pass does not create a fixed number of output channels. The number of channels created for each pixel in the output framebuffer or each vertex in the output vertexbuffer depends on your implementation of the Lua baking script.

Physical material limitations. Note that the Lua pass does not support dynamic types of illumination or radiance cacheing when used with physical materials (see the gather.sampletype and gather.useRadianceCache functions in the Lua Reference).

Setting up a render pass

You set up render passes in the context of setting up and running a rendering job. For more information about how to set up a render pass in the overall context of rendering a scene, see Rendering the Scene.

To set up a render pass:

  1. Create a new ILBRenderPassHandle.
  2. Initialize and configure the handle according to the type of lighting data you want to bake. See the functions listed for the different types of render passes listed under Creating Render Passes above.
  3. In order for your pass to be carried out in a rendering job, you need to assign it to at least one target in the same job by calling ILBAddPassToTarget().

For example:

ILBRenderPassHandle illuminationPass;
ILBCreateFullShadingPass(job, "illumPass", ILB_IM_FULL, &illuminationPass);
ILBAddPassToTarget(myTextureTarget, illuminationPass);

Related API functions

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