Gaffer Documentation

repository·main·Indexed 22 days ago

https://github.com/gafferhq/gaffer

A VFX application and framework for look developers, lighters, and compositors to build, iterate, and render scenes. Built on Cortex libraries, it features a multi-threaded deferred evaluation engine and supports Python and OSL scripting. The documentation covers building from source for Linux and Windows, integrating third-party renderers like Arnold and 3Delight, and using CLI utilities such as gaffer dispatch, gaffer env, and gaffer execute.

Tokens
46.1K
Snippets
84
Records
201
Agent score
75%

What's inside Gaffer

  1. What is a Spreadsheet node

    main

    The Spreadsheet node (Utility > Spreadsheet) provides a tabular interface for mapping values of one or more plugs to specific conditions in the graph. Unlike typical spreadsheet tools that adjust one plug across many nodes, each column in a Gaffer Spreadsheet connects to an individual plug on a specific node. This allows you to vary values based on the current Context without forking the network or using complex expression logic.

    It is particularly useful for:

    • Mapping different plug values to Context Variable values.
    • Managing multi-render and multi-shot graphs within a single branch.
    • Avoiding the complexity of branching a network for every unique shot or render option.
  2. What is a Box node and how is it used?

    main

    A Box node (_Utility_ > _Box_) is a container used to hold a nested node network, known as a sub-graph, inside a node graph. Boxes are used to add modularity, organization, and abstraction to your workflows.

    Key Uses:

    • Simplification: Wrap complex portions of a graph to reduce visual clutter.
    • Modularity: Sub-divide a large graph into a series of component sub-graphs.
    • Nesting: Boxes can be nested within other Boxes to maintain hierarchical simplicity.
    • Reference Scripts: Boxes can be exported as reference scripts. When exported, a Box preserves its custom UI, descriptions, tooltips, and documentation links, allowing you to share documented workflows across a team without writing code.
  3. What is IECorePreview

    main
    The IECorePreview directory contains advanced previews of upcoming Cortex functionality. These features are developed and tested here because they cannot be included in the stable Cortex 9 release due to compatibility constraints. Use this module if you need to experiment with or utilize cutting-edge Cortex features that are not yet part of the standard production release.
  4. Understand Gaffer's scene node and data flow model

    main

    In Gaffer, a scene node is any node that sends or receives scene data. Unlike many DCCs that have a single global scene, a Gaffer graph can support multiple independent scenes.

    Key Concepts:

    • Dynamic Computation: A scene is not a static data set; it is dynamically computed when a scene node is queried (e.g., when you select it).
    • Data Flow: In the Graph Editor, data flows from top to bottom. When a scene node computes a scene, it follows these steps:
      1. Data flows into the node through its input(s).
      2. The node modifies the data (if applicable).
      3. The node computes the resulting scene data and sends it through its output.
    • Independence: If nodes are not connected, their scenes remain separate. To interface multiple scenes, they must be joined later in the graph (e.g., using a Group node).
  5. Understand the role of Python in Gaffer

    main

    Gaffer uses a hybrid C++/Python architecture where Python serves several distinct purposes:

    1. Node Graph Definition: Gaffer node graphs are stored as Python scripts. When you save a .gfr file, Gaffer serializes the nodes, connections, and plug values into a series of Python instructions. Copying and pasting nodes also generates Python code.
    2. Application Configuration: Gaffer applications are configured via Python scripts.
    3. GUI and Scripting API: Much of the GUI is written in Python, and the Python Scripting API allows you to interactively build, modify, inspect, and debug node graphs via the built-in Python Editor.

    Key Distinctions

    • Scripts vs. Active Graphs: A script (like a .gfr file) is a set of instructions used to build a graph. An active graph in memory consists of C++ objects representing nodes and plugs.
    • Scripts vs. Expressions:
      • Scripting API: Used to interactively modify, inspect, or debug the graph structure and data.
      • Expressions: Code stored inside Expression nodes that runs during graph execution to dynamically change plug values.
  6. Use the Gaffer Image Coordinate System

    main

    Gaffer uses an integer grid coordinate system designed to be more intuitive than OpenEXR:

    • Origin: The bottom-left corner.
    • Direction: As y values increase, the image grows upwards.
    • Units: One unit equals one pixel.
    • Pixel Referencing: A pixel is referenced by the x and y coordinates of its bottom-left corner.
    • Sub-pixel Accuracy: For processes like rotation, the system uses floating-point values where (x + 0.5, y + 0.5) represents the pixel centre.
    • Rectangular Areas: Windows (Data/Display) are defined as the rectangle between the bottom-left corner of the bottom-left pixel and the top-right corner of the top-right pixel.
  7. How Gaffer Contexts affect scene queries

    main

    In Gaffer, a single plug can output different values depending on the Context in which getValue() is called. This is essential for multithreading, allowing different threads to query different parts of a scene or different image locations simultaneously.

    When querying an object plug directly via getValue(), it may fail if the context does not specify a scene:path. To query a specific object using the raw plug, you must manually set the scene:path in a Gaffer.Context:

    with Gaffer.Context( root.context() ) as context :
        context["scene:path"] = IECore.InternedStringVectorData( [ 'world', 'camera' ] )
        camera = root["StandardOptions"]["out"]["object"].getValue()

    However, it is recommended to use the utility methods (like .object(path)) which handle context management for you automatically.

  8. Customize Node and Plug UI with General Metadata

    main

    Gaffer uses a metadata convention to define how nodes and plugs appear in the user interface. You can use general metadata to override labels, descriptions, icons, and default values.

    Common general metadata keys:

    • label: The text displayed instead of the plug's name.
    • description: A description of the node or plug's purpose.
    • icon: The filename of the image used to represent the node.
    • documentation:url: A link to external documentation (use ! prefix for URLs, e.g., !http://www.gafferhq.org).
    • userDefault: Overrides the default value of a plug.
    • preset:<name>: Specifies a named preset value (e.g., "preset:Max", 1).
    • renameable: Boolean to enable/disable user renaming.
    • deletable: Boolean to enable/disable user deletion.
  9. How to offset a camera view

    main

    The Aperture Offset plug allows you to shift the camera view parallel to the image plane. This is useful for simulating tilt-shift lenses, rendering panorama tiles, or matching asymmetric crops. The behavior of the offset depends on the projection type:

    • Perspective (Field of View mode): 1 unit of offset = 1 whole horizontal field of view (e.g., 45°).
    • Perspective (Aperture and Focal Length mode): 1 unit of offset = 1 aperture unit of measure (e.g., 1mm).
    • Orthographic: 1 unit of offset = 1 world space unit.
  10. Use Set Expressions to manipulate object sets

    main

    Set expressions allow you to build new sets by combining existing sets or specific object locations using logical operators. Gaffer treats individual object names as single-member sets and allows you to combine multiple sets or objects using space-separated lists (which acts as a union |).

    // Combining sets and objects using space-separated lists (Union)
    set1 set2          // Results in the union of set1 and set2
    set1 D              // Results in the union of set1 and object D
    set1 | (D E)        // Results in the union of set1 and objects D and E
  11. Reference nodes and plugs using dictionary syntax

    main

    Nodes and plugs in Gaffer can be treated like Python dictionaries. This is the primary way to access plugs when they do not have assigned Python variables.

    • Nodes: Use root['NodeName'] to reference a node by its name in the graph.
    • Plugs: Use node['plugName'] to reference a plug. For nested plugs, use node['parentPlug']['childPlug'].

    Caution: Using assignment like root['Sphere'] = ... can overwrite existing nodes or plugs without warning. Always use dictionary syntax carefully.

    Pro-tip: You can drag and drop nodes or plugs from the Gaffer interface directly into the Python Editor to automatically insert the correct dictionary-style reference string.

    # Referencing a plug directly via a variable
    mySphere['radius']
    
    # Referencing a plug via the root dictionary
    root['Sphere']['radius']