Monday, December 1, 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 and examined using a very simple scene.

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 “No Decay” (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, brightening values, reducing color saturation, tweaking 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. Which one you prefer is of course a matter of taste, but if you’re aiming at photo-realism the gamma corrected 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 gamma corrected 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 (the ones used for the very first rendered image at the start of this tutorial):



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 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 modulate 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 could claim that the image is linear to the actual reflectivity of the planet surface, and thus in no need of gamma correction. I have no idea if this is true, but as the image is mainly black and white (not much gray), changes to the gamma would have little effect anyway. Why bother adding a gamma node that makes no noticeable difference?



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) are generally to be considered linear (not gamma encoded) regardless of the actual bit depth of the format in question. (Many HDR formats are not actually linearly encoded, but they are most often decoded to linear space by applications able to read 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 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.
  • 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. The behavior of different applications will have to be individually determined.

6. The Limitations of our Approach
There are two or three issues that the gamma corrected workflow described here does not solve in a satisfying manner. The least of these is that the gamma correction is applied as a post process, meaning that you cannot evaluate rendered tiles as they appear in the render view; you have to wait until the entire image has rendered, and the gamma correction been applied, until you can judge the lighting. This is annoying, but not really a serious problem.

The second problem is a bigger one. When we gamma correct file textures, the idea is to convert them from the sRGB color space into linear space for rendering. But the actual equation used for such a transformation is slightly more complicated than a simple gamma of 0.454545... Even though you can do the actual sRGB transformation in Maya (I will supply a MEL script for this in an upcoming tutorial), there is still a problem with doing this after the file node. The image needs to be linear before any processing is done on it, but the file node itself will actually filter the image, and optionally even color correct it. This will induce gamma related errors, something that cannot be fixed by simply gamma correcting the image afterwards. Luckily, these gamma induced errors are fairly minor in nature and can often be ignored, but it is still annoying. Maya should offer the ability to do proper color space conversions from within the file node itself, but until they do, the only option is to work with linear file textures, or to live with somewhat imperfect conversions.

The third problem is the biggest of them all. The rendered image is not the only thing that needs gamma correction to be correctly displayed: Maya’s own user interface has several features that need this exact same treatment. Whenever you select a color using the color picker, you’ll need to remember that this is a linear color value you’re selecting and that it will be much brighter in the rendered image. This can be very unintuitive. Same thing goes for swatches and previews of any kind. They will not correctly reflect the rendered result, as they are not gamma corrected. Even the hardware shaded modes in the view ports cannot be gamma corrected, making them far less useful. The fact that Maya offer no gamma management of the UI is unfortunate, as it makes a gamma corrected workflow less straightforward. Perhaps Autodesk prefer we all switch to Softimage XSI 7 were such settings are now available? (Check out the Color Management section towards the end of this page if you want to know how it’s done in XSI.) [Note: Autodesk probably won’t mind us switching to Softimage anymore, as they now own it…]


7. About the "Linear Workflow"
What we have been talking about so far is gamma management when rendering in Maya, and this has been done by what is most appropriately called a “gamma corrected workflow”. 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 instead. 

Compositing is also something that should be done in linear color space. All sRGB images should be converted before use, and you’ll use a viewer LUT to gamma correct on the fly as you’re working. The principle is exactly the same as for lighting/rendering; operate on linear data while displaying gamma corrected data. But if the first thing the compositor will do is remove the gamma encoding, why gamma encode in the first place? This will not only mean extra work, but also introduce unnecessary rounding errors. Same thing goes for the images used as file textures. If it is possible to have them be linear as well, there would be no need to gamma correct them from within Maya.

Keeping files linear throughout the entire pipeline can actually be quite beneficial, and this philosophy is most often referred to as the “linear workflow”, but it does come at a price.

The main issue with this approach is that linear images need to have a color depth of 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, then gamma correct (or apply some more accurate form of color space transformation), and finally downsample to 8 bits once you’re done.

Another issue with linear image files, 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 images 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 unless one has 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 and make sure it’s at least 16 bits.


8. Do Not Give Up

Hopefully you are all eager to give this gamma corrected workflow stuff a try, but there is one piece of advice I’d like to impart on you before you leave: Do not give up! It might seem simple enough when you read the text above. It might even work well the first time you try doing this tutorial on your own. But once you start implementing this workflow in your own projects, problems will pop up. Things will not look and behave the way you are used to, and it is only a matter of time before you start doubting the whole concept. You must persist! It’s hard to re-learn something, but it will be worth it in the end.
 

9. Links and Downloads

4 comments:

Anonymous said...

Fantastic walk-through. My textures have been washed out and I have never been able to figure it out on my own. Big help, thanks alot.

Anonymous said...

Wow! Va fan fåru allt ifrån? Awesome dude! TNX!

Anonymous said...

Wow! Thanks a lot, I searched for a real long time till I found this tutorial, but it was worth the search.

Anonymous said...

Cheers for this. nicely written and easy to follow.