Saturday, August 9, 2008

Basic Gamma Corrected Workflow with the Maya Software Renderer

by means of the Gamma Correction render setting and Gamma Correct utility node


The purpose of this tutorial is to introduce a simple way of rendering by means of a gamma corrected workflow in Maya. We will stay with Maya’s own Software Renderer and limit ourselves to the most basic tools and settings. The fundamental principles will be demonstrated with the simplest of scenes before moving on to the lighting and rendering of a somewhat realistic environment.

1. Setting the Gamma Correction
The first thing one has to do is to properly set the Gamma correction parameter found in the Render Settings. It is located in the Maya Software tab under Render Options > Color/Compositing. The default value is 1 (no correction), but we need to set it to a value corresponding to your display’s gamma, which is normally about 2.2 (and if it isn’t, you should consider calibrating it so).



So what will this do to our renders? The purpose of this setting is to adjust the rendered image in such a way that it is suitable for display on a typical monitor. As a monitor will display a linear image (such as those produced by 3D-renderers) as too dark, our intention is to brighten the image before showing it on screen.

We need to be aware of the fact that by setting this parameter to 2.2 we are not actually performing a gamma operation with an exponent of 2.2, but rather one of 0.454545… This is because Maya is using the term “gamma correction” in the sense that the value given is what we want to compensate for, not the value we want to apply. To correct for a display gamma of 2.2, Maya will thus apply a value of 1/2.2 = 0.454545… This convention will tend to be confusing, but it is fairly common and we have little choice but to comply.




2. Test Rendering a Simple Scene
To see the effect of the gamma correction we will light and render a simple scene consisting of a ball and a cube on a plane. Light is provided by two Spot Lights, and three Blinn shaders will give us a reflective ground plane, a sphere that is something of a cross between a pearl and a cue ball, and a cube of perhaps chocolate.




As we want a measure of realism in our lighting, it is important that we set the Decay rate to Quadratic on both lights. This is how light works in real life, but it is not the default setting as it does not agree with the more common way of rendering (without gamma correction). For us it will work perfectly, and after a few minutes worth of tweaking we get this:



This is not an image worthy of any awards, but it will do nicely for our purposes. Now what happens if we turn off the Gamma correction (by setting it to 1)? The same scene will now render like this:



This is the linear intensity version of the gamma corrected image above. It is not really the image that is dark, it is your monitor displaying it that way, but as we need the monitor to see anything at all, it seems wise to use the option of Gamma correction to compensate for it.



3. Trying it the Old Way
The common objection at this point is of course that if one had not set the gamma correction before lighting, one would simply have lit the scene brighter instead. This is probably how you’ve always done it, but unfortunately this method will not lend itself to realistic lighting, as we are about to see. Let’s investigate by keeping the Gamma correction at 1 and instead brighten the image by increasing the light intensities:



For this render I tripled the intensity of each spot light. The highlights blow out long before the overall brightness gets close to our original image, resulting in extreme contrast. This is hardly surprising as increasing light intensities is a linear operation, and cannot compensate for the non-linear nature of gamma correction. We clearly need to change our lighting in more drastic ways to get a pleasing result. Let’s start from scratch and re-light the whole scene without the Gamma correction applied. First of all we need to turn off the physically correct quadratic decay rate of the spot lights. We set them to None (as is the default) and cut the intensities to match. It is soon apparent that tweaking the lights alone will not be enough, so we start adjusting the shaders as well, reducing color saturation, specular intensities and reflectivity. Although a better match can be achieved, it would be good to stop at a state where the difference between the two approaches is still clear, so let’s settle for this:



The contrast is still higher than before, but most of you will probably find this result quite familiar. This is how you are used to seeing 3D renders, and you might even find it more appealing than the first image. But which one is more realistic? Well, there is no debating it; the correctly lit and gamma corrected image we started out with is the more physically correct of the two. Let’s have a side by side comparison:



The differences seen here are quite typical for the linear vs. the traditional workflow. The gamma corrected image (left) is more photographic, while the image at the right has the more classical CG look of high contrast and saturated colors. The differences will tend to be greatest in the mid-range values, here clearly represented by the shadows. Which one you prefer is of course a matter of taste, but if you’re aiming at photo-realism the linear workflow will more easily accommodate you. It is not that the traditional way of lighting will make it impossible to get the look you want, it’s just that the tools will work against you and thus require more tweaking. This will be all the more apparent as you begin to gamma correcting renders employing lighting techniques such as Global Illumination and Final Gather, as these are explicitly intended to produce realistic results, but even with our simple scene this should be clear.

For the sake of completeness, I will continue to try to match the gamma corrected image:



