OGRE  1.12.13
Object-Oriented Graphics Rendering Engine
Compositor Scripts

The compositor framework is a subsection of the OGRE API that allows you to easily define how to assemble the final image. A typical use-case are full screen post-processing effects - however Compositors are not limited to that. Compositor scripts offer you the ability to define rendering pipelines in a script which can be reused and modified easily, rather than having to use the API to define them. You still need to use code to instantiate a compositor against one of your visible viewports, but this is a much simpler process than actually defining the compositor itself.

Compositor Fundamentals

Compositing generally involves rendering the scene to a texture, either in addition to or instead of the main window. Once the scene is in a texture, you can then pull the scene image into a fragment program and perform operations on it by rendering it through full screen quad. The target of this post processing render can be the main result (e.g. a window), or it can be another render texture so that you can perform multi-stage convolutions on the image. You can even ’ping-pong’ the render back and forth between a couple of render textures to perform convolutions which require many iterations, without using a separate texture for each stage. Eventually you’ll want to render the result to the final output, which you do with a full screen quad. This might replace the whole window (thus the main window doesn’t need to render the scene itself), or it might be a combinational effect.

So that we can discuss how to implement these techniques efficiently, a number of definitions are required:

Compositor

Definition of a rendering pipeline that can be applied to a user viewport. This is what you’re defining when writing compositor scripts as detailed in this section.

Compositor Instance

An instance of a compositor as applied to a single viewport. You create these based on compositor definitions, See Applying a Compositor.

Compositor Chain

It is possible to enable more than one compositor instance on a viewport at the same time, with one compositor taking the results of the previous one as input. This is known as a compositor chain. Every viewport which has at least one compositor attached to it has a compositor chain. See Applying a Compositor

Target

This is a Ogre::RenderTarget, i.e. the canvas where the result of a series of render operations is sent. A target may be the final output (e.g. your Ogre::RenderWindow), or it may be an intermediate render texture, which you declare in your script with the texture line. A target which is not the output target has a size and pixel format which you can define inside the compositor script.

Output Target

As Target, but this is the single final result of all operations. The size and pixel format of this target cannot be controlled by the compositor since it is defined by the application using it, thus you don’t declare it in your script. However, you do declare a Target Section for it, see below.

Target Section

A Target may be rendered to many times in the course of a composition effect. In particular if you ’ping pong’ a convolution between a couple of textures, you will have more than one Target Sections per Target. Target Sections are declared in the script using a target or target_output line, the latter being the final output of which there can be only one.

Note
Internally this is referred to as Ogre::CompositionTargetPass
Pass

Within a Target Section, there are one or more individual Passes, which perform a very specific action, such as rendering the original scene (or pulling the result from the previous compositor in the chain), rendering a fullscreen quad, or clearing one or more buffers. Typically within a single target section you will use the either a render_scene pass or a render_quad pass, not both. Clear can be used with either type.

// Black and white effect
compositor B&W
{
technique
{
// Temporary textures
texture rt0 target_width target_height PF_BYTE_RGBA
target rt0
{
// Render output from previous compositor (or original scene)
input previous
}
target_output
{
// Start with clear output
input none
// Draw a fullscreen quad with the black and white image
pass render_quad
{
// Renders a fullscreen quad with a material
material Ogre/Compositor/BlackAndWhite
input 0 rt0
}
}
}
}

The major components of a compositor are the Techniques, the Target Sections and the Passes, which are covered in detail in the following sections.

Techniques

A compositor technique is much like a material technique in that it describes one approach to achieving the effect you’re looking for. A compositor definition can have more than one technique if you wish to provide some fallback should the hardware not support the technique you’d prefer to use. Techniques are evaluated for hardware support based on 2 things:

Material support

All Passes that render a fullscreen quad use a material; for the technique to be supported, all of the materials referenced must have at least one supported material technique. If they don’t, the compositor technique is marked as unsupported and won’t be used.

Texture format support

