Home Creators Posts Import Register Favorites Logout

Content

Light Path Expressions, or LPEs, are a very powerful tool for managing light contributions in render outputs. They're also complicated and difficult to understand. Let's fix that!

Background

What are LPEs and what are they used for?

LPEs are a way to create custom AOVs that isolate specific light behavior in a render. For example, they could be used to create an AOV for only direct light in your scene, only indirect, only emissive materials, only a specific object, everything but a specific light... you name it. The possibilities are endless. You can use these AOVs for great flexibility in compositing, allowing you to micromanage every aspect of your scene post-render.

Path-traced rendering is based on the concept of rays being sent from the camera and bouncing off objects in the scene until they reach a light source. Each one of these rays is a light path. "Expressions" refers to the use of regular expression (regex) syntax in LPEs. Regexes are a method of using symbols to parse strings of text. They're also notorious for their potential unreadability: (\W|^)po[#\-]{0,1}\s{0,1}\d{2}[\s-]{0,1}\d{4}(\W|$)

An old joke goes:

Some people, when confronted with a problem, think, "I know, I'll use regular expressions." Now they have two problems.

Thankfully, the regex used in LPEs is pared-down and is generally much clearer than the above.

Every light path consists of several events. There is always a camera event first and a light event last (or emissive event, since emission also illuminates).

In this diagram we see two light paths, a direct one in blue and an indirect one in green. Events are marked with red dots: we have a camera event, C, a light event, L, and numerous bounce events. (Note that direct light comes straight from a light source, while indirect is reflected. In the case of the green line, the light is reflected off of two walls.)

How would we describe this scene in LPE syntax? The simplest way is:

C.*L

This translates to:

Camera event (C) -> any event (.), that repeats zero or more times (*) -> light event (L)

The resulting AOV would display the complete scene since it covers all possible events.

This notation would not include emissive objects, however. L is lights only. We'd need to add an O, which is the symbol for emission. Updating our LPE, we get:

C.*[LO]

The square brackets [] mean ANY events contained within. So, this LPE looks for a camera event followed by any number of other events of any type, ending in either a light OR emission event.

LPE syntax will work in any renderer that supports it; Karma, Arnold, RenderMan, and many more. The details might vary slightly to cover unique features of each renderer, but the overall format should be the same. Be sure to check your renderer's documentation for details.

Let's set up a demo scene in Solaris to dig deeper. I put in a little bit of everything; glass, subsurface, glossy, volume, lights and emissive materials.

This isn't a Houdini tutorial, but I'll quickly explain what we're doing here in Karma. I added a Karma Render Settings node at the end of the tree. Under the Image Output tab, in the AOVs (Render Vars) section you can scroll down and add custom LPEs under Extra Render Vars. Give the LPE a Name (this is the name that it will have in your final render), set the Format as appropriate (all the stuff we'll be doing is fine as color3h, that is, red, green and blue at 16 bit/half precision), and set the Source Type to LPE.

Now we can enter our LPE syntax into the Source Name field and view the generated AOV by clicking the Render Outputs icon next to the viewport.

To start, let's create the catch-all LPE we made above: C.*[LO]. As expected, this displays the full scene.

Let's start playing around. C<RD>L will give us camera -> any single diffuse reflection event -> light. The angle brackets <> mean that ALL items within are required, not just any as with square brackets. This LPE gives us a typical diffuse direct AOV. The volume, SSS and glass turn black since they have no RD component.

Let's introduce a new symbol: +. A + means "one or more times." So, C<RD>.+L is camera -> any diffuse reflection event that repeats once or more -> light. In short, a diffuse indirect AOV showing bounced light and nothing else.

Let's explore how we can start isolating specific types of materials. Let's say we only want to see glossy surfaces. The syntax is CG.*[LO]: camera -> any glossy event, zero or more repetitions -> light/emission.

How about transmission only? CT.*[LO]. Camera -> any transmission event, zero or more repetitions -> light/emission. Note that SSS is a transmissive type of material.

Now, let's look into how to tag specific objects. We can use a Render Geometry Settings node to add LPE Tags to objects in our scene. Let's tag the center toy as "glass_toy":

If we wanted to see only the glass toy we could use the LPE C'glass_toy'.*[LO]. This is camera -> any event, zero or more repetitions, only affecting "glass_toy" -> light/emission.

We can also add tags to our lights. Let's say we wanted to see glossy or diffuse transmission only from the light on the right. After adding a tag, "right," to the appropriate light, we can use this LPE: C<T.>.*<L.'right'>. This translates to: camera -> only transmission (both kinds, TG and TD, glossy and diffuse), zero or more repetitions -> only from lights tagged "right."

What if we wanted to inverse this and exclude the "right" light? We can use the ^ symbol: C.*[<L.[^'right']>O]. (Brackets are required to group the ^ symbol with the tag.) This LPE shows everything in the scene, including emissive materials, except for the "right" light.

By now you can see how powerful this is. We can create AOVs for exactly the things we need and then have total control in post over our scene's appearance.

Conclusion

There you have it: a crash course covering every aspect of LPEs, from the theory behind them to their syntax. As a final note, remember that renderers sometimes have different naming conventions. Karma uses G for glossy, for example, while the equivalent in RenderMan is S for specular. Happy rendering!

Files

Comments

No comments found for this post.