This time the right image is probably as close as one can get by just tweaking light and material settings. It is by no means identical, but perhaps close enough for most production needs. The main point was not that this would be impossible, but that it would require more work and a more critical eye (I had to make many unintuitive adjustments to this last render; adding ambient components, setting individual shadow colors and other odd tings. The values used made little sense and had no basis in physics). Using a linear workflow will more easily result in physically correct lighting and better match photographic reference material or background plates.


If this is all there is to it, then why isn’t everyone doing it? Well, unfortunately there is plenty more to it (not that that’s an excuse), and the first problem we’ll face is the issue of file textures.



4. Gamma Correcting File Textures
Let’s add a texture to the sphere. Let’s say it’s now supposed to represent planet Earth. We create a nice color map that looks like this:



It is imported using a file texture node and connected to the color attribute of the sphere shader, giving us the simplest of shading networks:



Rendering the scene (still with the Gamma correction set to 1) we get this:



No surprises there. Now let’s set the Gamma correction to 2.2 again, and return to our original light and material settings:



Earth is looking a bit pale, don’t you think? Why is this? Well, the reason we gamma correct the rendered image to begin with is to make the linear light data suitable for display on screen, but this has already been done to our file texture once. Most normal images are in a color space known as sRGB, and this means that they have a gamma of 0.454545… already applied to them. If they hadn’t, they too would appear dark on a monitor, just as an uncorrected render would (should). This is known as gamma encoding, and is standard practice for most image formats. If a gamma encoded file texture is used in a render where the end result is gamma corrected, the textured surface will in effect have been corrected twice, making it overly bright.

There are two ways to address this issue; one is not to use textures in sRGB color space (you would instead convert them to linear color space before using them in Maya), the second is to remove the gamma encoding inside of Maya by means of a Gamma Correct utility node. We are going to employ the latter of these two methods. It is the simplest way to get around the problem, but unfortunately it is not quite as accurate as working with already linear textures. Let’s get it working first, and we’ll discuss the shortcomings later.

If you scroll down in the Create Bar of the Hypershade until you come to Color Utilities, you’ll find a utility node called Gamma Correct:



Inserting this node between the file texture node and the Blinn material will give us the ability to adjust the gamma of the Earth texture to our liking. Connect the file textures outColor to gammaCorrect1.value and the gammaCorrect1.outValue to the material color attribute:



Open the Attribute Editor for the gammaCorrect1 node and set all three Gamma values (one for each color channel) to 0.454545… (This is the gamma encoded in an sRGB image, and thus the value we want to “correct for”. The Gamma Correction node will actually perform a gamma operation with the reciprocal value of 2.2). The color data output can now be considered linear.

Re-rendering once again:



Pretty as a picture. Now let’s add a bump map.



Shouldn’t I gamma correct this texture as well? The answer is normally no, I should not. The reason for this is that a bump map does not contain light information, but height data. The purpose of the image is not to be displayed directly on screen, but rather to modify the normal direction of a surface, and there is no need for such information to be gamma encoded. It is of course possible that the bump map has been gamma encoded anyway, and this can happen for several reasons, but in this particular case it is linear and require no correction.

The new render looks like this:



Finally we’ll add a specular map to reduce the reflectivity of the land masses:



Now why shouldn’t this texture be gamma corrected? Well, it depends on the same thing as always; whether or not it is gamma encoded. This in turn will depend largely on how it was created. If the texture started out as a photograph, for instance, it will most certainly be gamma encoded. If you painted it by hand you should probably consider it gamma encoded as well (as you have been evaluating your painting by way of a monitor, you will unwittingly have compensated for the display gamma in the painting process). In the case of our Earth spec map though, I will claim that the image is linear to the actual reflectivity of the planet surface, and thus in no need of gamma correction. This isn’t true, but I thought it made for a slightly better picture, and that is all that counts in the end:




