Renderman Development On Windows

Windows development for CG is always a bit of hassle as much of the tools out there come from development inside studios using Linux – where it’s often being much simply to build source code from scratch.

Pixar provide source code and examples for much of their plugins as developer examples. You won’t find source code for things like PxrSurface which contain Pixar’s secret sauces – but you will find quite a lot of useful ingredients to get you started.

The following is based on Renderman 22. Very specifically it’s worked for me on R22.2 and R22.3 – I’ve not tried earlier or later versions – but hopefully much of this applies to R21 and other points releases of R22.

To get the developer examples, run the Renderman Installer and when you get to the packages to install click on Show All. The Examples will be downloaded to your Downloads folder as a compressed archive (use 7zip to extract it)

Image showing dialog box from Renderman Installer application.
Click the Show All box when running the Installer application.

I’ve been using Visual Studio 2017 Community Edition to do this.

In order to compile the examples on Windows using Visual Studio, the easiest way I’ve found is to use the Visual Studio Command Prompt.

>cd D:\scenes\rman\dev\PixarRenderMan-Examples-22.2_1903500-windows10_vc14icc170.x86_64\plugins\pattern\color
>cl -c "-I%RMANTREE%\include"  /D "WIN32" /D "_WINDLL"  /EHsc  PxrMix.cpp
>link /out:PxrMix.dll /dll "/libpath:%RMANTREE%\lib" "PxrMix.obj" libprman.lib

This should give you a DLL file, you can copy this into your Documents/rfm folder in order to use in Renderman, however in order to use it in RfM you’ll need to have a Args file which defines it’s parameters. Args files come from Katana and Pixar uses them to define the UI of plugins in both Katana and Maya.

The easiest way to create an Args file is just modify an existing one. For example, if you look in the $RMANTREE/lib/plugins/Args you’ll find the current ones (including PxrMix from the above example).

Rendering Overscan in Maya

There are a few attributes in Maya you can change in order to render the image with overscan. The first is resolution, while the second is either camera scale, focal length, field of view, camera aperture, camera pre-scale, camera post-scale or camera shake-overscan. I use camera scale as it’s more intuitive numbers you need to enter and it doesn’t mess with the camera aperture, focal length or field of view.

In order to render and work with overscan correctly, it needs to be done relative to your format your working with – this is typically your final output resolution inside Nuke, but it could also be the resolution of a matte-painting or a live-action plate. The way to figure out the amount of overscan to use is simple and we can use one of two methods, either based on a multiplier or based on the amount of extra pixels we want to use.

The simplest method to me is based on a multiplier. If our format size is 480*360 (as above) and we wanted to render the image with an extra 10%, we multiply the resolution by 1.1 and set the camera scale to 1.1. Like so…

Then in Nuke all we need to do is apply a Reformat node and set it to our original render format of 480×360, the resize type=none and keep preserve bounding box=on  – this has the effect of cropping the render to our output size but keeping the image data outside of the format. Or additionally you can set the reformat like so… type=scale; scale=0.90909091; resize type=none; preserve bounding box=on. Instead of typing in 0.90909091, you can also set the scale by just typing in 1/1.1 …

If we instead wanted to render an extra 32 pixels to the top, bottom, left and right of our image – making the image 64 pixels wider and higher – we need to do things a little bit differently as we need to change the camera aperture. The reason for doing this is that adding the same number of pixels to both the width and height results in a very slight change to the aspect ratio of the image.

new width = original width + extra pixels
new height = original height + extra pixels
overscan width = new width / original width
overscan height = new height / original height
new aperture width = original aperture width * overscan width
new aperture height = original aperture height * overscan height

So using our 480×360 example from above. If we wish to add an extra 64 pixels to the width and height we would calculate it like so…

480 + 64 = 544
360 + 64 = 424
544 / 480 = 1.13333333
424 / 360 = 1.17777777
1.417 * 1.13333333 = 1.606
0.945 * 1.17777777 = 1.113

Same as before in Nuke we then apply a Reformat node with the following settings. type=to box; width/height=480, 360; force this shape=on; resize type=none; preserve bounding box=on

More VRay Scene Access… or some more random tidbits

Following on from the last post. Here are another example of how you can mess around with VRay scenes using Python.

figure 1: transform += random() * 2, random() * 2, random() *2

This collection of cubes was created using only one cube, it’s been instanced 2500 times and moved about randomly, to do this I’ve used the random module in Python which is handy for doing random number things.

# figure 1
from vray.utils import *

import random as r
r.seed(1)