This one is slightly more complicated. When you request a texture) in your technique, you request a pixel format. Not all formats are natively supported by hardware, especially the floating point formats. However, in this case the hardware will typically downgrade the texture format requested to one that the hardware does support - with compositor effects though, you might want to use a different approach if this is the case. So, when evaluating techniques, the compositor will first look for native support for the exact pixel format you’ve asked for, and will skip onto the next technique if it is not supported, thus allowing you to define other techniques with simpler pixel formats which use a different approach. If it doesn’t find any techniques which are natively supported, it tries again, this time allowing the hardware to downgrade the texture format and thus should find at least some support for what you’ve asked for.

As with material techniques, compositor techniques are evaluated in the order you define them in the script, so techniques declared first are preferred over those declared later.

Format: technique { }

Techniques can have the following nested elements:

texture

This declares a render texture for use in subsequent Target Sections.

Format: texture <name> <width> <height> <PixelFormat> [<MRT Pixel_Format2>] [<MRT Pixel_FormatN>] [pooled] [gamma] [no_fsaa] [depth_pool <poolId>] [<scope>] [<cubic>]
Parameters
nameA name to give the render texture, which must be unique within this compositor. This name is used to reference the texture in Target Sections, when the texture is rendered to, and in Passes, when the texture is used as input to a material rendering a fullscreen quad.
width
heightThe dimensions of the render texture. You can either specify a fixed width and height, or you can request that the texture is based on the physical dimensions of the viewport to which the compositor is attached. The options for the latter are either of
  • target_width and target_height
  • target_width_scaled <factor> and target_height_scaled <factor>
