Linux for CG – APT

APT (Advanced Packaging Tool) is a collection of tools to install and manage software packages on Debian and it’s various off shoots (for example Knoppix and Ubuntu). Much like installing software on other operating systems, a package can contain multiple executables (programs).

Some useful packages for CG work include..

In order to install these packages, these are the typical steps that one needs to go through.

Note that APT requires superuser (administrator) privileges which means you have to prefix the sudo command in front of the command. It’s likely if your an artist in a large CG studio that you won’t be a superuser, so these instructions only really apply if your wanting to setup linux at home or in a small studio environment.

The first thing you need to do is get an up-to-date list of all the available packages from the internet.

> sudo apt-get update

The next step is to search for the name of the packages your interested in. APT allows you to do simple word searches for packages

> sudo apt-cache search [package]

Once you’ve found the package your after…

> sudo apt-get install [package]
ie... sudo apt-get install openexr

If the package exists it will download and install the package on your computer, ready to go – no need to restart the computer. Although sometimes you may need to open a new shell in order to pick up any changes. Once that’s done you can upgrade any existing packages on your system by using…

> sudo apt-get upgrade

As an illustrated example, to install the openexr commands you’d run the following series of commands…

> sudo apt-get update
> sudo apt-cache search openexr
> sudo apt-get install openexr

To check if it’s installed the openexr commands correctly try run either exrmaketiled or exrstdattr on the command-line.

 

 

 

OSL – BlackBody Colour

This node outputs a normalised colour given an input temperature in degrees Kelvin. This can be used as an input for lights to give the effect of different colour temperatures.

Download Here

BlackBodyColour Controls
BlackBodyColour Controls
  • Temperature: Temperature in degrees Kelvin.

 

OSL – Constant Surface

This shading node acts as a constant surface shader. It can be used to output flat colour without any shading (diffuse, specular, etc) on an object.

Download Here

Constant Controls
Constant Controls
  • EmissionOn: When set to 0 it will only compute the InColour for Camera rays. This prevents it from bleeding light onto surrounding surfaces. When set to 1 it will behave as OSL intended it as act as an emissive light, which bleeds light onto surrounding surfaces.
  • InColour: The input colour. Can be constant or texture.

Note that when EmissionOn is set to 1 it will take a lot longer to compute than when EmissionOn is set to 0.

OSL – ColourSwitch

This shading node does a binary switch between two input colours. Potentially useful if you want to test out two different textures or colour settings and don’t wish to rewire your shading network.

Download Here

ColourSwitch Controls
ColourSwitch Controls
  • Which: Which colour input to use. 0 = InColour0 and 1 = InColour1.
  • InColour0: Input Colour 0
  • InColour1: Input Colour 1

 

OSL – Exposure

This shading node applies an exposure adjustment to the input colour. This allows you to manipulate the colour using photographic stops.

Download Here

Exposure Controls
Exposure Controls
  • Active: Disable the effect by setting this to 0. This allows you to disable the adjustment without having to rewire your shading network.
  • InColour: The input colour. This can be any type of colour (texture, constant, etc)
  • Exposure: Measured in stops. Each stop will increase (double) or decrease (halve) the brightness.

Post DOF vs Rendered DOF

Although it’s far more common to render 3D images without Depth-Of-Field (DOF) as it renders quicker and offers some flexibility in compositing. In some situations that isn’t always the case as large ZBlur’s within Nuke can take a heck of a long time to render. In fact depending on your scene and your renderer it’s often quicker to render DOF in 3d than it is to apply it as a post process in 2d.

