Overview
========

The Renderer API allows the integration of renderers into Katana.

.. _plugin-intro:

What is a render plug-in?
-------------------------

A render plug-in is a collection of modules which provide Katana with
renderer-specific information that can be configured and declared to the
renderer in the UI as well as handling the corresponding Katana recipes at
render time. The modules used to implement a render plug-in are the following:

- `Render::RenderBase <RenderAPI.html#Foundry::Katana::Render::RenderBase>`_:
  Translates a Katana recipe into the renderer's language using a scene graph
  iterator (:doc:`FnScenegraphIterator <../Utilities/SceneGraphIterator>`),
  where the rendered content is typically visualised in Katana's **Monitor**
  tab.
  A render plug-in represents a single render process, which is instantiated
  with the Katana recipe and render arguments when a render is launched, and
  which is destroyed when the render is complete or cancelled.
  The render plug-in can delegate the handling of scene graph location types to
  delegate plug-ins (see `Render::ScenegraphLocationDelegate
  <RenderAPI.html#Foundry::Katana::Render::ScenegraphLocationDelegate>`_). This
  enables the registering and handling of new renderer-specific location types
  without changing the render plug-in.
  See :ref:`Recipe utility classes <recipe-utility-classes>`.
- `RendererInfo::RendererInfoBase
  <RenderAPI.html#Foundry::Katana::RendererInfo::RendererInfoBase>`_: Provides
  Katana with renderer-specific information needed to configure a renderable
  scene, e.g. shaders, render outputs. If applicable, this plug-in also
  advertises and configures nodes such as <RendererName>ShadingNode and
  <RendererName>OutputChannelDefine.
  It is also responsible for :ref:`advertising supported render methods
  <render-methods>` such as preview and disk renders.
- :ref:`Configuration nodes <configuration-nodes>`: Renderer-specific nodes are
  useful for configuring renderable properties such as global and object
  settings.

.. _render-methods:

Advertising render methods to start a render process
----------------------------------------------------

A render plug-in must advertise one or more supported render methods which
become available in the UI (unless explicitly hidden) and script mode. Render
methods are created by adding instances of render method classes to the vector
passed into `RendererInfo::RendererInfoBase::fillRenderMethods
<RenderAPI.html#Foundry::Katana::RendererInfo::RendererInfoBase::fillRenderMethods__std::vector:RendererInfo::RenderMethodP:R>`_.
The base render method classes represent different ways of handling a render
process in Katana:

- `RendererInfo::DiskRenderMethod
  <RenderAPI.html#Foundry::Katana::RendererInfo::DiskRenderMethod>`_: The
  render plug-in can query all the render outputs which have been declared
  using RenderOutputDefine nodes. Each output has a target location where it is
  intended to be written to disk. The primary output will be loaded and
  displayed in the **Monitor** tab.

    - See :ref:`Rendering one or more render outputs to disk
      <disk-images-to-katana>`.

- `RendererInfo::PreviewRenderMethod
  <RenderAPI.html#Foundry::Katana::RendererInfo::PreviewRenderMethod>`_:
  Preview renders are sent directly from the renderer to the **Monitor** tab
  using an
  inter-process communication protocol (IPC) where each bucket can be sent
  interactively (and progressively). Preview renders can display multiple AOVs
  in the **Monitor** tab but only one view.

    - See :ref:`Sending rendered images to Katana using the Display Driver API
      <preview-images-to-katana>`.

- `RendererInfo::LiveRenderMethod
  <RenderAPI.html#Foundry::Katana::RendererInfo::LiveRenderMethod>`_: A live
  render follows the same principles as a preview render in terms of how the
  render is launched and how the rendered content is delivered to Katana.
  The difference is that the render process is kept alive to allow live
  attribute updates, which are sent to the render plug-in using IPC.

    - See the :ref:`key stages of the render process <render-process>` and how
      they affect live rendering.
    - See `Render::RenderBase::queueDataUpdates
      <RenderAPI.html#Foundry::Katana::Render::RenderBase::queueDataUpdates__FnAttribute::GroupAttribute>`_.

