== Quick Start Guide anchor:quickstart_quickStartGuide[] This tutorial is designed to give new users their first exposure to the workflow in Gaffer. Brief explanations of each step will be given, but there's no need to worry if you don't completely grasp what is going on. Instead; the intent is to expose various aspects of the program, providing some practical experience that should be helpful as you work through the rest of the user guide. [NOTE] You will need 3delight configured for use in Gaffer to fully follow this tutorial. If you are using Arnold (or another renderer), you should be able to make substitutions for the RenderMan specific nodes. [IMPORTANT] To complete the sections covering shader assignments and light creation, you will first need to point Gaffer at the sample shaders provided as part of the install. Add "$GAFFER_ROOT/doc/examples/shaders" to your $DL_SHADERS_PATH prior to launching `gaffer`. Given all that, let's dive in: === Launch Gaffer * As detailed in the xref:installation_launchingGaffer[installation chapter], launch Gaffer from a shell with the following command: ------------------------------------ > gaffer ------------------------------------ * You should be presented with the default UI *layout*. .The default Gaffer interface. image::images/autoGenerated_target/quickstart_tutorial_figAA.png[align="center"] === Create a sphere * Locate the *NodeGraph* editor. This should be in the lower left portion of the window. * `right-click` within the bounds of the NodeGraph to pop-up a menu for creating nodes. ** 'Be patient as the menu can take a little while to build first time round.' * Navigate this menu to find the "Sphere" node, and `left-click` to select it. ** The path is _Scene -> Source -> Primitive -> Sphere_ * You should now be able to see a sphere in the *Viewer*. .Our first node is created and geometry is visible in the 3d view. image::images/autoGenerated_target/quickstart_tutorial_figBA.png[align="center"] === Adjust the sphere * Locate the *NodeEditor*. This should be in the upper right portion of the window. * This panel controls the parameters used to generate the sphere, as well as some properties of the node itself. * At the top of the editor change the "Node Name" from "Sphere" to "SphereA". This will change the label used to identify the node in the node network. * Within the "Settings" tab, change the "Name" parameter from "sphere" to "sphereA". This changes the name of the object created in the *scene*. * Change the "Radius" parameter from 1 to 2. You should see the sphere get twice as big in the viewer. * Next, switch to the "Transform" tab, and tweak the "Translate" control to move the sphere up by 2 units in the Y axis. .A bigger sphere. image::images/autoGenerated_target/quickstart_tutorial_figCA.png[align="center"] === Add a plane * Go back to the NodeGraph, and `left-click` in the empty space to clear the current selection. * Then press `tab` to launch the node creation menu again. * Type "plane" then `Enter`. * This should create a new node in the graph, and you should see some geometry forming a plane in the Viewer. * In the NodeEditor, set the "Dimensions" to 20, 20. * On the "Transform" tab, set the "Rotate" X value to -90 in order to lay the plane down flat. .We now have two nodes, and the active (selected) node is being viewed. image::images/autoGenerated_target/quickstart_tutorial_figDA.png[align="center"] === Group the geo * In the NodeGraph, select both the nodes that have been created. They should appear highlighted. ** Either hold down `Shift` and `left-click` to pick multiple nodes, or `left-click-drag` to draw a selection box around all the nodes you want to pick. * Keeping the two nodes selected, create a "Group" node (`right-click`, _Scene -> Hierarchy ->Group_). * Gaffer will automatically connect the outputs of both the "SphereA" and "Plane" nodes to the inputs of the new "Group" node. * The group node introduces a new level to the scene hierarchy, and parents the inputs scenes underneath that *location*. * Use the NodeEditor to set the "Name" of the new item in the hierarchy to "geoGroup". .The two geometry generating nodes feeding into a grouping node. image::images/autoGenerated_target/quickstart_tutorial_figEA.png[align="center"] === Inspecting the hierarchy * You may have noticed that when we created the group node, the display in the Viewer changed. Instead of showing the geometry, it switched to drawing a bounding box. ** This is because the hierarchy changed and in the default state (collapsed) we only see the bounding box of the top levels. * Locate the *SceneHierarchy* tab. This should be in the lower right portion of the window. * Click the small horizontal arrow head next to "geoGroup" to expand the hierarchy. * You should now see "plane" and "sphereA" listed underneath "geoGroup". ** The indentation indicates that these are parented to "geoGroup". * The Viewer should have updated to show you both the sphere and the plane together (where as previously we saw only the output of the individual nodes in isolation). * In the SceneHierarchy, click on "sphereA" to select that item. The ball geometry should become highlighted in the Viewer. ** Note how the selection in the hierarchy (the scene) is distinct from the selection in the graph. * Move your mouse over to the Viewer and press `f` to frame the view around the current scene selection. .Now we can see the geometry together. We can also see the parent-child relationships present in the hierarchy. image::images/autoGenerated_target/quickstart_tutorial_figEB.png[align="center"] === Adding a camera * Back in the NodeGraph, click in empty space to clear the selection. * Then create a "Camera" node (`right-click`, _Scene -> Source -> Camera_) * Clear the selection again and create a "Group" node with no connections. * From the base of the tile representing the "Camera" node, `left-click-drag` on the dot and keeping the mouse press down move over to the dot on the top of the "Group1" node. * Release the mouse. You should now have a connection running from the "Camera" node to the "Group1" node. * Perform the same drag-to-connect action to join the original "Group" node into the second dot on the top of the "Group1" node. * `left-click-drag` on the middle of the tiles to move them around in the NodeGraph. ** Try to arrange them to look like the picture below. ** Take care to ensure the connections match those shown in the image. .By feeding the camera and the existing group into a new group, we create a new scene composed of those two inputs. image::images/autoGenerated_target/quickstart_tutorial_figFA.png[align="center"] === Positioning the camera * Start by naming the group that combines the geometry and the camera. ** Select the "Group1" node. ** In the NodeEditor set the "Name" control to "rootGroup" * Go to the SceneHierarchy and recursively expand the new scene by `Shift-left-clicking` on the arrow head next to "rootGroup". ** You should now see the camera in alongside the ball and plane in the 3D viewport. * Back in the NodeGraph, select "Group1" and create an "AimConstraint" node (`right-click`, _Scene -> Transform-> Aim Constraint_). ** This node will let us target the camera at the contents of the scene. * Make sure the output of "Group1" is connected to the left most input of the new aim constraint. * In the NodeEditor, click the folder icon next to the "Target" field. ** This will pop-up a dialog that allows you to browse the scene hierarchy and pick specific locations. ** We want to select the item our camera should be aimed at. ** So `double-click` on the "rootGroup" entry in the dialog and keep navigating until you find "sphereA" (rootGroup->geoGroup->sphereA). Select it and press OK. * Next we need to tell the AimConstraint what item it should be affecting. In this case we want to affect the camera. ** Still with the AimConstraint node selected, go to the NodeEditor and switch to the the "Filter" tab. ** Click the "Add..." button and select "PathFilter" from the drop down. ** Click the "+" button that appears to add a path field to the filter list. ** In this new field, type `/rootGroup/camera`. * Now the camera is constrained to point at the sphere. We want to move the camera from the default position, but it would be nice to see the result of the constraint whilst we do this. ** To make that happen, ensure the "AimConstraint" node is selected, then go the the Viewer and click in the circle icon on the top right of the Viewer panel. The centre of the circle should go white. ** This has 'pinned' the Viewer, so that even if you select different nodes in the graph, the Viewer will stay focused on the scene output from the "AimConstraint" node. * We can now select the "Camera" node and switch to the "Transform" tab in the NodeEditor. * Set "Translate" Y to 5. * Hold `Ctrl` and `left-click-drag` in the "Translate" Z field. You should see the camera moving backwards and forwards whilst maintaining its aim on the sphere. * Move the camera until you are happy with its placement. .Here we are viewing the output of the AimConstraint node, but editing the controls of the Camera node. image::images/autoGenerated_target/quickstart_tutorial_figGA.png[align="center"] === Setting up for render * Now that we have the layout of our scene defined, we want to do a quick test render to check everything is working ok. * To start setting things up for rendering, lay down a chain of three nodes attached to below the AimConstraint. We need: ** A "StandardOptions" node, ** A "Outputs" node, ** And a "RenderManRender" node. * The connection order of the two middle nodes doesn't matter, but the chain needs to start and end with the "AimConstraint" and the "RenderManRender" respectively. ** I.e. _AimConstraint -> StandardOptions -> Outputs -> RenderManRender * Alongside these nodes create a "Display" node (`right-click`,_Image -> Source -> Display_). This node does not take any inputs, so we don't need to connect it into the graph. Place it off to the side of the "RenderManRender" node. * Go back and select the "StandardOptions". ** This node is responsible for setting up the basic properties of your render, such as which camera to use and what resolution the resulting image should be. ** In the NodeEditor, expand the "Camera" controls group, then use the scene browser dialog to select "/rootGroup/camera" as the camera to use. * Now select the "Outputs" node. ** This node creates a list of outputs to generate when rendering (display drivers in RenderMan terms). ** In the NodeEditor, press the "+" button and select _Interactive -> Beauty_ from the drop down menu. This will create an interactive render buffer we can view within the Gaffer app. * In order to be able see the render, we want to pin the "Display" in the Viewer panel. This way we can interact with other nodes, but see the renders we execute as they happen. ** To achieve this, hover the mouse pointer over the "Display" node in the NodeGraph and `middle-click-drag`. Holding down the middle mouse button, move the pointer up to the Viewer panel, then let go. This should swap the Viewer focus to the "Display" node and set the tab to pinned all in one action. * At this point we will need to save the Gaffer script. In order to kick off a render Gaffer needs a file on disk to execute. ** Go to the menu bar and select _File -> Save as..._ and use the file dialog to save the session somewhere suitable. * Finally, select the "RenderManRender" node and in the NodeEditor, click "Execute". If everything has gone to plan, you should see a grey ball on a grey plane! ** If that doesn't work: ** 'Double check you have the Display node selected and active in the Viewer.' ** 'Try pressing `f` to frame the Viewer to the image - it is possible the image is panned off to one side' ** 'Look in the shell Gaffer was launched from for error messages' *** `Unable to find mapping for output path` 'could indicate that the camera specified in the StandardOptions has its name spelt incorrectly, or the hierarchy has changed since it was selected.' *** `ERROR : Display::setupServer : Address already in use` 'suggests communication with the frame buffer has failed for some reason. Do you have another Gaffer session open?' *** `ERROR : Dspy::imageOpen : Could not connect to remote display driver server : Connection refused` 'probably means you are missing a Display node, so there is nothing to receive the pixels being sent. Add a Display node and try again.' .The rendered image shown in the Viewer. image::images/autoGenerated_target/quickstart_tutorial_figHA.png[align="center"] === Assigning some shaders * Grey balls are all well and good, but we want to take a first pass at assigning some shaders to the geometry. * To make the scene more interesting we're going to add a second sphere to sit alongside the first. ** In the NodeGraph select the "SphereA" node. ** Press `Ctrl-c` then `Ctrl-v` to copy and paste a duplicate of the original node. ** Using the NodeEditor, rename the new node to SphereB and change the "Name" control to "sphereB". ** On the "Transform" tab, set the "Translate" X value to 4. ** Back in the NodeGraph, drag from the output nodule of the SphereB into the right most plug of the "Group" node. ** Use the `middle-click-drag` to view the "Group" node in the Viewer tab. ** By default, you will just see the top level bounding box. Use the SceneHierarchy to expand the scene tree. * Now, go back to the NodeGraph and rearrange the nodes to make room in between the "AimConstraint" and the "StandardOptions". * Select the "AimConstraint" and then create a "ShaderAssignment" node (_Scene -> Attributes -> Shader Assignment_) ** This node is responsible for attaching shader definitions to items in the scene hierarchy. * We want to create a shader to assign, so click off in the space to the left of the "ShaderAssignment" and create another node: _RenderMan -> Shader -> demoSurface_ [NOTE] This is a simple surface shader distributed with the Gaffer Documentation. As noted earlier, you will need to add "$GAFFER_ROOT/doc/examples/shaders" to your $DL_SHADERS_PATH in order for it to appear in the RenderMan->Shader menu. This menu is dynamically built to contain all the shaders found on the path. * Drag from the output of the new shader node over to the right most plug on the "ShaderAssignment" node, creating a connection between them. * So that we can quickly see the result of this shader, set its "ambientCol" parameter value to 1,0,0 via the NodeEditor. * The last step we need to complete is telling Gaffer which objects to assign this shader to. For this we need a path filter: ** Select the "ShaderAssignment" node, then click the "Add..." button. ** From the drop-down select "PathFilter". ** One the path filter has been added, go to the SceneHierarchy editor and expand the tree so that you can see "sphereA" listed. ** `left-click-drag` on the "sphereA" entry in the SceneHierarchy and move the pointer up to hover over the path filter "+" in the NodeEditor. ** Release the mouse, and you should see the path to this item added as a row in the filter. * Following the same steps from the last section, kick off a render, and view the results by pinning the "Display" node. .Now we have a garish red shader assigned to sphereA. image::images/autoGenerated_target/quickstart_tutorial_figIA.png[align="center"] === Expanding the shader assignments * Attaching shaders to objects one by one is a bit tedious and not very flexible. ** Gaffer helps address this by supporting expressions in paths. * Here we'll demonstrate a brief example of this by assigning the same shader to items with similar names. * Simply change the path in the "ShaderAssignment" filter from "/rootGroup/geoGroup/sphereA" to "/rootGroup/geoGroup/sphere*****" ** The "*" character acts as a wild card, matching any object at that path with a name that starts with "sphere". ** So both "sphereA" and "sphereB" are matched and the shader assigned to both. .Two garish red balls. image::images/autoGenerated_target/quickstart_tutorial_figIB.png[align="center"] === Adding a light * To make our scene a little more interesting, let's add some light and shadow. * First off, create a new "demoSurface" shader and assign it to the "plane" geometry using the steps covered in the previous two sections (i.e. add a new 'ShaderAssignment", connect the shader, and set up a path filter). * Change the labels on the two shader nodes to "ballSurface" and "floorSurface". * Use the NodeEditor to set the parameters on the two shaders to match the following: .ballSurface [options="header",cols="20%,80%"] |======================= |Parameter|Value |Diffuse Col| 0.5, 0.18, 0.18 |Specular Col | 1.0, 1.0, 1.0 |Specular Roughness| 0.25 |Ambient Col|0.0, 0.0, 0.0 |====================== .floorSurface [options="header",cols="20%,80%"] |======================= |Parameter|Value |Diffuse Col| 0.18, 0.5, 0.18 |Specular Col | 0.0, 0.0, 0.0 |Specular Roughness| 0.25 |Ambient Col|0.0, 0.0, 0.0 |====================== * Now we want to add a light to our scene to illuminate the geometry. * Create a "demoLight" node (_RenderMan -> Shader -> demoLight_) and place it up towards the top of the node network. * Unlike the surface shader, the light shader actually generates a scene - albeit a scene with just a single light in it. ** With the "demoLight" node selected, look in the SceneHierarchy editor. You should see an item in there called "light". This is the name of the light object as defined by the "Name" control on the node - so go ahead and change it to something meaningful such as "keyLight". * We need to join this light into the hierarchy along with the rest of our scene contents, and the easiest way to do that will be to connect it into the existing "Group1" node. Drag the output from "demoLight" to an empty plug on "Group1". * Select "Group1" and explore the SceneHierarchy to see where the "keyLight" item has been placed. * Now go back to the "demoLight" node and modify some of its settings: ** Intensity : 2.0 ** Translate X : -2.0 ** Translate Y : 5.0 ** Translate Z : 2.0 * Kick off a render and inspect the results! .Much more tasteful. image::images/autoGenerated_target/quickstart_tutorial_figJA.png[align="center"] === Processing the result * The render is a little on the dark side, so we will apply a simple grade in order to brighten our image. * Gaffer has image processing operations as well as 3D scene processing, and the "Display" node is in fact a source generator for the 2D aspect for the app. * This means that the steps to colour process the render are quite simple: ** With the "Display" node selected create a "Grade" node (_Image -> Colour -> Grade_) ** Make sure this node is active in the Viewer ** In the NodeEditor, `right-click` on the "Gain" control and select "Gang" from the pop-up menu. This makes the three sliders of the colour control change in unison. ** `Ctrl-left-click-drag` in the "Gain" R field and adjust the exposure of the image until it's nice and bright. .Image processed using the GafferImage module image::images/autoGenerated_target/quickstart_tutorial_figKA.png[align="center"] That is where we will leave the demo for now; having covered the basics of constructing a 3D scene, setting up renders, assigning shaders, and creating lights. The results have a certain "1985" feel right now, but hopefully you have gained some sense of how this approach could be applied to more sophisticated content. [NOTE] Even though in this demo we have made use of Gaffer's primitive generators to construct the base scene, it is expected that in the majority of cases Gaffer scripts will be processing cached input (for example alembic scene files). There is still use for the scene processing operations (e.g. grouping lights, transforming instances) but complex hierarchies are expected to normally be generated outside of Gaffer.