Post DOF

  • Flexibility in compositing. Can adjust effect as needed.
  • Quicker to render.
  • Can be inaccurate – no physically based parameters (although this is largely dependant on the plugin used. The effect is driven by the artist.
  • Large blurs are slow to render.
  • Prone to artifacts. Can’t handle certain situations at all without lot’s of hackery.

Rendered DOF

  • No Flexibility in compositing.
  • Slower to render.
  • Accurate. Physically based parameters.
  • Requires more pixel samples in order to avoid noisy renders.

The following render was done at 2048×1556 and was rendered without any DOF. The total render took 83 seconds. The Depth AOV was rendered using a Zmin filter with a filterwidth of 1×1 in order to avoid anti-aliasing in the render.

Click to see full resolution.

I also rendered the same image with DOF on.

Click to see full resolution.

Unfortunately my plan to show the difference between the two full resolution images was put on hold by Nuke taking far too long to render the full resolution ZBlur. I gave up after 10 minutes so decided to concentrate on a particular region.

Crop region used.

The following 1:1 crop demonstrates the difference between Post DOF and Rendered DOF.

Keep in mind that the Nuke time for the Post DOF was only for the crop area your seeing above – it was taking too long to render the full image with Post DOF. As you can see the Post DOF breaks down quite heavily in some places, while the rendered DOF image did take longer to render, it’s much more accurate and the read time of the image is less than a second in Nuke.

Observations…

  • The rendered DOF spent less time ray-tracing and more time spent on sampling the image. This was due to the increase in pixel samples in order to get less noisy results and higher focus factor.
  • With pixel samples at 3×3 the DOF render took 57 seconds, faster than the 83 seconds that it took to render the Non-DOF version although the final result was unacceptable. For less extreme blurs pixel samples could be set as low as 6×6.
  • Focus Factor parameter in 3Delight helps speed up DOF renders by reducing the shading rate in areas of high blur with very little perceivable difference.
  • Despite some noise, the end result is much more visually pleasing than the ZBlur result in Nuke.

 

 

Salamander Sculpt

After many years I’ve finally bit the bullet and decided to learn ZBrush in earnest. This is the first of my sculpting endeavours…

Blocking out the main features. I’m not entirely sure on the nostrils at the moment, which is why they’re rather faint.

I’m referring to it as a salamander at the moment, but so far I’ve primarily been working without reference, so it’s kind of morphed into a hippo-lizard hybrid.

Head of a hippo, body of a lizard. Let’s say I was originally aiming for a creature which was more gelatinous than well-formed. šŸ˜‰

 

A Recipe for Creating Environment Maps for Image Based Lighting

This is the recipe I use for creating environment maps for use in image based lighting. While the example I’m going to use specifically involves a chrome ball, a lot of this also applies to environment maps captured by taking panoramic photos.

Goals and Flow

The two main goals of this technique are to…

  1. Maintain consistent and high-quality results.
  2. Make things as easy and automated as possible.

The first goal requires that we use image formats which allow floating-point colours and image processing techniques that degrade the image as little as possible.

In terms of balance between consistency and quality, I’d prefer to sacrifice quality in order to maintain consistency – this mainly becomes a problem when dealing when dealing with colour-spaces.

The second goal is to make things as uncomplicated and simple as possible. It’d also be nice to make as much of this as automated as possible so that large batches of images can be processed with minimal fuss.

If I was a bit more sorted my workflow would look some like this, where the raw image gets converted into an image which is worked with and then that gets converted into whatever output format I’m aiming for.

Ideal workflow.

However I’m not entirely keen on bring raw images directly into Nuke at the moment, primarily cause I’m not entirely happy with the results, so I’ve added an additional step to the process. This involves converting the raw image to an intermediate image, which at this stages means exporting the image out as a 16bit TIF with a gamma-encoded colour-space.

Current workflow.

So that means we’re aiming to use formats like OpenEXR or if push comes to shove we’ll use 16-bit TIF. We’re also going to try keep any colourspace conversions or resampling of the images to a bare minimum.

The Ingredients

  • Adobe Lightroom – This is my personal preference, but your probably able to get similar (or perhaps even better) results using other raw converters.
  • The Foundry’s Nuke – This works well with processing large batches of images and has good colour support. It also has a handy little node for converting mirror ball images into lat-long images.
  • J_Ops for Nuke – Primarily for the J_MergeHDR node, but it also containsĀ  J_rawReader which allows you to read camera raw images within Nuke.

Preparing in Lightroom

The first goal after importing your images is to zero out any default tonal adjustments made by Lightroom, for this I apply the General – Zeroed preset in the Develop module.

Zeroed preset applied in Lightroom.

From here I export with the following settings…

  • Format: TIF
  • Compression: None
  • Colourspace: sRGB
  • Bit-Depth: 16bits per component
  • Image resizing: None

With regards to the colourspace, I’ve chosen sRGB because it’s the easiest colourspace to deal with. Ideally I’d like to use ProPhoto as it has a larger colour gamut, but I’m still working on the finer details of using ProPhoto within Nuke.

Hopefully the ACES colour-space will become more common in the future as it has a much larger colour gamut and is linear, but at this stage software support for it is limited.

In Nuke

Once you bring in all your images that you exported from Lightroom. The first thing you want to do is crop the image to the boundaries of the chrome ball. It’s best to get the crop as tight as possible.

Cropping in Nuke, the radial node is used to visualize the crop by overlaying a semi-transparent circle on top.

I use a radial node into order to visualise the crop to make sure things are lining up. You can also copy the settings from the radial node onto the crop node.

You can copy values by clicking and dragging from one curve icon to another.

A couple of little tips here, the first is to use whole pixel values (ie… 2350) for your crop values rather than sub-pixel values (ie… 2350.4). The reason for this is that Nuke will resample the image is you use sub-pixels – if your not careful when resampling an image you can lose quality and introduce either softening or sharpening to the image.

The second tip is if you want to maintain a perfect square when cropping. In order to do so click in the area.y attribute on the radial node and press the = key. In the expression editor that pops up enter…

area.t - (area.r - area.x)

Now when you adjust the top and side edges, the bottom edge will adjust itself automatically so that it maintains a square 1:1 ratio.

Merging into an HDR image

Once I’ve set up the crop on one image, it’s just a matter of copying the same crop node onto all the other images and plugging all of those into a J_MergeHDR node.

Cropped chrome ball images plugged into a MergeHDR node. Click for larger image.
MergeHDR node settings.

The first thing to do is click on the Get Source Metadata button to read the EXIF information off the images. The second thing to do is to set the target EV. You can either do this by setting the target ISO, Aperture and Shutter settings or by clicking on the EV Input checkbox and then manually setting a target EV value (I’ve set it to 12 in the above image).

Using the EV values we can also match exposures between images shot with different ISO, Aperture and Shutter settings.

The EV values can be used to match exposures on two images shot with different ISO, Aperture and Shutter settings.

In the example above we can use the difference between the two EV values (5.614 and 10.614) in order to match the exposure on one to the other. The difference between the two is approximately 5 stops (10.614 – 5.614 = 5), so if we apply an exposure node to the brighter image and set it to -5 stops, we can get a pretty good exposure match between two images. Although the example below is perhaps a bit extreme – as there are plenty of clipped values – in certain areas the exposures match up pretty well.

Where this potentially comes in useful is matching reference photography where automatic settings were used. If you don’t want to figure out the differences yourself, you can plug a MergeHDR node into each image and then set the target EV on all the MergeHDR nodes to the same value.

Applying an exposure node to the over exposed image and setting it to -5 stops.

From Chrome Ball to Lat-Long

The penultimate step in the puzzle is to convert the chrome ball into a lat-long image. This is easy using the SphericalTransform node in Nuke.

SphericalTransform node plugged into a MergeHDR node.

The settings to use are…

  • Input Type: Mirror Ball
  • Output Type: Lat-Long Map
  • Output Format: Any 2:1 image format (ie… 4096×2048, 2048×1024, 1024×512, 512×256)

Exporting from Nuke

The very last step is to write it out as an EXR and make sure the colourspace is linear.

 

Colour Temperature in Maya

For a while I’ve wanted to implement colour temperature control into my lighting workflow but I’ve never been able to figure out how it’s calculated. Then I came across this site, which has already mapped out blackbody temperatures to normalised sRGB values.

Using this as a starting point I mapped out the values into a SL function…

color blackbodyfast( float temperature;)
{
	uniform color c[16] = 
		{
		(1,0.0401,0),(1,0.1718,0),(1,0.293,0.0257),(1,0.4195,0.1119),(1,0.5336,0.2301),
		(1,0.6354,0.3684),(1,0.7253,0.517),(1,0.8044,0.6685),(1,0.874,0.8179),(1,0.9254,0.9384),(0.929,0.9107,1),
		(0.8289,0.8527,1),(0.7531,0.8069,1),(0.6941,0.77,1),(0.6402,0.7352,1),(0.6033,0.7106,1)
		};
	float amount = smoothstep ( 1000, 10000, temperature );
	color blackbody = spline ( "catmull-rom", amount, c[0],
		c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],
		c[10],c[11],c[12],c[13],c[14],c[15],
		c[15]);
	return blackbody;
}