Each render method can :ref:`advertise and write render debug outputs
<debug-output>` to a file which are displayed in an external editor.

Render methods can be hidden from the UI using
`RendererInfo::RenderMethod::setVisible
<RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setVisible__b>`_
where it can still be used in script mode when launching a render process with
StartRender.

A render method can customise the way a render is launched in Katana. By
default, a render process will create a catalog item, register the render so
that it may be cancelled etc., and report any render messages in the render log.
These properties can be configured to launch a detached render where Katana will
absolve itself from any involvement beyond launching the render process with the
recipe.
This is done by passing false into the following functions:

- `RendererInfo::RenderMethod::setCreateCatalogItem
  <RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setCreateCatalogItem__b>`_
- `RendererInfo::RenderMethod::setReportRenderMessages
  <RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setReportRenderMessages__b>`_
- `RendererInfo::RenderMethod::setRegisterRender
  <RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setRegisterRender__b>`_

.. _batch-rendering:

Batch rendering
```````````````

Katana requires a batch render method so the ``RendererInfoBase`` automatically
creates a ``DiskRenderMethod`` with default parameters which will be used for
batch
rendering. The parameters can be overridden in
`RendererInfoBase::configureBatchRenderMethod
<RenderAPI.html#Foundry::Katana::RendererInfo::RendererInfoBase::configureBatchRenderMethod__RendererInfo::DiskRenderMethodR>`_.

.. _render-methods-ui:

Launching render methods in the UI
``````````````````````````````````

The render methods are grouped in Katana's **Render** menu based on their type.
The method name is passed as an argument to the render process where the render
plug-in can retrieve it using `Render::RenderBase::getRenderMethodName
<RenderAPI.html#Foundry::Katana::Render::RenderBase::getRenderMethodName>`_.

:Tip: It is useful to use the default name and label provided by the render
      method classes for the most common cases as the render menu collapses
      items whose corresponding methods share the same name and label. This is
      done to allow simplifying the render menu where multiple renderers have
      equivalent render methods. Furthermore, standardising the user experience
      across renderers makes it easier for users to find the render method they
      want to launch.

.. _starting-renders:

Starting a render
-----------------

A render plug-in must implement the `Render::RenderBase::start
<RenderAPI.html#Foundry::Katana::Render::RenderBase::start>`_ function which is
called at the start of Katana's render process. The plug-in has immediate
access to:

- The Katana recipe which is traversed using a :doc:`FnScenegraphIterator
  <../Utilities/SceneGraphIterator>`, where the root iterator is retrieved using
  `Render::RenderBase::getRootIterator
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::getRootIterator>`_.
  Utility classes and functions are available which assist with the scene graph
  traversal and attribute handling (see :ref:`Processing the Katana recipe
  <recipe-traversal>`).
- Render arguments consisting of the render method name which was used to launch
  the render process, render time (frame), etc.
  These arguments can be retrieved either directly as strings using
  `Render::RenderBase::findArgument
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::findArgument__ssCR.ssCR>`_,
  or alternatively using explicit wrapper functions such as
  `Render::RenderBase::getRenderMethodName
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::getRenderMethodName>`_
  and `Render::RenderBase::getRenderTime
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::getRenderTime>`_ which
  returns the render time as a float value.

.. _render-process:

Key stages of the render process
--------------------------------

Implementing only the start function is sufficient for most renders.
More flexibility is needed for live renders where the render process is kept
alive and updates/commands can be sent to the render plug-in until the render is
either stopped by the user, or the Katana session ends.
This flexibility is provided by supporting optional functions which are called
at different points during the render process:

- `Render::RenderBase::start
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::start>`_: Called to
  start the render process. This is the only function that must be implemented
  by the render plug-in.