5. Gamma Encoded or Not Gamma Encoded?
The important thing here is apparently figuring out whether an image file read by the renderer is gamma encoded or not. Following are a few guidelines:


  • Most 8 bit images are gamma encoded, as are most 16 bit images.
  • 32 bit images are not gamma encoded.
  • HDR images (hdr, exr, pfm, raw) are always linear (not gamma encoded) regardless of the actual bit depth of the format in question.
  • There is no need to gamma encode information such as Alpha, Z-depth, bump/displacement maps, normal maps, or data of any sort not directly mapped to a color attribute. These types of images are not meant for direct viewing, and it makes no sense correcting them to “look good” on screen (as they don’t really “look” like anything at all). A gamma corrected render will not affect any channels other than R, G and B, so you generally do not have to worry about this when outputting auxiliary channels, but if you are rendering passes that output this kind of information to the color channels you must make sure not to gamma correct them.
  • Displacement and Normal maps generated by applications such as Z-brush and Mudbox are always linear. Color maps generated in a similar fashion are discussed below.
  • Images created by means of a painting application (such as Photoshop, Painter, and including color textures from 3D painting programs) should generally be considered gamma encoded if you evaluated the result by the “look” of the image (even if it is an alpha or a bump map you’re painting). If you have taken care to have certain values represent specific data (each step in value representing one millimeter difference in a displacement map, for instance) instead of “going by eye” then the image is not to be considered gamma encoded.
  • There are several ways in which you might unwittingly gamma encode an image without even being aware of it. For instance, opening a 32 bit image in an image viewer and saving an 8 bit copy will probably have changed the color space. The original 32 bit image was linear, but the 8 bit copy is now a gamma encoded sRGB image. This is because most applications capable of displaying floating point images (which are always linear) will gamma correct them immediately when reading the file.

6. Lighting a (Somewhat) Realistic Environment
Let’s continue by creating a basic interior scene. It will be more of an outline of the process than any detailed step-by-step instructions.

7. The Limitations of our Approach

8. What to View and What to Save?
As should be clear by now we gamma correct images for display purposes, but should we keep this correction when we write them to disc, thus gamma encoding them, or should we render linear images? The answer will depend on what the images are intended for. As long as you use a Gamma correction setting of 2.2 your renders can, for most practical purposes, be considered to be in sRGB color space. You can continue working with them in the same way as you always have, but if they are to be passed on for compositing there are several advantages to keeping the images linear (and this is of course one the cornerstones of the linear workflow). The main issue with this approach will be that linear images need to be rendered at 16 bits or more. The reason for this is a bit out of scope for this tutorial, but it is a question of perceptual uniformity. As a gamma encoded image is perceptually uniform it can get away with a color depth of only 8 bits per channel without introducing visual banding artifacts. A linear image is not perceptually uniform, and thus requires higher color resolution to be as visually adequate. Although I recommend you look into this if you are considering a thoroughly linear workflow, I will only supply you with the essential rule here: An image needs to be gamma corrected before being quantized to 8 bits for the result to be perceptually uniform. This means that you cannot render linear 8 bit images out of Maya and gamma correct them afterwards. You need to render at 16 bits, gamma correct (or apply some more accurate form of color space transformation) and downsample to 8 bits once you’re done.

How about a gamma corrected image saved from the Maya Render View? As is quite clear when you watch the rendering process in the Render View, the gamma correction is not applied until the entire image has finished; it’s a post process. This is very annoying in and of itself, but the important question is whether or not the image is perceptually uniform. The image displayed in the Render View is always 8 bits, and if the gamma correction is done as a post process the result should, for all intents and purposes, be useless. Luckily for us though, this isn’t the case. The gamma operation is not performed on the actual data presented in the Render View, but is done in floating point precision behind the scenes. The linear image is then swapped for the gamma corrected one once the render is finished. If a gamma encoded 8 bit image is what you want, then the one you get from the Render View is quite adequate.

Another issue with the rendering of linear images, besides the fact that they need be at least 16 bits, is that they will not display properly without being gamma corrected. This is not a problem for most compositing applications as they have viewer lookup tables (LUTs) specifically for this purpose, but it can be a bit of a hassle when you want to evaluate your renders by opening them in your favorite image viewer or sequence player. All high-end viewers are designed to manage this effectively, often even semi-automatically, but there are simpler applications out there that do not offer any control over gamma at all (the standard Windows Picture and Fax Viewer being an obvious example). Even Photoshop is going to cause you headaches.

These concerns are often enough for many to decide against working with linear image files, and if one does not have several consecutive processes that all benefit from working with linear data, that is a very sensible decision. It is simply a matter of weighing the pros against and cons. The only thing that is truly important is that you gamma correct the images while you’re lighting. If you like the image as it is, keep it that way. If you have adequate justification to supply the compositing artist with linear images, set the Gamma correction to 1 for final render.

9. Where to Go From Here

10. Preaching to the Converted
Hopefully you are all eager to give this linear workflow stuff a try, but there are a few things I’d like to impart on you before you leave.

11. Links and Downloads

  • MEL script to toggle the Gamma correction parameter
  • MEL script to insert a Gamma Correction Node (save selection, check if texture node, save texture name, create Gamma node, rename Gamma node according to texture name, set gamma to 1/2.2, connect everything properly, return selection)
  • “Introduction to a Linear Gamma Workflow for CG Artists”
  • Other tutorials

No comments: