Monday, July 28, 2008

This tutorial series is intended to be used with mental ray for Autodesk Maya 8.5.

“Happiness is like the sun: There must be a little shade if man is to be comfortable.” - Let's start our exercise with this little quote by Otto Ludwig.

Welcome to the first of the six-part tutorial series, discussing possibly the most challenging kind of 3D environment: interiors. mental ray (for Maya) users typically get cold feet and sweating fingers when it comes to this “closed combat”; the royal league of environment lighting. It’s for no reason though, as all you need for the battle is a simple field manual (this tutorial), and just a little bit of patience...

So what is it all about? Let’s have a look at our object for this demonstration (Fig. 1) ...

As you can see, we have a closed room; you can tell by the porthole and the characteristic door that it is a room inside a ship. Let’s imagine that it’s a tween deck of the ferry “MS No-Frills”, used as a lounge, and the staircase leads to its upper deck.

From a lighter’s point of view, we can estimate by this analysis that there is light coming in from a) the opening in the ceiling where the staircase leads outside, and b) from the porthole and the window beside it. That’s not much, and if you ever took a photograph under such conditions you will know that, even with nice equipment, you would have a hard time catching the right moment (the “magic hour”) to illustrate the beauty of this particular atmosphere. (Atmosphere is also defined, besides by the lighting condition itself, by things like a point in time, the architecture, the weather, and occasionally also the vegetation.)

So, for our first tutorial part, we will choose the following scenario: our ship, the MS No-Frills, is anchored somewhere along the shore of Tunisia (North Africa) in the Mediterranean Sea; it’s summer, the time is around early afternoon, and the weather is nice and clear. That’s all we need to know at this stage to get us started...

Fig. 1

If you open up the scene, you will see that there’s no proper point of view defined yet. Feel free to either choose your own perspective or use one of the bookmarks I have set in the default perspective camera (Fig. 2). By clicking on one of the bookmarks, all relevant camera attributes (position, orientation, focal length, etc.) are changed to the condition stored in the bookmark. This greatly helps when trying out different views without committing oneself, and without creating an unnecessary mess of different cameras.

Fig. 2

Before we start lighting and rendering the scene, we should have a little introduction to the actual shading of the scene and about a few of the technical aspects of things such as color spaces. If you find this too boring then you might want to skip the next two paragraphs as this is not essential, but is nonetheless an explanation regarding how to achieve to the result at the end of this tutorial.

A Note on Shading.

All the shaders you see are built on the new mia_material that ships with Maya 8.5. This shader was intended as a monolithic (from the Greek words “mono”, meaning single, and “lithos”, meaning stone) approach for architectural purposes, and it can be practically used to simulate the majority of the common materials that we see every day. Unlike the regular Maya shaders, and most of the custom mental ray shaders, it implements physical accuracy, greatly optimized glossy reflections, transparency and translucency, built-in ambient occlusion for detail enhancement of final gather solutions, automatic shadow and photon shading, many optimizations and performance enhancers, and the most important thing is that it’s really easy to use. And it’s all in one - thus “monolithic”. I therefore decided to use it in our tutorial...

A Note on Color Space.

As you may already know, usually all of the photographs and pictures that you look at on your computer are in the sRGB color space. This is because, for example, a color value of RGB 200, 200, 200 is not twice as bright as a color with RGB 100, 100, 100, as you would expect. It is of course mathematically twice the value, but perceptually it is not. As opposed to plain mathematics (like 2 x 100 = 200), our eyes do not work in such a linear way. And here’s where the sRGB comes in... This color space ‘maps’ the values so that they appear linearly. This is why most of the photographs are visually pleasing and look natural, which is not in a true mathematically linear color space. However, almost every renderer spits out these old and truly linear images (because this simply is how computers work - mathematically linear), unless we tell the renderer to do otherwise. Most people are not aware of this, and instead of rendering in the right color space they unnecessarily add lights and ambient components to unwittingly compensate for this error. In Fig. 3 and Fig. 4, you can see two photographic examples illustrating the difference between a true linear (left) and an sRGB color space (right). In Fig. 5, you can see the same from a CG rendering; you’ll notice that the true linear one looks a lot more “CGish” and unnatural. Even if you brightened it up and added/reduced the contrast, you still couldn’t compensate for the fact that it’s in the wrong color space, specially if you carelessly used textures from an sRGB reference (i.e. from almost any digital picture you can find), which adds up even more to the whole mess. This is an essential issue in order to create visually pleasing and naturally looking computer graphics. If you have followed me up to here, and you think you understand the need for a correct color space, then go take a break and get yourself some coffee or delicious green tea and enjoy life for a while - you've earned it! This is all tricky yet fundamental knowledge. How this theory is practically applied in mental ray will be shown later on...