- `Render::RenderBase::pause
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::pause>`_: Pause the
  render/live render process. Currently it is only called during a live render
  when updating regions of interest.
- `Render::RenderBase::stop
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::stop>`_: Always called
  at the end of the render process.
- `Render::RenderBase::queueDataUpdates
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::queueDataUpdates__FnAttribute::GroupAttribute>`_:
  Called asynchronously in a separate thread during a live render with the
  attributes that have changed.
  The updates can either be applied directly or queued here and applied later in
  the main thread.
  When and how often this function is called depends on the **3D Update Mode**:

    - **Manual**: The ``queueDataUpdates()`` function is called when the user
      explicitly clicks the **Trigger 3D Update** button.
    - **Pen-Up**: The ``queueDataUpdates()`` function is called after an
      attribute value has changed anywhere in the scene graph.
    - **Continuous**: The ``queueDataUpdates()`` function is called with a
      fixed frequency
      (every 10ms) if attribute values have changed.
      Currently this only applies to camera and light transform updates in the
      viewer.

- `Render::RenderBase::hasPendingDataUpdates
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::hasPendingDataUpdates>`_:
  Called after live update data or command has been processed asynchronously to
  inform the render process of whether some or all of the data updates have not
  been applied in the queueDataUpdates function.
- `Render::RenderBase::applyPendingDataUpdates
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::applyPendingDataUpdates>`_:
  Called if hasPendingDataUpdates returns true. This is used to facilitate a
  workflow where a set of updates are queued in the update thread and then
  flushed in the main thread.
- `Render::RenderBase::processControlCommand
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::processControlCommand__ssCR>`_:
  Called when a custom live render command is executed.
- `Render::RenderBase::stopLiveEditing
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::stopLiveEditing>`_:
  Called when a live render is stopped by the user.

.. _recipe-traversal:

Processing the Katana recipe and utility classes
------------------------------------------------

Interpreting the Katana recipe into the renderer's language involves a deferred
evaluation of the scene graph. This is done by traversing the scene graph using
a :doc:`FnScenegraphIterator <../Utilities/SceneGraphIterator>` starting from
the root. The render plug-in can get the root iterator using
`Render::RenderBase::getRootIterator
<RenderAPI.html#Foundry::Katana::Render::RenderBase::getRootIterator>`_.
Each iterator corresponds to a scene graph location which contains a set of
corresponding attributes.
Scene graph location types and attributes are based on conventions where the
render plug-in can selectively handle location types and attributes that are
applicable to the renderer.

.. _sg-delegates:

Scene graph delegates
`````````````````````

The handling of scene graph locations and their attributes can be dynamically
delegated to `Render::ScenegraphLocationDelegate
<RenderAPI.html#Foundry::Katana::Render::ScenegraphLocationDelegate>`_
plug-ins. Given an arbitrary scene graph iterator (e.g.
:doc:`FnScenegraphIterator <../Utilities/SceneGraphIterator>` sgi), we can
check if a corresponding delegate plug-in exists and invoke it using
`RenderOutputUtils::processLocation
<RenderAPI.html#Foundry::Katana::RenderOutputUtils::processLocation__FnScenegraphIterator.ssCR.ssCR.voidP.voidPP>`_

.. code-block:: c++

    bool pluginFound = RenderOutputUtils::processLocation(sgi, "myrenderer", sgi.getType(), 0x0, 0x0);

.. _recipe-utility-classes:

Scene graph utility classes
```````````````````````````

Utility classes are provided to parse standardised attribute conventions where
they can be extended to provide renderer-specific behaviour through overrides:

- `Render::RenderSettings <RenderAPI.html#Foundry::Katana::Render::RenderSettings>`_:
  Parses **renderSettings** at **/root**.
- `Render::CameraSettings <RenderAPI.html#Foundry::Katana::Render::CameraSettings>`_:
  Parses **camera.geometry** at **/root/world/cam/<cameraName>**.
