Showing posts with label maya rendering mental ray. Show all posts
Showing posts with label maya rendering mental ray. Show all posts

Tuesday, March 20, 2012

Maya - Full linear workflow for Viewport 2.0

A gamma of 2.2 is for "practical" purposes, sRGB-encoding, and it's important to be aware of when gamma is being applied so it can be removed for proper 3D lighting calculations, then re-applied when required. If you're confused, here's an excellent page on Understanding Gamma Correction. I won't go into explaining the details of "linear workflow" in Maya, since there's plenty of information elsewhere about it. This post will focus on addressing a problem I was confronted with when using the "Gamma Correction" option in Maya 2012's Viewport 2.0; doubling up of gamma-encoded color textures being displayed. I wanted to have linear sRGB textures in the viewport too, not only in the rendering process. Color Management doesn't work for the viewports, and the gammaCorrect nodes aren't supported in Viewport 2.0 yet (as of Maya 2012), but the problem can be solved by using the Mental Ray image conversion utility imf_copy.

By default, the folder path to imf_copy.exe (C:\Program Files\Autodesk\Maya2012\bin) already exists in the system PATH variable under "System > Advanced system settings" in Windows. It's not important to check, but you'll need to add the path to imf_copy if you encounter a "program not found"-related error. To bring up the command-line interpreter (cmd.exe) with the working folder at the currently focused (active) window: Press Shift, right-click, and then choose "Open command window here".

For scalar textures (such as bump maps, scalar and vector displacement maps, specular amount maps, reflection amount maps, normal maps, etc) along with HDRs (should already be linearly mapped), you could use the following command to convert the image, which produces a memory mappable image file (.map) with the same bit-depth as the input file:

imf_copy -p "input_image" "output_image.map"

However, for color textures (diffuse color and 8-bit reflection color textures), you should use this:

imf_copy -p -e -g 0.4545 "input_image" "output_image.map" map rgba_16

The main difference here is that you're doing a 0.4545 gamma operation on the input image, which approximates the sRGB gamma correction (1/2.2) by bringing the image into a linear representation of color values. This is essentially the same as using a gammaCorrect node with the same setting. So don't use the gammaCorrect node in Maya, and if you're using Color Management (you don't have to), set the file node for the .map image to "Linear sRGB". An important aspect of the newly produced image is that its bit depth will be 16-bit integer per-channel. Converting an 8-bit image with a gamma of 0.4545 will expose posterization (easily seen in the dark colors) when applying the display gamma; by converting to 16-bit, you remove the potential for color banding artifacts. Another option is used: -e (error diffusion), this is enabled to effectively remap the color values to 16-bit using dithering.

Note that you don't have to convert your scalar and HDR images at all, unless you're interested in the memory performance benefits the .map format offers. Also, you don't have to use that format; you could use (for example) Photoshop actions to apply the gamma edits on a set of images and store them to 16-bit output image files. Once you've output the image files, you can import them into file nodes as usual, but however you apply the gamma to the rendered image itself or Render View display (using mia_exposure_photographic, mia_exposure_simple, or Color Management's view manager in the Render View), you'll have a setup that is perceptually correct in Viewport 2.0, so lights will give you a close approximation of how the rendered result will be, at least for relatively simple scenes.

Viewport 2.0 closely matching Mental Ray software render.
To verify my idea, I tested a basic scene using a gradient image in sRGB produced from Photoshop. The Stanford bunny has a real-time reflection map applied (an HDR image) through an envBall node in the "Reflection Color" of the mia_material_x_passes, and the floor is a substance procedural texture converted to a color texture, but has no gamma change applied since procedurals are linearly color mapped already. The photographic lens shader is being used purely for the view gamma, and I reduced the exposure slightly under "Render View > Display > Color Management". If you want the Render View color manager to deal with the view gamma instead of an exposure shader, set the "Image Color Profile" to Linear sRGB, and Gamma on the exposure node to 1.0. Color Management in the Render Settings was disabled, as all images are already in a linear color mapping (or approximated as linear sRGB with the gamma 0.4545 baked into the .map images). There is a bit of noticeable color banding in the gradient image (even with the Viewport 2.0 floating-point render target enabled), but that's fine and doesn't appear in the rendered result.

When working in a real scene, you won't bind yourself to the lighting results the viewport is showing you (unless you're rendering with the Hardware 2.0 renderer), and you would probably want to have tone mapping applied; "Burn Highlights" and "Crush Blacks" at their defaults will alter the rendered image even more from the viewport, but that's a good thing and mimics the human perceptual response better; before doing the final renders ready for compositing purposes, remember to remove all tone mapping and gamma effects; for example, with mia_exposure_photographic, setting Burn Highlights to 1.0, Crush Blacks to 0.0, Vignetting to 0.0, and Gamma to 1.0 will give you a non-tonemapped image; all the other settings in that shader, such as cm2_factor, are simply multiplier effects and won't alter the masterBeauty pass in a non-linear way. In Nuke or other compositing software, you can then re-apply tone mapping effects.