Fig. 3

Fig. 4

Fig. 5

So, let’s get started with lighting the scene... Maya 8.5 introduces, along with the mia package, a handy physical sun and sky system. This makes it easy to set up a natural looking environment and we can then focus more on the aesthetic part of the lighting process, instead of tweaking odd-looking colors. The sky system is created from the render global’s environment tab (Fig. 6).

d) a tone mapping lens shader called mia_exposure_simple, which also connects to the camera’s mental ray lens slot.

It’s also worth mentioning here that this button also turns Final Gathering ON.

Fig. 7

Now that we have a default sun and sky system set up, we are almost ready to render. Before we do the first test render, let’s make sure we are in the right color space, as mentioned. By default, we are rendering in true linear space (for an explanation please refer to the previous notes on color space), which is - for our needs right now - not correct. The lens shader we created however brings us into a color space which closely approximates sRGB by applying a 2.2 gamma curve (see the Gamma attribute) globally to the whole rendered image, as we calculate it. Generally, this is a good thing and is desirable. But if we apply a gamma correction in this way, then we would have to “un-gamma” every single texture file in our scene. This is due to the fact that the textures already have the “right” gamma (this is usually true for any 8bit or 16bit image file), and adding a gamma correction on top of that would double the gamma and could potentially wash out the textures’ colors. What a bummer!

So, we either have to “un-gamma” every texture file (boring and tedious), or instead of the lens shader’s gamma correction, we can use mental ray’s internal gamma correction (still boring, but less tedious).

As you can see from Fig. 8, we set the Gamma value in the Render Globals’ primary framebuffer menu to the desired value, which is - simply because mental ray works this way - 1 divided by the value (2.2 for approximating sRGB in our case), which equals 0.455. At the same time, we also need to remove the gamma correction of our lens shader, so we must set its Gamma attribute to 1.0 (linear equals no correction; you can select these shaders from the hypershade’s Utilities tab). Thus we completely hand over the gamma correction to mental ray’s internal mechanism, which automatically applies the right “un-gamma” value to every of our textures. There are no more worries for our color textures now. If we use “value” textures however (like for bump maps, displacement maps, or anywhere where a texture rather feeds a value than an actual color), we'd have to disable this mechanism for the particular “value” texture by switching a gammaCorrect node in front of it, with the desired gamma compensation (2.2 in our case) filled into the gammaCorrect's Gamma attribute (note: this attribute does not mean the value for the actual color^gamma function, it rather indicates the desired compensation situation, i.e. the “inverse”, or reciproke of the gamma function - no one ever would tell you about that, but now you know better). This is a long-winded theory, but now we’re ready to go!

Fig. 8

I tweaked the Final Gathering settings (Fig. 9) so that we will get a relatively fast converging, yet meaningful, result. I also turned down the mia_physicalsun’s Samples to 2.

Fig. 9

It’s kind of dark and has a few errors (Fig. 10), mainly because of insufficient ray tracing settings.

Fig. 10

Let’s now increase the general ray depths (Fig. 11) and the Final Gathering ray depths (Fig. 12). We’re also turning the Secondary Diffuse Bounces on. However, the Secondary Bounces button in the Render Globals only sets their Bounce Depth to 1; we want it to bounce twice so we’re selecting the actual node where all the mental ray settings are stored, which is called “miDefaultOptions”.

Fig. 11

Fig. 12

You can do this by typing in “miDef*” in the input line with LMB Select by name on (the asterisk is a wildcard for lazy people like me, see Fig. 13).

Fig. 13

Once we select the miDefaultOptions, all more or less hidden mental ray settings are exposed to the attribute editor. There’s also some stuff in the mentalrayGlobals node, but we’re focusing on the Final Gather tab in the miDefaultOptions right now. Let’s set the FG Diffuse Bounces attribute to 2 (Fig. 14). These ray depth settings should suffice to get the result at the end of this tutorial.