- `Render::GlobalSettings <RenderAPI.html#Foundry::Katana::Render::GlobalSettings>`_:
  Parses **<rendererName>GlobalStatements** at **/root** (see
  :ref:`Configuring global settings <global-settings>`).
- RenderOutputUtils: A collection of useful utility functions.

:Tip: Avoid using the iterator function getByPath to get an iterator for a
      location that has already been traversed as it will traverse the scene
      graph again from the root. It is generally preferable to use a cached
      iterator class unless the memory footprint is a critical issue.

.. _disk-images-to-katana:

Disk Render: Rendering one or more render outputs to disk
---------------------------------------------------------

Disk renders can only be launched from a render node and the renderer has to
provide a target filename for each render output (port).
The rendered target file for the primary render output is read and displayed in
the **Catalog** and **Monitor** tabs when the render is complete (if the file
type is
supported).

There are two steps required to configure and perform a disk render:

- Configure how the render outputs are handled. This includes where they are
  rendered to, whether they should be displayed in the **Monitor** tab, what
  pre- and
  post-processes are required, etc. This is done in
  `Render::RenderBase::configureDiskRenderOutputProcess
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::configureDiskRenderOutputProcess__DiskRenderOutputProcessR.ssCR.ssCR.ssCR.floatCR>`_
  which is called for each output where the type of `Render::RenderAction
  <RenderAPI.html#Foundry::Katana::Render::RenderAction>`_ and its properties
  governs the workflow for the render output.
- Loop over and process each render output in the render plug-in. The render
  outputs are parsed in `Render::RenderSettings
  <RenderAPI.html#Foundry::Katana::Render::RenderSettings>`_ where they are
  retrieved using e.g. `Render::RenderSettings::getRenderOutputs
  <RenderAPI.html#Foundry::Katana::Render::RenderSettings::getRenderOutputs>`_.

Following these steps, a simple workflow for a **color** pass which renders to a
temporary location where the file is then copied to the target location could be
as follows (note that the following code snippet omits the ``Foundry::Katana``
namespace for simplicity):

**configureDiskRenderOutputProcess**

.. code-block:: c++

    // Get the render outputs from the render settings
    RenderSettings renderSettings(getRootIterator());
    RenderSettings::RenderOutput output = renderSettings.getRenderOutputByName(outputName);

    // Generate a unique temporary local output location used by the renderer
    std::string tempRenderLocation = RenderOutputUtils::buildTempRenderLocation(
                                         rootIterator, outputName, "render", "exr", frameTime);

    // Use the path from the location plug-in as a final target location which
    // is displayed in the Monitor tab
    std::string targetRenderLocation = outputPath;

    // Declare the render action used for this render output
    std::auto_ptr<Render::RenderAction> renderAction;

    // Determine the rendering behaviour based on the output type
    if (output.type == "color")
    {
        // Here we render to a temporary location and then convert and copy it to the final location
        renderAction.reset(new Render::CopyAndConvertRenderAction(targetRenderLocation,
                                                                  tempRenderLocation,
                                                                  output.clampOutput,
                                                                  output.colorConvert,
                                                                  output.computeStats,
                                                                  output.convertSettings));
    }

The attributes for each output are found at the root of the scene graph under
**renderSettings.outputs**.
The easiest way to get the attribute values for a particular render output is to
use `Render::RenderSettings::getRenderOutputByName
<RenderAPI.html#Foundry::Katana::Render::RenderSettings::getRenderOutputByName__ssCR>`_.

**start (or any function which processes the render outputs)**

.. code-block:: c++

    ...
    // Get all render outputs for a disk render
    RenderOutputs outputs = renderSettings.getRenderOutputs();

    // Iterate through and process each output
    ...
    if (output.type == "color")
    {
        // Get the render location which in this case is a temporary location
        // as defined by the render action
        std::string renderLocation = output.renderLocation;
        ...
    }