As a concept however, you can see how closely the render matches the viewport, which was the goal of this setup. It's at least useful for properly displaying color maps, and rendering correctly with Hardware 2.0 for pre-visualization work, regardless of how the exposure or lighting eventually diverges from the viewport setup in a software rendering. If you're working in a scene with dozens or even hundreds of textures at 4k resolution, eventually your graphics card won't be able to handle all the textures; that's fine, simply work without textures being displayed.

To simplify all this image converting, you could use a FOR loop in the command line. To avoid having to enter the text editor frequently, use the following batch scripts:
 
Save the text below as "_img-map_scalar.bat" and drag your scalar and HDR images to it:
:convertfile
@IF %1 == "" GOTO end
imf_copy -p %1 "%~d1%~p1%~n1.map"
@SHIFT
@GOTO convertfile
:end
@ECHO.
@ECHO Done!
@pause

Save the text below as "_img-map_color16.bat" and drag color and reflection color images to it:
:convertfile
@IF %1 == "" GOTO end
imf_copy -p -e -g 0.4545 %1 "%~d1%~p1%~n1_linear.map" map rgba_16
@SHIFT
@GOTO convertfile
:end
@ECHO.
@ECHO Done!
@pause

The "color" script is only for applying a 0.4545 gamma correction to 8-bit color and 8-bit reflection maps and converting them to 16-bit (integer) for rendering without banding artifacts. In general, you can use the "scalar" script for everything else; a typical scene might consist of mostly scalar textures and a few HDR color maps, which would be converted using the "scalar" script; note that the "scalar" script outputs a .map with the exact same bit-depth as the input, because no "rgba_*" was specified. If you paint and produce 16-bit color maps from Mari or Photoshop, use the "color" script; however, when exporting a 16-bit color map, if you know you've done a gamma-compensated or full linear workflow while texture painting, use the "scalar" script. The same concepts apply for painting 32-bit color maps; again, be aware of gamma being "baked in" if using typical 8-bit images as painting sources. You're probably painting using 8-bit sRGB gamma-encoded images and the gamma is now "baked" into your 32-bit floating-point color map (if you're basing all your painting in a non-color managed view, which can be changed in Mari under "View > Palettes > Color Manager"). This is fine, but simply be aware of it so you can apply a 0.4545 gamma (with imf_copy) to your 32-bit image exported from Mari. To make a new batch script for 32-bit floating-point color maps that need a 0.4545 gamma correction, just replace the "rgba_16" with "rgba_fp" in the "color" script above, and save it as a new script maybe named "_img-map_color32". Again, it all depends on how you're working, and if a texture image looks a bit washed out or darkened, then you know that somewhere in the image pipeline, you've not compensated for the gamma. Remember, the goal is to have all color data being sent to the renderer to be linear, and you can achieve that using gammaCorrect nodes, Color Management, the imf_copy utility, Photoshop, Nuke, and many other options.

You can name the batch files however you like to, but including an underscore ( _ ) at the beginning of their name will alphabetically sort them to the top of the file browser (with alphabetical sorting enabled). Simply drag the image file(s) over the batch script and it will take each image in the selection and output a .map file to the input's source folder, regardless of where the batch script is located. The Windows command line won't work if you have too many files in your selection (I can't say how many since I think it's based on the path name length of all the files, something like 2048 total characters), so keep that in mind before you drag twenty or so images to the batch script and wonder why it refuses to produce results.

If you're not into dragging the files over the batch scripts and are interested in a more familar menu-based approach, you can append these scripts to the right-click context menu in Windows with the free and highly useful program called "FileMenu Tools" from LopeSoft. Install that program, then in the settings; Add a command, set the action to "Run program", give it a name, set the Element Types for Drives and Folders to "No", then set the path to the batch script. Repeat for both and now you'll be able to right click a selection of image files and convert right from the Windows Explorer context menu. You can set it to spawn multiple instances simultaneously, which would speed up the task significantly since each selected image will be given a CPU thread on its own imf_copy instance, rather than sequentially converting each image on only one thread. Remember that it won't work if you select too many files, as mentioned in the paragraph above.

Using "FileMenu Tools" to use the batch scripts in a familiar menu interface; select images, right click, choose option.


8-bit files converted to 16-bit memory mapped files will be significantly larger than their sources. You could remove the "-p" and " flag to disable filtered image pyramid creation which will reduce the output file size slightly, as it's not entirely necessary (it's useful for efficient texture loading into memory). In future versions of Maya, if the gammaCorrect node is then supported in Viewport 2.0, and/or Color Management works in the viewport (I sent this as a feature request to Autodesk), then you won't have to "bake" the gamma into the .map files. For now, this method works very well.

Update: Maya 2013 has significant improvements in Viewport 2.0, along with support for the gammaCorrect node. If you don't want to use the Color Management feature, you could just use gammaCorrect nodes set to 0.4545 on typical 8-bit sRGB-encoded color file textures and the images will be transformed into linear color space not only for rendering, but for viewport display too (with Gamma Correction enabled in Viewport 2.0), which was the point of this post; getting file textures to look correct in Viewport 2.0. By doing the gamma corrections using gammaCorrect nodes, you'll only need to use one batch script for all your textures (the one that doesn't alter the gamma, the "scalar" one). I'll explore further possibilities as I get into rendering some assets for my current project and I'll post updates if necessary here.

Sunday, March 27, 2011

Maya - Flicker-free Final Gather in dynamic animations

"Flickering" is a common issue that comes up for anyone who uses Final Gather in Mental Ray to compute indirect illumination for a scene containing moving objects. This tutorial addresses the flickering problem for animations with dynamic movement; that is, characters, creatures, etc, not just a moving camera. I assume you have some experience with Final Gather, but I will explain some of the most pertinent attributes needed to better understand the workflow presented here. The technique used in this tutorial is applicable to Maya 2008 and newer versions as it relies on the mental images production shader library "mip_render_subset" node. The video below shows the resultant test scene featuring flicker-free Final Gather indirect illumination:



Even in the simple scene above, Final Gather will cause flickering, due to the inherent nature of its random sampling methods. Keep in mind that a frozen Final Gather (referred to as FG henceforth) map works well even on objects that move slightly (such as leaves in the breeze). In the video below, a Paint Effects plant, converted to polygons for rendering in Mental Ray, is flickerless despite its slight motion; this demonstrates that a frozen FG map with very low settings works not just for static objects:



So it's important to know that a frozen FG map is quite flexible, but it has limits, particularly for objects that encounter major lighting changes during an animation such as a character.

Note: Once the mip_fgshooter is implemented into Maya with an intuitive interface, the particular workflow presented in this post won't be necessary anymore, for most situations. For now, there's a few scripts that allow you to try out the mip_fgshooter, such as this one here: fgshooter UI for Maya. There is a discussion of this over at CGTalk forums. Check it out here: Flicker-free Final Gather.

After some experimentation I've settled on a relatively good workflow for achieving a flicker-free FG result; here's the outline listed below.
  • Hide moving objects, compute a Final Gather Map for objects that don't move.
  • Freeze the FG map, then unhide all moving objects, render the scene normally.
  • On a new render layer, set FG as a layer override to "Rebuild", with a new FG map override.
  • The new map will be for moving objects, be of high quality, and will be rebuilt (never frozen).
  • Attach the mip_render_subset node as a lens shader to speed up rendering of second pass.
  • Output the "indirect_result" of the mia_material_x to a surface shader, assign the surface shader to the mia_material's geometry, and associate with mip_render_subset.
  • Render the scene, mip_render_subset will only render selected objects and/or materials; essentially creating a fast indirect pass for moving objects.
  • You'll now have a FG-only pass for your moving objects, to be added onto your original render in the composite.

This method will force you to render the scene twice, but only at the cost of computing an additional FG pass along with ONLY the indirect contribution of the moving objects (characters, vehicles, etc), which shouldn't add much to your render time. The reason the scene requires rendering twice is because FG won't allow setting of Rebuild and Freeze for different individual maps in the same rendering session. Since FG is view-dependent, resolution-dependent, and dependent on how much geometric details and lighting contrast the scene contains, the settings you converge on for one scene will probably not work for other scenes, so the more you know the better you'll be able to get a good result fast. Below are the settings for the above blocks/bricks collision test video for the "Frozen" portion of the FG pass. I'll describe some of the relevant settings, but if you don't know all of the settings in FG and are serious about using it, I recommend you taking some time and make a practice scene, check out the manual, online videos, and experiment with the settings; you'll be glad you did.

Very low but adequate frozen FG settings for this simple scene.

Something to note with Frozen FG maps: you're able to get away with really low FG settings, particularly the Point Density defining just how many FG points will be sampled from the camera view, while using Point Interpolation to smooth the map out by averaging neighboring FG points, along with the Normal Tolerance which is a threshold that allows interpolation of nearby points to occur only after a certain angle between their respective surface normals is met. As a note on just how resolution dependent FG is, for example, if you set your resolution from 1280x720 to 1920x1080, you're essentially quadrupling the amount of Point Density without even changing the attribute. Accuracy defines the amount of rays casted from each FG point, which increases render time while better estimating the indirect illumination of each FG point. Accuracy is usually worth increasing over Point Density, but it will only go so far, as Point Density is arguably the most important setting. If you're working in a tone-mapped workflow with photometric lights (or the Sun and Sky system), you shouldn't have to change the Diffuse Scales (which are gains on the FG results, allowing surfaces to reflect more or less indirect light than they are supposed to for plausibly accurate light transport in the render). Secondary Diffuse Bounces isn't really relevant here, but if you don't know, it adds more bounces of FG points. By default there is 1 primary indirect bounce of light (there has to be, or else no indirect light would exist), and the secondary bounces are set to 0 by default. Adding a few more indirect bounces will yield a more accurate result with usually little addition to render-time, so long as the FG settings aren't too high. The setting Optimize for Animations (called Multiframe mode in the Mental Ray manual) will usually help on scenes with animation, as the Max Radius parameter is used to limit how far in world units FG interpolation can occur, but it's not always better than the Automatic mode, even for animations. While setting the FG Filter to higher values (such as 2) reduces flicker, it also produces a more biased result (meaning not as accurate). FG is as unbiased as possible with the Filter set to 0, the default, and I recommend you keep it there. On the concept of unbiased indirect lighting, an interesting mode to try out is No FG Caching. This is a brute force method, therefore it's highly accurate but computationally expensive, though it will cause no flickering (only sub-pixel noise). In the brute force method, Accuracy defines how many samples will be taken; the more samples, the less noisy the image, the longer the render time.


Same Point Density, number of points increase at higher resolution.
Speaking of physically-plausible renderings, when using the Mental Ray Sun and Sky, setting the RGB Unit Conversion of the mia_physicalsky to 0.318 for each RGB component (1/pi or 1/3.1415927) converts the raw values of the Sun and Sky so that they fit easily into the mia_exposure_photographic tone mapper, meaning the Cm2 factor (the Candela per meter squared conversion factor) doesn't have to be adjusted. The Mental Ray architectural design manual describes how 1/pi is derived: "The value 0.318 (1/pi) originates from the illuminance/luminance ratio of a theoretically perfect Lambertian reflector". This is useful to know if you're using mia_exposure_photographic and are trying to replicate a real-world camera setup without having to change the Cm2_factor to some arbitrary number. In addition, each pixel in the final floating-point rendered image will be represented as candela per square meter luminance values.

Alright, so the main idea here is to create a Frozen FG pass ONLY for the objects that aren't moving OR are moving very little (think of leaves moving in a gentle wind). This will entail simply hiding those objects you know are going to flicker with low FG settings, then unhiding them after the FG map has been computed and Rebuild set to Freeze. Always remember to disable the option Enable Default Light in the Common tab of the Render Settings window, as the default light will, among other things, cause a lighting change if you're batch rendering, cancel and then continue the render using batch scripts, so this setting needs to be off. Feel free to use the Render Passes and such; this will be a beauty render without indirect lighting on the moving objects; we'll take care of the FG on those objects next. Just in case you don't know how to create a Frozen FG map, here's a quick explanation, but this isn't the point of the tutorial so I'll make it quick:

To create a Frozen FG map, define a map first in the Final Gather File field (an extension name doesn't matter, though I use .fgmap), then enable the Preview Animation mode in the Preview section of the Options tab of the Render Settings. Preview Animation will render out your scene but won't save files in this case. You'll ONLY be calculating the FG map for your main rendering camera. To set the renderer to render only the FG pass, under the Features tab, set the Render Mode to Final Gathering Only. Image sampling (anti-aliasing and such) settings don't matter and will have no effect, since FG is being rendered only. Then under the Common tab, set the By frame attribute to a setting such as 10, or 5, there usually isn't a need to render every frame for the FG map, unless the camera view is covering a massive change per frame. Keep in mind that the pixel resolution of the image does matter, so you'll need to set that to your target output pixel resolution, also under the Common tab. Now render the current frame and Mental Ray will calculate the FG data for the length of the animation. Remember to switch Rebuild to Freeze and unhide any objects (such as your characters/creatures) you didn't want in the frozen FG solution when you're ready to render again. Here's a quick explanation on the Rebuild modes in Final Gather:

Rebuild On: Overwrites the FG map on every render, and with each frame advance at render-time.
Rebuild Off: Appends (adds) FG points to the map, as needed, without overwriting it.
Rebuild Freeze: Reads from the FG map, doesn't overwrite nor append anything to it.

Alright, now you have a beauty render with frozen FG on all static (along with slightly moving) objects. Those highly moving objects have no FG contribution, so now it's time to render out the scene again, but without doubling the render time, and with minimal effort. If you don't have the mental images production shader library exposed in Maya 2011, in the MEL command line type: 

createNode mip_render_subset

Or, if you'd like to expose these shaders in the Maya 2011 Hypershade without having to manually create them using the createNode command, copy the script mentalrayCustomNodeClass.mel from the directory (in Windows) "C:\Program Files\Autodesk\Maya2011\scripts\others\" and paste it into your local user scripts directory located at "C:\Users\YourUserName\Documents\maya\2011-x64\scripts\", ensuring that if you make a mistake, you can just delete your copy and Maya will work again. Change this line near the bottom of the new file:

int $enableMIPShaders = (`optionVar -query "MIP_SHD_EXPOSE"`== 0);

After the "MIP_SHD_EXPOSE"`==, change the 0 to a 1. (This is a boolean variable, 0 equals "off" and 1 equals "on", so you're now exposing the production shader library to the Hypershade when Maya loads). Also, verify they are loaded by going to "Window > Rendering Editors > mental ray > Shader Manager". Make sure "production.mi" is loaded.

In the picture below, the mip_render_subset node's attributes are shown.


The mip_render_subset node wants you to define at least one object (by typing in the name of a shape node of a geometry object) OR a material's shading group node (not the material, the shading group, because Mental Ray's material is represented as the shading group node in Maya). By the way, if you define a material and a selection of objects, the shader only works if all conditions are met (that is, objects with the particular material (SG node) selected). So what does this node do anyway? Well, it is designed to ONLY render the defined objects AND/OR objects with the chosen material (you can also just define a material and no objects). It's a "quick-fix" shader for re-rendering an object in a scene that was rendered incorrectly (such as wrong material settings that can't be corrected with a matte in compositing), but without having to re-render the entire scene again nor having to isolate the object manually. In this tutorial, we'll use this shader to "isolate" the moving objects in the scene for the second render pass. The shader is applied as a lens shader on the renderable camera under the "mental ray" section. If you already have a lens shader applied (such as mia_exposure_photographic), then simply choose the Create button under the Lens Shaders section of the camera shape node attributes. Note that only the first mip_render_subset node will render, as these are unstackable. Here's a simple demo of using the mip_render_subset for isolating a specific material: mip_render_subset - Basic Example

To enter an object into the mip_render_subset, simply copy/paste its shape node name. Press Load Attributes in the Attribute Editor to refresh/redraw the window, allowing the next empty entry in the object array list to display. Now just add the objects you want to be isolated in the render. To keep things quick, I won't explain the other settings, as they aren't relevant in this tutorial, but, there is one setting that can speed up rendering at the expense of accuracy: Full Screen FG. Full Screen FG is enabled by default, and it does what is reads as: computes the FG pass for the whole scene first, then renders only the objects/materials defined by this lens shader. If you disable the Full Screen FG option, the FG pass will only compute for the isolated objects, so the render time will definitely be faster, but at the expense of accuracy. It is highly recommended you keep this setting on, which is the default. We're not done with the mip_render_subset yet, I've just explained what it is and the general idea of how it's used; you'll soon see how it'll be used along with the indirect_result shader attribute to ONLY render out the FG contribution for the moving objects once I go over some of the FG settings for this second pass, as they are entirely different from the frozen FG map pass.


Before I move on, I'd like to mention that I'm using the Render Layers feature within Maya to assign overrides to various attributes I want to change for the selected layer only, which show up as an orange color. The overall concept is simple but there's a lot you can do; if you haven't utilized them in your workflow yet, I highly recommend you read about Render Layers in the Maya manual. There's also plenty of video and such on the internet describing their use.


This second pass will require the settings for FG to be considerably higher. For example, each FG point is casting 1500 rays to estimate their indirect illumination. The Point Density is at 0.100 (which is barely enough for this particular scene). Point Interpolation has been set to 50, which eliminates some of the flickering almost for free, but keep in mind that for points to "get the most out of interpolation", you need a certain amount of points that are eligible for interpolation (remember the Normal Tolerance setting). This means that if you don't have enough Point Density in your animation to match the smaller details in the scene, interpolation won't be able to help much, meaning for those areas, Accuracy will have to be high enough to subdue the higher potential for flickering. What I'm saying is that Point Density is the most important setting and will determine if the animation will flicker or not; you need to have a certain amount of FG points or else you can't eliminate the flicker, but it really is a balance between a high enough Point Density along with relatively high Accuracy (for good estimation of each of those important FG points), then use the Interpolation setting for the final smoothing; 25-75 are pretty good for Point Interpolation on typical scenes. Remember that if you change the render resolution, the FG results will look different, so tweak the final settings at your target render resolution. So what settings do you use? There are no specific ones since each scene is different; with experience you'll be able to set up a scene's FG faster. Enable the option Diagnose Finalgather, and you'll be able to see every single FG point sampled from the camera into the scene, while the Map Visualizer will allow you to see the points in the viewport. Consider that some of those points will be interpolated if they're close enough to each other AND if they fit within the Normal Tolerance. Generally you won't have to adjust Normal Tolerance, but there needs to be a sufficient amount of FG points to resolve a good amount of the detail in your scene; along with a relatively high Accuracy setting, which is cheaper than increasing the Point Density and will yield similar results. Remember the Rebuild mode here is On, allowing FG to compute at each frame.

Another very good tip to know about Final Gather is that as you're tweaking it, you're able to get almost instant feedback if you write out a temporary FG map and then set the Rebuild mode to Freeze; you can then adjust some settings in the IPR (Maya's interactive renderer) without having to wait for the FG to calculate again. The settings you're able to tweak with a Frozen FG map: Point Interpolation, Diffuse Scales, Filter, and the Min/Max Radius. Of course, tweaking Accuracy and Point Density require the map to be re-computed. The Min Radius and Max Radius are advanced settings which are best left at their defaults of 0.000, but they can be adjusted if needed. They are good for forcing Point Interpolation to only interpolate points that are near other points to a certain radius in world space; Mental Ray computes internal defaults for the Min and Max radii and you probably won't have to adjust them often, but they're available. Though these FG settings are somewhat "high" (not high at all for a single over-night frame render, but for animations, settings need to be low), they won't fill in details nor color bleeding. That's fine, you can use the mia_material_x's Ambient Occlusion with Color Bleed option, or rendering out a traditional Ambient Occlusion pass for compositing will be fine too. An interesting way to use an AO pass is to color correct the image but set the AO pass as a mask into the color correct, controlling gain and such, but also, adding a bit of saturation back into the darker areas, again using the AO pass as a mask. This method is fine, but if you're rendering in passes (diffuse, reflection, etc), you can apply AO in a more correct way, by rendering out an ambient color or indirect lighting pass, gain down that pass using the ambient occlusion pass as a mask, then add the direct/diffuse lighting on top of the indirect pass, which eliminates the "dirty" look of most renders using ambient occlusion, due to the AO effect occurring in direct light. Now onto setting up the FG pass of the moving objects.

You've already rendered out the moving objects in the first pass; they just have no FG contribution to them; well now you're going to render the second pass, but it will only contain FG for those objects, and you'll be able to composite this new render onto the first one by simply adding color values, with the added bonus of being able to adjust the amount FG contributes to those moving objects if needed. This will be done by utilizing the indirect_result attribute of certain Mental Ray shaders optimized for pass-based rendering, such as mia_material_x and mia_material_x_passes that each expose outputs such as diffuse, opacity, etc.

Side Note: For the sub-surface scattering shader, you should incorporate its scattering result into the mia_material_x_passes' Additional Color attribute, make sure the SSS shader's diffuse and specular contribution to 0, allowing the mia_material to handle diffuse, glossiness (specular), reflectivity, etc, while the SSS shader does what it does best, sub-surface scattering and only that; you could also mix specular/glossiness from both materials. Also remember to assign the misss_fast_lmap_maya node to the mia_material shading group's Light Map Shader slot. If you're to be rendering linear color space HDR (high dynamic range) images, make sure to disable Screen Composite under Algorithm Control of the SSS shader. This keeps the result physically plausible, by keeping the material from reflecting more light than what illuminates it (that is, it obeys the conservation of energy concept). These recommendations for using the SSS shader are from the person who actually wrote it: Zap Andersson (Zap's mental ray tips). I've digressed somewhat, let's get back to the Final Gather stuff, but rendering with color management (aka "linear workflow") is very important.

If you're using the mia_exposure_photographic lens shader and you want to maintain linear color output for HDR images (essential in allowing compositing math to apply in a predictable and proper way), remember to set Burn Highlights to 1, Crush Blacks to 0, and Gamma to 1.0 before you do the final render. In the compositing application, you should use a color Lookup Table (LUT) to transform the image to sRGB (appropriate for all typical LCD monitors) color space for viewing, while allowing the underlying compositing math to operate in a linear fashion.


For the shaders being used in this second pass, in order to isolate and only render the indirect element (instead of everything else too), you'll connect the indirect_result attribute of the mia_material_x (or _passses, whichever you're using) to a new Surface Shader's outColor attribute. The connection is displayed below in the Hypershade. As a side tip, if you didn't know, the green arrow represents a triple-attribute connection such as XYZ, dark blue represents a single connection such as integer to integer, a cyan arrow represents double attributes connected (such as UVs), and purple means a connection to a table of data. The connection we're making here is a simple color to color (3 values of RGB to another 3 values of RGB). Now assign the Surface Shader to the geometry the incoming mia_material was assigned to; if you're using Render Layers, the material will be assigned as a Material Override. Regardless of whether you're using Render Layers, if you render the object now, it will only produce FG or any other indirect result. This is faster and more efficient than re-rendering the object with all of it's shading qualities, those of which were already computed in the first pass.

The next step is to add the moving objects into the mip_render_subset object list. If you have a lot of objects that use the same material, then simply use that material instead of adding the objects manually. Copy/paste geometry object shape node names AND/OR a material's shading group name into their respective fields of the mip_render_subset node. Make sure the node is applied as a lens shader to the renderable camera. Now render the scene and you'll see the FG is computed for the entire scene, but once it finishes, only the objects/materials listed in the mip_render_subset render, AND only their indirect illumination renders, meaning a really fast render compared to computing texture filtering, blurry reflections, and such. If you want a faster rendering without having to disable the Full Screen FG option in the mip_render_subset node, then you might want to disable Final Gather Cast and Final Gather Receive on the distant objects in the scene, ones that wouldn't contribute much if any FG to the objects/materials listed in the mip_render_subset, thus skipping them entirely from the FG computation. This will decrease accuracy of the light transport a bit but will speed up the rebuild of each FG pass on each frame. Below is the result, the indirect result only of the blocks themselves, and they aren't flickering!



That's really all there is to it. Use your compositing application to composite the results onto the original first pass. This may not be the best method to do flickerfree FG in Maya, but there doesn't appear to be much information on the internet about it, and so after some experimentation I found this workflow to be the most efficient and fast, for now. If you have a high dynamic range scene with an intense amount of contrast differences, you'll probably be asking FG to do more than is practically feasible. Another way to smooth out FG is to use a blurred environment map that only FG rays see by means of using a ray switcher; the production shader library includes several such nodes, and keep in mind the usefulness of the mia_envblur node and the Single Sample from Environment attribute in the mia_material. If all else fails, you can always render a Frozen FG map for the static objects and then Light Link a directional Light Rig (without shadows and specular on the lights disabled) onto the moving objects; for best results you can render out the contribution (not talking about Contribution Maps of Render Layers) of the Light Rig lighting the moving objects with all other lights disabled and everything else matted out, then combine that result in the compositing stage to fake indirect illumination; I recommend rendering a test FG image and then try to match that in the compositing program. It won't be perfect but plausible results are achievable that are guaranteed to never flicker. As proof of the Light Rig concept on the moving objects, the video below shows the moving objects lit by a light rig comprising of just around 16 or so directional lights, without shadows, along with the Sun and Sky. This isn't a bad way to go if you're working with an exceptionally complex scene that would require unavailable increases in render time for the significantly more expensive Final Gather computations on extremely detailed moving objects.



Please feel free to leave comments and suggestions!