Fig. 14

Let’s re-render (Fig. 15). It is still pretty dark, but you can tell that the indirect light contribution is sufficient (don’t worry about detailed shadowing, we’ll get to that later on), so we need to actually raise the exposure level of our piece, somehow.

Fig. 15

Remember, we’re all still on the very basic default settings for everything. One setting used to tweak the exposure is the Gain attribute in the mia_exposure_simple, which is connected as a lens shader to our camera. Let’s increase the Gain value to 0.5 (Fig. 16).

Fig. 16

That’s much better, and gives a more natural feeling (Fig. 17).

Fig. 17

Now we can start to actually make decisions on the lighting and aesthetic accentuations. For this part, please don’t feel constrained to the settings and colors that I choose - feel free to follow your own ideas! I’m rotating the sunDirection to X -70, Y 175, Z 0 to accentuate certain elements by direct sunlight, and I’m setting the attributes of the mia_physicalsky to the values you can see in Fig. 18. I increased the Haze value to 0.5 (note that this attribute takes values up to 15, so 0.5 is rather low). Then I set the Red/Blue Shift to 0.1, which basically means a white-balance correction towards reddish (towards blue-ish would be a negative value, like -0.1). I also raised the Saturation attribute to 2.0, which is it’s maximum value. I then made slight adjustments to the horizon, which does not have much effect on the global look but I experimented with what we could see through the porthole and the window.

Fig. 18

The last thing I changed was the Ground color. I gave it a greenish tint because I thought this gave it a more lagoon-like feeling, and I think it gives the whole piece a more interesting touch (Fig. 19). From my own point of view, this is a good base for what we intended to accomplish with the early afternoon in the Mediterranean Sea scenario.

Fig. 19

If we’re satisfied with the general look, we can then go about setting up the scene for a final render. Firstly, let’s increase the Final Gathering quality, because we can reuse the Final Gathering solution later on. As you can see from Fig. 20, I raised the Accuracy to 64, but more importantly, and especially for the shadow details, the Point Density is now at 2.0. With a denser Final Gathering solution we can also raise the Point Interpolation without losing too much shadowing contrast. I also set the Rebuild setting to Off, because the lighting condition is not changing from now on and we can therefore re-use existing Final Gather points.

Fig. 20

Let’s have a look (Fig. 21). As you can see, there is still a lack of detail in the shadowed areas, especially in the door region. We can easily get around this with the new mia_materials which implement a special Ambient Occlusion mode. You only need to check on for Ambient Occlusion in the shaders, as everything else is already set up fairly well by default (all I did was set the Distance to a reasonable value and darkened the Dark color a little).

Fig. 21

The main trick is the Details button in the mia_material (leaving the Ambient at full black). By turning on the Details mode, the Ambient Occlusion only darkens the indirect illumination in problem-areas, avoiding the traditional global and unpleasant Ambient Occlusion look. See Fig. 22 with the enhanced details.

Fig. 22

Note: to adjust the shaders all at once, select all mia_materials from the hypershade, and set the Ao_on attribute in the attribute spread sheet to 1 (Fig. 23) (the attribute spread sheet can be found under Window > General Editors > Attribute Spread Sheet). Also note that switching on the Ambient Occlusion in the shader scraps the Final Gathering solution; it will be recalculated from scratch. If you find the Final Gathering taking too long, turn the Point Density down to 1.0 or 0.5, as this still gives you nice results but the lighting details will suffer.

Fig. 23

Now let’s increase the general sampling quality (Fig. 24). The sample level is now at Min 0 and Max 2, with contrast at 0.05 and the Filter set to Mitchell for a sharp image.

Last but not least, if you are having problems with artifacts caused by the glossy reflections, raise the mia_material’s Reflection Gloss Samples (Refl_gloss_samples) up to 8 for superior quality. You can do this with the attribute spread sheet, as well.

Fig. 24

For the final render, I chose to render to a 32bit floating point framebuffer, with a square 1024px resolution. This can be set in the Render Globals (Fig. 25).

Fig. 25