.. note:: Disk renders do not support displaying arbitrary output variables
          (AOVs) in the **Monitor** tab.
.. note:: Katana's **Monitor** tab currently only supports images of type EXR,
          CIN, RLA, and OIIO.

.. seealso::

    - `Render::RenderBase::configureDiskRenderOutputProcess
      <RenderAPI.html#Foundry::Katana::Render::RenderBase::configureDiskRenderOutputProcess__DiskRenderOutputProcessR.ssCR.ssCR.ssCR.floatCR>`_
    - `Render::DiskRenderOutputProcess
      <RenderAPI.html#Foundry::Katana::Render::DiskRenderOutputProcess>`_
    - `Render::RenderAction <RenderAPI.html#Foundry::Katana::Render::RenderAction>`_
    - `Render::CopyRenderAction <RenderAPI.html#Foundry::Katana::Render::CopyRenderAction>`_
    - `Render::CopyAndConvertRenderAction
      <RenderAPI.html#Foundry::Katana::Render::CopyAndConvertRenderAction>`_
    - `Render::TemporaryRenderAction
      <RenderAPI.html#Foundry::Katana::Render::TemporaryRenderAction>`_
    - `Render::NoOutputRenderAction
      <RenderAPI.html#Foundry::Katana::Render::NoOutputRenderAction>`_
    - `Render::RenderSettings::RenderOutputs
      <RenderAPI.html#Foundry::Katana::Render::RenderSettings::RenderOutputs>`_
    - `Render::RenderSettings::getRenderOutputs
      <RenderAPI.html#Foundry::Katana::Render::RenderSettings::getRenderOutputs>`_

.. _preview-images-to-katana:

Preview Render: Rendering directly to Katana's **Monitor** tab
--------------------------------------------------------------

A preview render can be launched from any node in the UI where the renderer
sends the rendered content (e.g. buckets) interactively to the **Monitor** tab
as soon
as they are ready using the :doc:`Display Driver API <../DisplayDriver>`.

Katana starts a listener when the UI is launched which retrieves image and ID
data over a communication protocol. Preview renders have no concept of render
outputs but instead use channel buffers that contain the names of the selected
outputs and the corresponding buffer IDs. The IDs represent buffers that are
reserved in Katana's **Catalog** tab and they are used by the display driver to
make
sure the image channel data goes to the right buffer.

The following exmample demonstrates how the channel buffers are queried from the
render settings (note that the following code snippet omits the
``Foundry::Katana``
namespace for simplicity):

.. code-block:: c++

    RenderSettings::ChannelBuffers buffers;
    renderSettings.getChannelBuffers( buffers );

    RenderSettings::ChannelBuffers::const_iterator it;
    for( it = buffers.begin(); it != buffers.end(); ++it )
    {
        RenderSettings::ChannelBuffer buffer = it->second;
        // Use buffer.bufferId and buffer.channelName with the Display Driver API
        ...
    }

.. note:: Katana's **Monitor** tab currently only supports images of type EXR,
          CIN, RLA, and OIIO.

.. seealso::

    - `Render::RenderSettings::ChannelBuffer
      <RenderAPI.html#Foundry::Katana::Render::RenderSettings::ChannelBuffer>`_
    - `Render::RenderSettings::getChannelBuffers
      <RenderAPI.html#Foundry::Katana::Render::RenderSettings::getChannelBuffers__ChannelBuffersR>`_
    - `RendererInfo::RenderMethod
      <RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod>`_

.. _debug-output:

Generating a render debug output
--------------------------------

There are two steps involved in creating a render debug output:

- Advertise that a render method supports debug outputs. This creates the
  necessary UI hooks to allow the user to ask for a debug output.
- Check for specific render arguments in the render plug-in which indicate that
  the render process was triggered with the expectation that a render debug
  output file is created.

.. _debug-advertise:

Advertising debug output support
````````````````````````````````

The most common way of requesting render debug output in Katana is through the
**Debug** submenu in a node's context menu.
In order to add a menu item for the renderer to the **Debug** submenu, a batch
render method has to be defined with debug output supported.
This is done using `RendererInfo::RenderMethod::setDebugOutputSupported
<RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setDebugOutputSupported__b>`_.
The output file extension is set using
`RendererInfo::RenderMethod::setDebugOutputFileType
<RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setDebugOutputFileType__ssCR>`_.
The text of the menu item is formatted as **Open <rendererName>
.[fileExtension] Output in External Editor**, for example **Open dl .nsi Output
in External Editor**.
The menu item launches a render process with a render argument which specifies a
target location for the render debug output (this is discussed more in the next
section).

Disk/batch renders do not support a partial scene graph, so a preview render
method is used if **Render Only Selected Objects** is turned on in the **Scene
Graph** tab. A partial scene graph here will still include the **/root** and
**/root/world** locations,
so it is conceptually identical to a full scene graph.

A different type of partial scene graph output can be obtained using a scene
graph location's
context menu, where a **Debug** submenu contains menu items that follow the
same signature as
the one above.
These menu items can be made available using
`RendererInfo::RenderMethod::setSceneGraphDebugOutputSupported
<RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setSceneGraphDebugOutputSupported__b>`_
and `RendererInfo::RenderMethod::setDebugOutputFileType
<RenderAPI.html#Foundry::Katana::RendererInfo::RenderMethod::setDebugOutputFileType__ssCR>`_
as before. A current limitation is that only one render method can support this
feature.

Debug output can be created from Python using the following functions in
the ``NodeDebugOutput`` module:

.. code-block:: python

    NodeDebugOutput.WriteRenderOutput(node, renderer, filename=None, expandProcedural=True,
                                      openInEditor=False, customEditor=None, log=None)

    NodeDebugOutput.WriteRenderOutputForRenderMethod(renderMethodName, node, renderer,
                                                     filename=None, expandProcedural=True,
                                                     log=None, openInEditor=True,
                                                     customEditor=None, sceneGraphPath=None,
                                                     printToConsole=False)

The former method always uses the batch render method and runs synchronously
(blocking).
The latter one supports any render method and runs asynchronously
(non-blocking).

.. _debug-arguments:

Creating a debug output in the render plug-in
`````````````````````````````````````````````

We know that our render plug-in should create a debug output if
``renderOutputFile`` was passed as an argument to the render process
(``renderboot``).
The argument's value can be retrieved using
`Render::RenderBase::getRenderOutputFile
<RenderAPI.html#Foundry::Katana::Render::RenderBase::getRenderOutputFile>`_
where the value specifies the target location of the debug output. Katana will
by default open the debug output file when the render process has finished.

Another render argument is passed which indicates whether the bounded
procedurals should be expanded which is queried using
`Render::RenderBase::isExpandProceduralActive
<RenderAPI.html#Foundry::Katana::Render::RenderBase::isExpandProceduralActive__b>`_.

.. note:: A debug output will not cancel a preview render which is in progress.
          However, a non-concurrent preview render will cancel a debug output
          process. A full debug output runs a synchronous disk render by default
          and therefore blocks the UI.
          A partial debug output using **Render Only Selected Objects** runs an
          asynchronous preview render which does not block the UI.

.. _default-renderer:

Setting the plug-in as the default renderer in Katana
-----------------------------------------------------

Setting the default renderer in Katana is done using the environment variable
``DEFAULT_RENDERER=<rendererName>``.

.. _linking-plugins:

Linking the plug-in to its corresponding renderer info plug-in
--------------------------------------------------------------

The name used to register the render plug-in should be returned in the renderer
info plug-in through `RendererInfoBase::getRegisteredRendererName
<RenderAPI.html#Foundry::Katana::RendererInfo::RendererInfoBase::getRegisteredRendererName>`_.