I decided rather than map every temperature value from 1000K to 40000K, I decided just to deal with 1000K to 10000K using the CIE 1964 10 degree Colour Matching Functions – only because of the later date of 1964, I couldn’t see (nor greatly understand) the difference between the colour matching functions. The original function I wrote called blackbody used every value of the kelvin scale from 1000K to 10000K, this resulted in an array of 90 values. The modified one above uses every 6th value which brings the array size down to 16 values, in my tests I didn’t notice a speed difference using 90 values, but looking at a comparison of the two functions I couldn’t see enough visual difference to bother using the full 90 steps.

Blackbody temperature comparison in sRGB. Temperature is mapped to T coordinate.

There is a slight peak where the warm and cool colours meet in the 90 step version. It’s a bit more obvious looking at the image in linear light.

Blackbody temperature comparison in Linear. Temperature is mapped to T coordinate.

Because the values are in sRGB, they need to be converted to Linear before getting used in the shader. The SL used in the main body of my test surface looks something like this…

#include "colour.h"

surface blackbody_srf(
	uniform float temperature = 5600; #pragma annotation temperature "gadgettype=intslider;min=1000;max=10000;step=100;label=Temperature;"
)
{
	color blackbody = blackbodyfast (temperature);
	blackbody = sRGB_decode(blackbody);
	Oi = Os;
	Ci = blackbody * Oi;
}