If I want to have the 32bit framebuffer right out of the GUI (without batch rendering), I need to turn the Preview Convert Tiles option On and turn the Preview Tonemap Tiles option Off, in the Preview tab of the Render Globals (Fig. 26).

Fig. 26

Important: I also need to choose an appropriate image format. OpenEXR is capable of floating point formats and it’s widely used nowadays, so let’s go for that (Fig. 27).

Fig. 27

When rendering to the 32bit image, you will get some funky colors in your render view, but the resulting image will be alright - don’t worry. After rendering, you can find it in your projects images\tmp folder. Fig. 28 shows my final result: a pretty good base for the post production work.

Fig. 28

Since we rendered to a true 32bit image, we have great freedom for possibilities. See Fig. 29 for my final interpretation where there is no additional painting, only color enhancement. Try it for yourself!

I hope you have enjoyed following this tutorial as much as I enjoyed writing it!

Welcome back aboard to the second part of the environment lighting series for Autodesk Maya 8.5. Again, we will be using mental ray for Maya for this challenging interior illumination, so all you need for the this is to get your CPU at operating temperature and the basic maya scene of our ship's interior.

Before we can start, we need to properly set the project (Fig. 1). If you're not familiar with the use of projects, you might want to know that (one of) the main reasons for doing this is because of the relative texture paths Maya uses. These relative paths ensure that we can port the scene from one file location (e.g. my computer) to another (your computer) without any hassle, as opposed to absolute paths which would always point to a static location that might differ from system to system.

Fig. 1

So we're back aboard the MS No-Frills, still anchored somewhere in the Mediterranean Sea (Fig. 2). For this second tutorial, we will set our goals for accomplishing a twilight atmosphere, which would usually occur at either dusk or dawn.

Before we actually look at the scene, let's take a few moments to think about this very special situation (you might want to skip or come back later to this paragraph if you want to go straight to the execution). Twilight, from a technical point of view, is the time (usually around half an hour) before sunrise or after sunset. In this condition the sun itself is not visible; the sun's light is however scattered towards the obeserver in the high layers of the atmosphere, either by the air itself (Rayleigh-scattering) or aerosols. This scattering effect causes the beautiful and different colors that we enjoy every dusk or dawn. From an artistic point of view, twilight may happen in a variety of occasions, for example in stormy weather, or when natural and artificial light sources meet - typically whenever two (thus “twi-”) light sources or light conditions compete for predominance (imagine two wrestlers intensely fighting on the floor, and it's absolutely impossible to tell who's going to win the fight). Twilight always has this dramatic sense to it, and often the dramatic colors as well. In case of a storm, they might even range from greenish to deep blue. Usually, in the case of dusk and dawn, colors range from blue to purple, and from yellow to orange and red. The crux is that these colors are mostly equally dominant (and therefore leave us with great artistic and interpretational freedom) - as opposed to any other lighting condition, where there is usually one light source which is predominant. With this in mind, we are now ready to simulate the very particular case of twilight.

We will use the same base scene as used for part 1 of this tutorial (the sunny afternoon), so all shaders and textures are ready to rumble. All surface shaders are made from the mia_material that ships with Maya 8.5 (you might want to read back to the “note on shading” in part 1 - sunny afternoon - which explains its basic functionality).

Fig. 2

Again, we are using the newly introduced physical sun and sky system, which can easily be created from the render globals (Fig. 3). This button saves us time setting up all the nodes and connections to make the system work properly (thus it also turns final gathering ON). It basically consists of three things:

Fig. 3

The sun, whose direction we control using the directional light (called sunDirection, by default) with it's light shader mia_physicalsun; the sky, which consits of an environment shader (mia_physicalsky) connected to the camera; and a simple, yet effective, so-called tonemapper (mia_exposure_simple), used as a lens shader on the camera (Fig. 4).

Fig. 4

Before we start rendering, let's firstly think about a reasonable sun direction that would fit our needs for twilight. It is very tempting to actually use an angle that leaves the sun below the horizon line, however this would yield a diffuse, not very dramatic lighting. You might want to experiment with this a little, but I have decided to have a more visible indication of where the sun actually is. I rotated the sun on X -12.0 Y 267.0 Z 0.0; this makes the direct sunlight shine through the back windows, still providing a very flat angle (Fig. 5).

There's still one important point that we should consider before pushing the render button: the color space. As already explained in the “note on the color space” in the first tutorial (sunny afternoon), we should make sure we work in a correct space, which is sRGB, or in our case an sRGB closely approximating 2.2 gamma curve.

Fig. 5

The mia_exposure_simple already puts us into this space by default (The Gamma attribute defaults to 2.2), but by doing it this way, we double the gamma on our filetextures, which by default are already in sRGB - that's a big secret no-one may have ever told you before, but trust me - it's like that. So we either need to remove the gamma from our textures (“linearize” them) before rendering, which can be done with a gammaCorrect node in front of them in the shader chain with Gamma set to 1/2.2, which is 0.455 rounded (important: the gammaCorrect node works inversedly - the value we put in there is the desired gamma compensation value, not the actual gamma function itself!), OR we can use mental ray's internal gamma correction mechanism - which I prefer. So we abandon the mia_exposure_simple's gamma correction, simply by setting its Gamma attribute to 1.0, and enable mental ray's mechanism by setting the primary framebuffer's Gamma to 1/2.2 = 0.455, in the render globals (Fig. 6).

Fig. 6

So we're ready to go and do the first test rendering (Fig. 7). As you can see the scene is pretty dark and has a few errors caused by the insufficient ray depths. However, we are still using the render globals default Draft quality preset...

Fig. 7

Let's now increase the raytracing depths to a reasonable amount (Fig. 8). The values you see in Fig. 8 should satisfy our requirements; we might increase the reflection depth later on...

Fig. 8

I also tweaked the final gathering settings to a lower quality (Fig. 9). This way, we get a fast converging - yet meaningful - indirect illumination for our preview renders. But besides lowering the general final gathering quality, I increased its trace depths, and, more importantly, turned the Secondary Diffuse Bounces button on. This button however only gives us a single bounce of diffuse light, as that's how they designed the render globals, but as I'm not satisfied with that let's go under the hood of the mental ray settings...

Fig. 9

We are selecting the miDefaultOptions node (for example by typing “select miDefaultOptions” without the quote marks in the MEL command line) (Fig. 10). This node is basically responsible for the export of all the settings to mental ray. The regular render globals are practically a more user friendly “front-end” to the miDefaultOptions. There's also some stuff in the mentalrayGlobals node, but this does not affect us right now.

As you can see, the FG Diffuse Bounces attribute is actually exposed; we set it to our desired depth, which is 2 for now.

Fig. 10

It looks better, but still appears to be seriously under exposed (Fig. 11). There are several ways to adjust the general exposure level in mental ray for maya, but let's choose the easiest one: raising the Gain attribute of our mia_exposure_simple...

Fig. 11

You can navigate to the mia_exposure_simple either by selecting your camera (to which it is connected), or by opening the hypershade and selecting it from the Utilities tab. I gave it a serious punch and boosted the Gain to 4.0 (Fig. 12).

Fig. 12

Now it's much better from an exposure point of view, but it looks very cold and not very twilightish (Fig. 13). You might want to experiment with the sun's direction, but if we overdo this then we will loose the nice light which is playing on the floor. I therefore decided to solve the problem using the mia_physicalsky - the environment shader which is responsible for pretty much the entire lighting situation.

Fig. 13

I upped the Haze parameter to 2.0, which gives us a nice “equalization” of direct light coming from the sun, and the light intensity of the sky (Fig. 14) At lower haziness, the sunlight would be too dominant for our twilight atmosphere. I then shifted the Red/Blue attribute towards reddish, to achieve a warmer look (if I wanted to shift it towards blueish, i.e. doing a white balance towards a cooler temperature, I would have to use a negative value for the Red/Blue shift). I also slightly increased the Saturation, which is pretty much self explanatory. Now, for an interesting little trick to make the whole lighting situation more sunset/sunrise-like, whilst still maintaining the direct light on the floor (i.e. the actual light angle), I increased the Horizon Height to 0.5. This not only shifts the horzizon line but also makes the whole sky system think that we have a higher horizon, and thus provides a more accentuated sunset/sundawn situation. Remember this does not have too much of an effect, yet it's still an interesting way to tune the general look. The last two things I changed were the Horizon Blur and the Sun Glow Intensity, however both of these attributes dont have much of a visible effect on the general illumination of our interior.

Fig. 14

Once we're finished setting up the basic look, we can go about configuring the render globals for the final quality (Fig. 15). First of all, let's increase the final gathering quality, since we can reuse the final gathering solution later on. In Fig. 15 you can see the values I used - 64 for accuracy, which means each final gather point shoots - in a random manner - 64 rays above this point's hemisphere (less accuracy would give us a higher chance of a blotchy final gathering solution). To work against the blotchiness we could also increase the Point Interpolation to really high values, like 100+, but this would most likely wash out the whole contrast and detail of our indirect illumination if we dont have a sufficient Point Density value. The Point Density - in conjunction with a reasonable Point Interpolation - is the most responsible part in achieving nicely detailed shadowing, and so we have to find a good correlation between these two. In our case, I found it sufficient to have a Point Density of 2.0 and a Point Interpolation of 50. You might want to try a density of 1.0 (or even 0.5) if you think the former settings take too long to calculate, but you'll surely notice the lack of detail in the indirect illumination. Note that increasing/decreasing the interpolation does not affect the final gathering calculation time at all. It also does not hurt the actual rendering time too much. The crucial value is the point density which adds to calculation time, as well as the accuracy. Also note that you might be able to comfortably experiment with the Point Interpolation if you freeze the final gathering solution (set Rebuild to Freeze).

Fig. 15

It looks much better now, but there are still some areas that seriously lack detail, such as the door region (Fig. 16). To reveal these details we could render a simple ambient occlusion pass and multiply it over in post production. This would accentuate the problem areas, but at the same time it would add this typical all-present, physically incorrect and visually displeasing ambience. To overcome this, and still use the advantage of ambient occlusion, we can use the mia_material's internal ambient occlusion mode...

Fig. 16

We simply need to enable it in the shader, and set the Detail attribute to ON (which it is by default) (Fig. 17). This special ambient occlusion mode is intended to enhance the problem areas' details, where the point density might still not suffice.

Fig. 17

To enable the ambient occlusion in all shaders, we simply select them all from the hypershade and open the attribute spread sheet, from Window > General Editors > Attribute Spread Sheet (Fig. 18). There we navigate to the attribute called Ao_on and set its value to 1 (ON).

Fig. 18

Although it still might be physically incorrect, it reveals all the details that the final gathering was not able to cover (Fig. 19). Of course, it still looks very coarse, and this is mainly because the general sampling settings are still at extremely low values.

Fig. 19

To ensure nice edge antialising, as well as better shadow and glossy sampling, we set the min/max sample levels to 0/2 and the contrast values each to 0.05 (Fig. 20). The filter should be changed, too; I chose Mitchell for a nicely sharp image. I'm also raising the Reflection Gloss Samples (Refl_gloss_samples) up to 8 in the mia_materials. Note that this happens on a per shader basis, and we can use the attribute spread sheet again to do this all at once for all shaders.

Fig. 20

Last time we rendered to a full 32bit floating point framebuffer. This time, for my final render, I chose to render to a 16bit half floating point framebuffer (Fig. 21). The 16bit half takes less storage (and bandwith) but still provides the increased dynamic range of floating point buffers. If we want to render the floating point buffer right out of the GUI, wihtout batch rendering, we need to make sure the data written into the buffer actually is floating point; thus the Preview Convert Tiles in the Preview tab of the render globals needs to be switched ON, and the Preview Tonemap Tiles option needs to be switched OFF. This will produce funky colors in your render view preview, but the image written to disk (typically in your project's images\tmp folder) should be alright.

Fig. 21

The use of a 16bit half framebuffer forces us to use ILM's OpenEXR format, as it is the only supported format right now for this particular kind of framebuffer (Fig. 22). That's not actually bad, since OpenEXR is a very good and nowadays widely used format.

Fig. 22

Here's the final rendered, raw image (Fig. 23) - a good base for the post production work.

Fig. 23

In my final interpretation I decided to exaggerate the colors that make a dramatic twilight atmosphere (Fig. 24). Again, there is no painting happening, only color enhancement which done using Adobe Lightroom 1.0.

I hope you enjoyed following this second part of the series as much as I have enjoyed writing it. Stay tuned for part 3 where we will be covering an extremely interesting and no less challenging lighting situation: moonlight.