l=findByType("Node") # Get all Node plugins
v=Vector(0.0, 0.0, 0.0)
for x in range(2500):
	dupl = l[0].duplicate('dup' + str(x))
	t=dupl.get('transform')
	v = Vector(r.random()*2, r.random()*2, r.random()*2)
	t.offs += v
	dupl.set("transform", t)

The r.send(1) is used to create a seed point for any future calls to random module, this means that the random numbers chosen are going to be the same each time we render the image – if we’re making changes to the render we don’t want the position of the cubes to change each time we render.

The v variable is used to store the random number we’re using to offset the transform, at the moment this is just is using random.random() which produces random values between 0 and 1, in the above example this has the effect of moving the cubes only along the positive xyz axis. There is also random.uniform(min,max) which produces random values between the min and max numbers we give it.

figure 2: transform += uniform(-1,1) * 2, random() * 2, random(-1,1) * 2

Here the effect moves the cubes along positive and negative XZ. I’ve keep the Y axis in positive space so that the cubes don’t go through the ground plane.

# figure 2
from vray.utils import *

import random as r
r.seed(1)

l=findByType("Node") # Get all Node plugins
v=Vector(0.0, 0.0, 0.0)
for x in range(20):
	dupl = l[0].duplicate('dup' + str(x))
	t=dupl.get('transform')
	v = Vector(r.uniform(-1,1)*2, r.random()*2, r.uniform(-1,1)*2)
	t.offs += v
	dupl.set("transform", t)

OpenEXR and 3Delight

The OpenEXR format has a number of useful features which are super handy for CG animation and VFX such as saving the image data in either half or full floating point, setting data-windows and adding additional metadata to the the file. 3Delight for Maya allows you to use all these features, but doesn’t cover how to use them in the documentation (at least I couldn’t find mention of it).

In order to use gain access to these features you need you need to add an extra attribute to the render pass called “exrDisplayParameters”. In the example below, the name of my render pass is called “beauty”.

addAttr -dt "string" -ln exrDisplayParameters beauty;
setAttr "beauty.exrDisplayParameters" -type "string"
"-p \"compression\" \"string\" \"zip\" -p \"autocrop\" \"integer\" \"1\" ";

The string attribute should end up looking like so in the attribute editor…

-p "compression" "string" "zip" -p "autocrop" "integer" "1"

The above sets the compression type to zip and to also tells 3Delight to autocrop the image when it’s rendered. Auto-crop adjusts the bounding box of the data-window (or ROI, region-of-interest) to only contain non-black pixels (I believe it does this based on the alpha channel), this allows Nuke to process the image quicker as it only calculates information within that data-window. See this tutorial on Nuke Bounding Boxes and how to speed up your compositing operations.

The basic syntax of the parameter string is easy enough to understand, the three arguments passed to the -p flag are name, type and value.

-p "[name]" "[type]" "[value]"

You can also add additional metadata to the header of the EXR render. For example you may wish to include things such as

  • Project, scene and shot information.
  • Characters or creatures in the shot.
  • Model, texture, animation versions used.
  • Maya scene used to render the shot.
  • Focal length, Fstop, Shutter Angle, Filmback size.

3Delight already includes some metadata already with the EXR, so you don’t need to add information for the following…

  • Near and far clipping planes.
  • WorldToCamera and WorldToNDC matrices. The Nuke Python documentation has info on how you can use this to create cameras in Nuke based of this data.

You can add this metadata using the “exrheader_” prefix and then the name of your attribute. The following will add three metadata attributes called “shutter”, “haperture” and “vaperture”.

-p "exrheader_shutter" "float" "180" -p "exrheader_haperture" "float" "36" -p "exrheader_vaperture" "float" "24"

While the following will add the project name “ussp” and the maya scene name that was used to render the shot…

-p "exrheader_project" "string" "ussp" -p "exrheader_renderscene" "string" "h:/ussp/bes_0001/scenes/lighting_v01.ma"

The easiest way to get information from your scene to this parameter pass is to set up a Pre-Render MEL script in your render-pass along the lines of…

string $sceneName = `file -q -sn`; //Grab the name of the current scene.
string $projectName = `getenv "PROJECT"`; //This assumes you have an environment variable called "PROJECT" with the project name setup already.
string $parameters = "";
$parameters += (" -p \"exrheader_renderScene\" \"string\" \"" +  $sceneName + "\" ");
$parameters += (" -p \"exrheader_projectName\" \"string\"" + $projectName + "\" ");
setAttr ($pass + ".exrDisplayParameters") -type "string" $parameters;

See the 3Delight documentation has more information on what type of metadata you can add  to the EXR.