where <factor> is the amount by which you wish to multiply the size of the main target to derive the dimensions.
PixelFormatThe Ogre::PixelFormat of the render texture. This affects how much memory it will take, what colour channels will be available, and what precision you will have within those channels. You can in fact repeat this element if you wish. If you do so, that means that this render texture becomes a Multiple Render Target (MRT), when the GPU writes to multiple textures at once. If you use a depth format here, the texture will be used as the depth attachment instead of the depth-buffer. Use the MRT format to specify both the depth and the colour attachments.
pooledIf present, this directive makes this texture ’pooled’ among compositor instances, which can save some memory.
gammaIf present, this directive means that sRGB gamma correction will be enabled on writes to this texture. You should remember to include the opposite sRGB conversion when you read this texture back in another material, such as a quad. This option will automatically enabled if you use a render_scene pass on this texture and the viewport on which the compositor is based has sRGB write support enabled.
no_fsaaIf present, this directive disables the use of anti-aliasing on this texture. FSAA is only used if this texture is subject to a render_scene pass and FSAA was enabled on the original viewport on which this compositor is based; this option allows you to override it and disable the FSAA if you wish.
depth_poolWhen present, this directive has to be followed by an integer. This directive is unrelated to the "pooled" directive. This one sets from which Depth buffer pool the depth buffer will be chosen from. All RTs from all compositors (including render windows if the render system API allows it) with the same pool ID share the same depth buffers (following the rules of the current render system APIs, (check RenderSystemCapabilities flags to find the rules). When the pool ID is 0, no depth buffer is used. This can be helpful for passes that don’t require a Depth buffer at all, potentially saving performance and memory. Default value is 1. Ignored with depth pixel formats.
scopeIf present, this directive sets the scope for the texture for being accessed by other compositors using the texture_ref directive. There are three options :
  1. local_scope (which is also the default) means that only the compositor defining the texture can access it.
  2. chain_scope means that the compositors after this compositor in the chain can reference its textures, and
  3. global_scope means that the entire application can access the texture. This directive also affects the creation of the textures (global textures are created once and thus can’t be used with the pooled directive, and can’t rely on viewport size).
cubicThis texture is of type Ogre::TEX_TYPE_CUBE_MAP - i.e. made up of 6 2D textures which are pasted around the inside of a cube.
Example: texture rt0 512 512 PF_R8G8B8A8
Example: texture rt1 target_width target_height PF_FLOAT32_RGB
Example : texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope
Note
It is imperative that if you use MRT that the shaders that render to it render to ALL the targets. Not doing so can cause undefined results. It is also important to note that although you can use different pixel formats for each target in a MRT, each one should have the same total bit depth since most cards do not support independent bit depths. If you try to use this feature on cards that do not support the number of MRTs you’ve asked for, the technique will be skipped (so you ought to write a fallback technique).

texture_ref

This declares a reference of a texture from another compositor to be used in this compositor.

Format: texture_ref <Local_Name> <Reference_Compositor> <Reference_Texture_Name>
Parameters
Local_NameA name to give the referenced texture, which must be unique within this compositor. This name is used to reference the texture in Target Sections, when the texture is rendered to, and in Passes, when the texture is used as input to a material rendering a fullscreen quad.
Reference_CompositorThe name of the compositor that we are referencing a texture from
Reference_Texture_NameThe name of the texture in the compositor that we are referencing

Make sure that the texture being referenced is scoped accordingly (either chain or global scope) and placed accordingly during chain creation (if referencing a chain-scoped texture, the compositor must be present in the chain and placed before the compositor referencing it).

Example : texture_ref GBuffer GBufferCompositor mrt_output

scheme

This gives a compositor technique a scheme name, allowing you to manually switch between different techniques for this compositor when instantiated on a viewport by calling Ogre::CompositorInstance::setScheme.

Format: scheme <Name>

compositor_logic

This connects between a compositor and code that it requires in order to function correctly. When an instance of this compositor will be created, the compositor logic will be notified and will have the chance to prepare the compositor’s operation (for example, adding a listener).

Format: compositor_logic <Name>

Registration of compositor logics is done by name through Ogre::CompositorManager::registerCompositorLogic.

Target Sections

A target section defines the rendering of either a render texture or the final output. You can update the same target multiple times by adding more than one target section to your compositor script - this is very useful for ’ping pong’ renders between a couple of render textures to perform complex convolutions that cannot be done in a single render, such as blurring.

There are two types of target sections, the sort that updates a render texture

Format: target <Name> [<slice>] { }

and the sort that defines the final output render

Format: target_output { }

The contents of both are identical, the only real difference is that you can only have a single target_output entry, whilst you can have many target entries.

Note, the target entry can refer to Cube map textures. Therefore, it takes an optional decimal slice parameter that specifies which face you want to render on. The default is 0, hence +X.

Here are the attributes you can use in a ’target’ or ’target_output’ section of a .compositor script:

input

Sets input mode of the target, which tells the target pass what is pulled in before any of its own passes are rendered.

Format: input (none | previous)
Default: input none
Parameters
noneThe target will have nothing as input, all the contents of the target must be generated using its own passes. Note this does not mean the target will be empty, just no data will be pulled in. For it to truly be blank you’d need a ’clear’ pass within this target.
previousThe target will pull in the previous contents of the viewport. This will be either the original scene if this is the first compositor in the chain, or it will be the output from the previous compositor in the chain if the viewport has multiple compositors enabled.

only_initial

If set to on, this target pass will only execute once initially after the effect has been enabled. This could be useful to perform once-off renders, after which the static contents are used by the rest of the compositor.

Format: only_initial (on | off)
Default: only_initial off

visibility_mask

Sets the visibility mask for any render_scene passes performed in this target pass. This is a bitmask (specified as decimal or hex) and maps to Ogre::Viewport::setVisibilityMask.

Format: visibility_mask <mask>
Default: visibility_mask 0xFFFFFFFF

lod_bias

Set the scene LOD bias for any render_scene passes performed in this target pass. The default is 1.0, everything below that means lower quality, higher means higher quality.

Format: lod_bias <lodbias>
Default: lod_bias 1.0

shadows

Sets whether shadows should be rendered during any render_scene pass performed in this target pass.

Format: shadows (on | off)
Default: shadows on

material_scheme

If set, indicates the material scheme to use for any render_scene pass. Useful for performing special-case rendering effects.

Format: material_scheme <scheme name>
Default: None

Passes

A pass is a single rendering action to be performed in a target section.

Format: pass <type> [custom name] { }

There are the following types of a pass:

clear

This kind of pass sets the contents of one or more buffers in the target to a fixed value. So this could clear the colour buffer to a fixed colour, set the depth buffer to a certain set of contents, fill the stencil buffer with a value, or any combination of the above.

stencil

This kind of pass configures stencil operations for the subsequent passes. It can set the stencil compare function, operations and reference values for you to perform your own stencil effects.

render_scene

This kind of pass performs a regular rendering of the scene. It will use the visibility_mask, lod_bias, and material_scheme from the parent target pass.

render_quad

This kind of pass renders a quad over the entire render target, using a given material. You will undoubtedly want to pull in the results of other target passes into this operation to perform fullscreen effects.

compute

This kind of a pass dispatches a compute shader as attached to the given material. Compute shaders are independent from normal rendering pipeline as triggered by render_scene or render_quad. They do not have any predefined input/ outputs but rather read/ write to any buffers you attach to them.

render_custom

This kind of pass is just a callback to user code for the composition pass specified in the custom name (and registered via Ogre::CompositorManager::registerCustomCompositionPass) and allows the user to create custom render operations for more advanced effects. This is the only pass type that requires the custom name parameter.

render_quad & compute

Here are the attributes you can use in the render_quad and compute sections of a .compositor script:

material

Sets the material to be used. With compute passes only the compute shader is used and only global auto parameter can be accessed. For render_quad you will want to use shaders in this material to perform fullscreen effects, and use the input attribute to map other texture targets into the texture bindings needed by this material.

Format: material <Name>

input

This is how you map one or more local texture into the material you’re using to render. To bind more than one texture, repeat this attribute with different texUnit indices.

Format: input <texUnit> <name> [<mrtIndex>]
Parameters
texUnitThe index of the target texture unit, must be a number in the range [0, OGRE_MAX_TEXTURE_LAYERS-1].
nameThe name of the local render texture to bind, as declared by texture and rendered to in one or more Target Sections.
mrtIndexIf the local texture that you’re referencing is a Multiple Render Target (MRT), this identifies the surface from the MRT that you wish to reference (0 is the first surface, 1 the second etc).
Example: input 0 rt0

identifier

Associates a numeric identifier with a pass involving a material. This is useful for registering a listener with Ogre::CompositorInstance::addListener, and being able to identify which pass it is that’s being processed, so that material parameters can be varied. Numbers between 0 and 2^32 - 1 are allowed.

Format: identifier <number>
Example: identifier 99945
Default: identifier 0

quad_normals

Pass the camera Frustum far corner vectors in the quad normals for passes of type quad. This is particularly useful for efficiently reconstructing position using only the depth and the corners.

Format: quad_normals <camera_far_corners_world_space|camera_far_corners_view_space>
Default: None

thread_groups

Passes of type compute operate on an abstract "compute space". This space is typically divided into threads and thread groups (work groups). The size of a thread group is defined inside the compute shader itself. This defines how many groups should be launched.

Example: if you want to process a 256x256px image and have a thread group size of 16x16x1, you want to specify 16 16 1 here as well.
Format: thread_groups <groups_x> <groups_y> <groups_z>

render_scene

Here are the attributes you can use in a render_scene section of a .compositor script:

first_render_queue

For passes of type ’render_scene’, this sets the first render queue id that is included in the render. Defaults to the value of Ogre::RENDER_QUEUE_BACKGROUND.

Format: first_render_queue <id>
Default: first_render_queue 0

last_render_queue

For passes of type ’render_scene’, this sets the last render queue id that is included in the render. Defaults to the value of Ogre::RENDER_QUEUE_SKIES_LATE.

Format: last_render_queue <id>
Default: last_render_queue 95

material_scheme

If set, indicates the material scheme to use for this pass only. Useful for performing special-case rendering effects. This will overwrite any scheme set in the parent Target Sections.

Format: material_scheme <scheme name>
Default: None

camera

Use a camera different from the output Viewport for rendering the scene into this target. Very useful for reflection effects like mirrors or water. The camera will be searched by name in the currently active scene and must be created prior to activating the compositor.

The optional parameter align_to_face automatically rotates the camera towards the target cubemap face, when rendering to a cubic texture.

Format: camera <name> [<align_to_face>]
Default: None

clear

For passes of type ’clear’, this section defines the buffer clearing parameters.

Format: pass clear { }

Here are the attributes you can use in a ’clear’ section of a .compositor script:

buffers

Sets the buffers cleared by this pass.

Format: buffers [colour] [depth] [stencil]
Default: buffers colour depth

colour_value

Set the colour used to fill the colour buffer by this pass, if the colour buffer is being cleared

Format: colour_value (<red> <green> <blue> <alpha> | auto)
Default: colour_value 0 0 0 0

If set to auto the background colour of the viewport is used, to which the parent compositor is attached to.

depth_value

Set the depth value used to fill the depth buffer by this pass, if the depth buffer is being cleared

Format: depth_value <depth>
Default: depth_value 1.0

stencil_value

Set the stencil value used to fill the stencil buffer by this pass, if the stencil buffer is being cleared

Format: stencil_value <value>
Default: stencil_value 0.0

stencil

For passes of type ’stencil’, this section defines the stencil operation parameters.

Format: pass stencil { }

The stencil buffer is used to mask out pixels in the render target, allowing you to do effects like mirrors, cut-outs, stencil shadows and more. Each of your batches of rendering is likely to ignore the stencil buffer, update it with new values, or apply it to mask the output of the render.

The stencil test is: $$(referenceValue\,\&\,compareMask)\;compareOp\;(stencilBuffer\,\&\,compareMask)$$

The result of this will cause one of 3 actions depending on whether

  1. the stencil test fails
  2. the stencil test succeeds but the depth buffer check fails
  3. both depth buffer check and stencil test pass

Here are the attributes you can use in a ’stencil’ section of a .compositor script:

check

Enables or disables the stencil check. The rest of the options in this section do nothing if the stencil check is off.

Format: check (on | off)

comp_func

Comparison operator for the stencil test.

Format: comp_func <func>
Default: comp_func always_pass
Parameters
funcone of Ogre::CompareFunction without the CMPF_ prefix. E.g. CMPF_LESS_EQUAL becomes less_equal.

ref_value

The reference value used in the stencil comparison.

Format: ref_value <value>
Default: ref_value 0.0

mask

The bitmask applied to both the stencil value and the reference value before comparison.

Format: mask <value>
Default: mask 4294967295

fail_op

The action to perform when the stencil check fails.

Format: fail_op <op>
Default: fail_op keep
Parameters
opone of Ogre::StencilOperation without the SOP_ prefix. E.g. SOP_INCREMENT_WRAP becomes increment_wrap.

depth_fail_op

The action to perform when the stencil check passes, but the depth buffer check fails.

Format: depth_fail_op <op>
Default: depth_fail_op keep
Parameters
opone of Ogre::StencilOperation without the SOP_ prefix. E.g. SOP_INCREMENT_WRAP becomes increment_wrap.

pass_op

The action to take when both the stencil and depth check pass.

Format: pass_op <op>
Default: pass_op keep
Parameters
opone of Ogre::StencilOperation without the SOP_ prefix. E.g. SOP_INCREMENT_WRAP becomes increment_wrap.

two_sided

Toggles two-sided stencil operation, which swaps increment and decrement for back-facing polygons.

Format: two_sided (on | off)
Default: two_sided off

Applying a Compositor

Adding a compositor instance to a viewport is very simple. All you need to do is:

Where viewport is a pointer to your viewport, and compositorName is the name of the compositor to create an instance of. By doing this, a new instance of a compositor will be added to a new compositor chain on that viewport. You can call the method multiple times to add further compositors to the chain on this viewport. By default, each compositor which is added is disabled, but you can change this state by calling:

Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, compositorName, enabledOrDisabled);

For more information on defining and using compositors, see Demo_Compositor in the Samples area, together with the Examples.compositor script in the media area.

Ogre::CompositorManager::addCompositor
CompositorInstance * addCompositor(Viewport *vp, const String &compositor, int addPosition=-1)
Add a compositor to a viewport.
Ogre::CompositorManager::setCompositorEnabled
void setCompositorEnabled(Viewport *vp, const String &compositor, bool value)
Set the state of a compositor on a viewport to enabled or disabled.
Ogre::PF_BYTE_RGBA
@ PF_BYTE_RGBA
32-bit pixel format, 8 bits for blue, green, red and alpha.
Definition: OgrePixelFormat.h:300
Ogre
Definition: OgreAlignedAllocator.h:34
Ogre::CompositorManager::getSingleton
static CompositorManager & getSingleton(void)
Get the singleton instance.