This tells Katana how to namespace attribute data provided by the renderer info
plug-in (e.g. shaders), in such as way that it can be easily retrieved by the
render plug-in.

.. _configuration-nodes:

Adding configuration nodes
--------------------------

GenericAssign nodes are useful to expose a set of scoped attributes which can be
used to specify renderer-specific properties such as global settings. These
nodes are created using an XML file which contains the attributes and
corresponding UI hints, as well as the scene graph scope.
The XML file has to reside in a directory called ``GenericAssign`` where it will
be picked up and used to automatically register a node whose name matches the
XML filename.

.. _global-settings:

Configuring global settings (<rendererName>GlobalStatements)
````````````````````````````````````````````````````````````

A typical use for a configuration node is to declare global options which apply
during the render process. The convention in Katana is to scope these global
settings at the root of the scene graph under a group attribute named
**<rendererName>GlobalStatements**.
A fixed CEL statement is used to prevent users from being able to scope the
global attributes arbitrarily. The following example shows how the GenericAssign
node is configured to get this behaviour, as well as providing a simple
attribute setup which utilises widget hints and conditional visibility:

.. code-block:: xml

    <args format='1.0' scope='/root' fixedCEL='/root'>
      <group name='myrendererGlobalStatements' hideTitle='True' closed='True' groupInherit='False'>
        <group name='bucket' closed='True'>
          <string name='order' default='horizontal' widget='popup'>
            <hintlist name="options">
              <string value="horizontal"/>
              <string value="vertical"/>
              <string value="spiral"/>
            </hintlist>
            <help>Some help text</help>
          </string>

          <int name='orderorigin' default='0, 0' size='2' tupleSize='2'
              conditionalVisOp='equalTo' conditionalVisPath='../order' conditionalVisValue='spiral'/>
        </group>
        ...
      </group>
    </args>

Here, we declared a closed group which encapsulates all bucket settings where a
popup list offers a choice of three bucket orders and a conditional property is
shown if the **spiral** value is selected.

The `Render::GlobalSettings <RenderAPI.html#Foundry::Katana::Render::GlobalSettings>`_
utility class can be extended where it retrieves the global statements based on
Katana's naming convention. The class can then freely be used to parse the
attribute data and encapsulate global settings related functions.

.. _object-settings:

Configuring object settings (<rendererName>Statements)
``````````````````````````````````````````````````````

GenericAssign nodes can also be used to configure attributes for arbitrary scene
graph locations based on a CEL statement. This allows assigning attribute data
on a per object basis while traversing the scene graph. By convention, these
attributes can be assigned to any scene graph location below (and including) the
world location, where the attributes are grouped under
**<rendererName>Statements** and can be inherited.
The following example shows how to configure the scope as well as setting up a
page which encloses a set of attributes (differently to a group attribute):

.. code-block:: xml

    <args format='1.0' scope='/root/world//\* /root/world'>
      <group name='myrendererStatements' hideTitle='True' closed='True'>
        <page name="Geometry">
          <int name='invert_normals' default='0' widget='checkBox'>
            <help>
              Some help text.
            </help>
          </int>
          ...
        </page>
        ...
      </group>
    </args>

.. _id-passes:

Sending ID pass data to Katana
------------------------------

There are two aspects in terms of getting ID pass data to Katana:

- Assign an integer value to a renderable scene graph location and advertise the
  mapping between the two to Katana.
- Render the ID pass and send the single channel image to Katana.

The latter is naturally expressed as a channel in the
:doc:`Display Driver API <../DisplayDriver>` so this section will focus on the
former.

`Render::IdSenderInterface <RenderAPI.html#Foundry::Katana::Render::IdSenderInterface>`_
is a utility class which handles the ID communication with Katana. It is used
to both get a unique integer ID from Katana as well as sending the ID values
and their corresponding scene graph location names to Katana.

Example:

.. code-block:: c++

    int64_t nextId;
    int64_t maxId;

    // Get an instance of the ID sender interface from the factory
    Render::IdSenderInterface* idSender;
    idSender = Render::IdSenderFactory::getNewInstance(getKatanaHost(), frameID);

    // Get the next unique ID integer value
    idSender->getIds(&nextId, &maxId);

    // Use nextId with the scene graph iterator (sgi) location

    // Send the ID and scene graph location path
    idSender->send(nextId, sgi.getFullPath().c_str());

A ``frameID`` as used above can be retrieved from a
`RenderSettings::ChannelBuffer
<RenderAPI.html#Foundry::Katana::Render::RenderSettings::ChannelBuffer>`_
object, e.g.:

.. code-block:: c++

    RenderSettings::ChannelBuffers channelBuffers;
    renderSettings.getChannelBuffers(channelBuffers);

    // Here we assume the first channel buffer is valid and used
    int64_t frameID = convertToInt(channelBuffers[0].bufferId);

.. _render-threads:

Setting the number of render threads
------------------------------------

There are two conventions used in Katana to declare the number of render threads
for a launched render process:

- Using a **renderSettings.renderThreads** attribute.
  The function `Render::RenderSettings::applyRenderThreads
  <RenderAPI.html#Foundry::Katana::Render::RenderSettings::applyRenderThreads__iR>`_
  can be used to apply the value if it has been set.
- UI preferences and batch command line argument. Both override values are sent
  to the render process as a ``threads`` argument where it can be applied using
  `Render::RenderBase::applyRenderThreadsOverride
  <RenderAPI.html#Foundry::Katana::Render::RenderBase::applyRenderThreadsOverride__iR>`_.
  Note that this value should always override every other thread value as the
  user has explicitly requested it.

    - UI mode: The **interactiveRenderThreads3D** value is sent to the render
      process if **interactiveRenderThreadOverride** is set to **Yes** in the
      **Preferences** dialog.
    - Batch mode: The thread count is set using the ``--threads3d`` argument
      when
      launching Katana where the value is sent to the render process.

Customizing the Network Material Group Context Layered Menu
-----------------------------------------------------------

A user, while viewing the node graph from within a NetworkMaterialCreate
context, can press the **Tab** key to open a layered menu with an entry for
each shading node type of the currently selected render plug-in. The user can
switch between which of the render plug-ins is currently selected by
pressing **Shift+Tab** which opens an additional layered menu populated with
one entry per installed render plugin.

By default, the **Tab** menu is populated with the node types of the selected
render plug-in and a subset of Katana node types.

Customization of the entries in the **Tab** menu can be achieved by first
instantiating and then registering a ``LayeredMenu`` as described in the
`LayeredMenuAPI
<../../Scripting/CustomizingUserInterface/LayeredMenu.html>`_.

Functions have been provided to get and set the display name and color for a
render plug-in.

The name and color can be set using:
    `RenderingAPI.RenderPlugins.SetRendererPluginDisplayName()
    <../../Scripting/RenderingAScene/RenderingAPI.html#RenderingAPI.RenderPlugins.SetRendererPluginDisplayName>`_
    `RenderingAPI.RenderPlugins.SetRendererPluginDisplayColor()
    <../../Scripting/RenderingAScene/RenderingAPI.html#RenderingAPI.RenderPlugins.SetRendererPluginDisplayColor>`_

The name and color can be retrieved using:
    `RenderingAPI.RenderPlugins.GetRendererPluginDisplayName()
    <../../Scripting/RenderingAScene/RenderingAPI.html#RenderingAPI.RenderPlugins.GetRendererPluginDisplayName>`_
    `RenderingAPI.RenderPlugins.GetRendererPluginDisplayColor()
    <../../Scripting/RenderingAScene/RenderingAPI.html#RenderingAPI.RenderPlugins.GetRendererPluginDisplayColor>`_

An example script is included in the Katana distribution:
    ``plugins/Src/Resources/Examples/UIPlugins/RenderPluginsExamples.py``