Used in a light shader the output looks something like this…

Blackbody temperature. Light intensity is the same throughout. sRGB.

The only problem now is that 3Delight doesn’t show a preview of light shader or more importantly the colour temperature in the AE settings for my light.

To get around this I decided to implement an expression which changed the colour of the Maya light that my 3Delight shader was attached to. Because MEL doesn’t have a spline function like SL does I had to improvise using animation curves. First up the MEL to create the three curves that I need to create the RGB colour temperature.

$red = `createNode animCurveTU`;
$green = `createNode animCurveTU`;
$blue = `createNode animCurveTU`;

setKeyframe -itt "spline" -ott "spline" -t 1 -v 1 $red ;
setKeyframe -itt "spline" -ott "spline" -t 10 -v 1 $red ;
setKeyframe -itt "spline" -ott "spline" -t 11 -v 0.929 $red ;
setKeyframe -itt "spline" -ott "spline" -t 12 -v 0.8289 $red ;
setKeyframe -itt "spline" -ott "spline" -t 13 -v 0.7531 $red ;
setKeyframe -itt "spline" -ott "spline" -t 14 -v 0.6941 $red ;
setKeyframe -itt "spline" -ott "spline" -t 15 -v 0.6402 $red ;
setKeyframe -itt "spline" -ott "spline" -t 16 -v 0.6033 $red ;

setKeyframe -itt "spline" -ott "spline" -t 1 -v 0.0401 $green;
setKeyframe -itt "spline" -ott "spline" -t 2 -v 0.172 $green;
setKeyframe -itt "spline" -ott "spline" -t 3 -v 0.293 $green;
setKeyframe -itt "spline" -ott "spline" -t 4 -v 0.4195 $green;
setKeyframe -itt "spline" -ott "spline" -t 5 -v 0.5336 $green;
setKeyframe -itt "spline" -ott "spline" -t 6 -v 0.6354 $green;
setKeyframe -itt "spline" -ott "spline" -t 7 -v 0.7253 $green;
setKeyframe -itt "spline" -ott "spline" -t 8 -v 0.8044 $green;
setKeyframe -itt "spline" -ott "spline" -t 9 -v 0.874 $green;
setKeyframe -itt "spline" -ott "spline" -t 10 -v 0.9254 $green;
setKeyframe -itt "spline" -ott "spline" -t 11 -v 0.9107 $green;
setKeyframe -itt "spline" -ott "spline" -t 12 -v 0.8527 $green;
setKeyframe -itt "spline" -ott "spline" -t 13 -v 0.8069 $green;
setKeyframe -itt "spline" -ott "spline" -t 14 -v 0.77 $green;
setKeyframe -itt "spline" -ott "spline" -t 15 -v 0.7352 $green;
setKeyframe -itt "spline" -ott "spline" -t 16 -v 0.7106 $green;

setKeyframe -itt "spline" -ott "spline" -t 2 -v 0 $blue;
setKeyframe -itt "spline" -ott "spline" -t 3 -v 0.0257 $blue;
setKeyframe -itt "spline" -ott "spline" -t 4 -v 0.1119 $blue;
setKeyframe -itt "spline" -ott "spline" -t 5 -v 0.2301 $blue;
setKeyframe -itt "spline" -ott "spline" -t 6 -v 0.3684 $blue;
setKeyframe -itt "spline" -ott "spline" -t 7 -v 0.517 $blue;
setKeyframe -itt "spline" -ott "spline" -t 8 -v 0.6685 $blue;
setKeyframe -itt "spline" -ott "spline" -t 9 -v 0.8179 $blue;
setKeyframe -itt "spline" -ott "spline" -t 11 -v 1 $blue;

rename $red "colourTemperatureRed";
rename $green "colourTemperatureGreen";
rename $blue "colourTemperatureBlue";
The resulting animation curves.

Then the next stage was to create an expression which linked the outputted colour temperature to the light colour.

float $r, $g, $b;
if (will_point_lgt1.colourType > 0)
{
	$temp = will_point_lgt1.temperature;
	$amount = `smoothstep 1000 10000 $temp`;
	$c = 16 * $amount;
	$r = `getAttr -t $c colourTemperatureRed.output`;
	$g = `getAttr -t $c colourTemperatureGreen.output`;
	$b = `getAttr -t $c colourTemperatureBlue.output`;
}else{
	$r = will_point_lgt1.lightColourR;
	$g = will_point_lgt1.lightColourG;
	$b = will_point_lgt1.lightColourB;
}
point_lgtShape.colorR = $r;
point_lgtShape.colorG = $g;
point_lgtShape.colorB = $b;
Previewing the light inside Maya. The Maya-specific settings of this light are ignored in the final render.

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