Skip to content

Commit 90bfc67

Browse files
committed
[usdLux] normalized lights divide by surfaceArea expressed in meters^2
# Intro + Background Neither the current UsdLux implementation, or the current version of the UsdLux clarifications and changes in [this OpenUSD proposal](PixarAnimationStudios/OpenUSD-proposals#77) [(md)](https://github.com/NVIDIA-Omniverse/USD-proposals/blob/pr/usdlux-clarification/proposals/usdlux-clarification/README.md) [(pdf)](https://github.com/NVIDIA-Omniverse/USD-proposals/blob/pr/usdlux-clarification/proposals/usdlux-clarification/README.pdf), explicitly specify how the behavior of `LightAPI.inputs:normalize` relates to linear stage units (`metersPerUnit`), and what happens when the linear stage units change (ie, by being composed into another stage with different `metersPerUnit`). We wish to further update the UsdLux clarification to address this gap. ## Terms **lsu = linear stage unit(s)** - When used with a numerical value - ie, "the cube is 3 lsu" - it means the raw binary numerical value stored in the scene / computer, before any unit-aware compensation is done. - When used with a unit name - ie, "the lsu is centimeters", it means the setting stored in the scene, via `metersPerUnit` - ie, `metersPerUnit=.01` implies "the lsu is cm" **nit** - while not a formal SI unit, it is a common alias for the SI unit of luminance, candela per square meter (`cd/m^2`) ## Common usage of the normalize attribute In theory, you might desire to have normalized lights and non-normalized lights behave differently when composed into a scene with different units... but I struggled to come up with a credible common scenario for that. Most commonly, normalize is used to allow lighting artists to adjust the size of a light without affecting it's overall illumination output on the surrounding scene. ie, you might want to make shadows softer without dramatically altering the overall light level of the scene. It's used as a way to alter the way you sculpt the light while designing it - not as a way to mark it as a fundamentally different type of light, that should behave in a fundamentally different way from other lights, when placed into a new setting, or when automated, non-artistic operations are done on it. As transforms associated with changes in scene scale are "non-artistic" (and ideally, automated) changes, it follows that artists will generally want normalized and non-normalized lights to behave similarly in this situation. That is, if they have two lights that appear identical in two_lights.usd, except one is normalized and one isn't, they will want the two lights to *stay* identical to each other when placed into a new scene. # Assumptions and Observations ## Assumption 1: Light dimensions must be in lsu If this were not the case, then a layer with both lights + geometry would not retain the same relative size when composed into a scene with a different `metersPerUnit` - which is unlikely to be the wanted behavior. ## Assumption 2: For non-normalized lights, `inputs:intensity` represents luminance in `nits` This document is intended as a further exploration to the proposed UsdLux clarifications and changes from this [OpenUSD proposal](PixarAnimationStudios/OpenUSD-proposals#77) [(md)](https://github.com/NVIDIA-Omniverse/USD-proposals/blob/pr/usdlux-clarification/proposals/usdlux-clarification/README.md) [(pdf)](https://github.com/NVIDIA-Omniverse/USD-proposals/blob/pr/usdlux-clarification/proposals/usdlux-clarification/README.pdf), and that proposal assumes (non-normalized) `inputs:intensity` is in a fixed units, `nits`. ## Observation 1: Direct light sampling for non-normalized, non-ies lights are generally not affected by `metersPerUnit` For non-normalized lights, we've assumed `inputs:intensity` [is always a measure of base luminance in `nits`](#assumption-2-for-non-normalized-lights-inputsintensity-represents-luminance-in-nits). Because measurement of luminance is unaffected by distance, it is thus unaffected by a scale change. Most other UsdLux light properties are modifiers to the luminance, whose formulas do not depend on any values which are in scene units. (One possible exception are lights with attached ies files, whose measurements are defined to be luminous intensity values expressed in candela. However, we defer discussion of unit interaction with ies files for another disucssion.) Therefore, direct light sampling for non-normalized, non-ies lights are unaffected by scale changes. By "direct light sampling", I mean the sampling of a light for a ray known to intersect the light. The [light dimensions are in lsu](#assumption-1-light-dimensions-must-be-in-lsu), so a `metersPerUnit` change can/will affect their size and position in the scene, and therefore can affect whether a given ray will intersect it, or the exact sampling pattern used. But, once it's known a ray intersects a non-normalized, non-ies light, the `metersPerUnit` setting is unimportant. Therefore, other than ensuring the size scale of a non-normalized light is as desired, they will generally not present any special problems when undergoing unit changes. ------------------------------------------------------------------------------- # Normalized Area Light Option 1: Normalized lights divide by scene-relative surface area ## Summary of behavior - The `sizeFactor` for normalized area lights (where `luminance = inputs:intensity / sizeFactor`) is in scene-relative units of `lsu^2` - ie, we divide by the "raw" binary surface area, not taking scene units / `metersPerUnit` into account - Believe this is what most renderers currently do ## When rendering the composed stage, renderers need to: - **no extra action required** - because all relevant quantities are expressed in lsu, no conversions are necessary, and in theory, the renderer shouldn't even have to read the `metersPerUnit` setting ## When composing lighting scenes with different `metersPerUnit`, artists / end users need to: - artist action always required: **apply compensating scale xform** - ie, the current "standard behavior" taken to preserve real-world units for any reference with different `metersPerUnit` - additonal artist action required for normalized area lights: **per light overrides must be manually calculated and applied** - `inputs:intensity` is in lsu-relative units, and so remains unchanged - ...but because of the compensating scale xform, the dimensions of the light in lsu changes - because the dimensions of the light in lsu change, the calculated normalization scale factor changes, and thefore the luminance (in `nits`) of the light changes - put another way - the compensating scale xform will be treated just like any other scale xform, and the light will try to automatically adjust it's luminance without knowledge of the scene scale causing the brightness of the light to be incorrect relative to the intended size of the asset - HOWEVER - this change will not reflect how a "real world" light would behave, and therefore is unlikely to be what an end user "desires" - regardless of [whether the light is marked as "normalized" or not](#common-usage-of-the-normalize-attribute) - if the comosed asset also has non-normalized lights, their relative behavior will change - if the composed asset also has "normal" geo, the light interaction will change - therefore, the end user will need to manually apply new intensity override values on all normalized lights, which are precalculated to offset the scale change - also, any subsequent changes to intensity in the original source would be overriden/lost - Can we put the burden on USD or renderer, to handle this automatically? - Any solutions I could envision require significant additions or changes to USD ## Backwards compatibility behavior - This is generally the current behavior adopted by most renderers, so therea are no backward compatibility issues. ------------------------------------------------------------------------------- # Normalized Area Light Option 2: Normalized lights divide by fixed-unit surface area (meters^2) ## Summary of behavior - The `sizeFactor` for normalized area lights (where `luminance = inputs:intensity / sizeFactor`) is in fixed units of `meters^2` ## When rendering the composed stage, renderers need to: - for non-normalized area lights: - **no extra action required** - for normalized lights: - for "standard" area lights with non-zero surface area: - **normalization sizeFactor multiplied by `metersPerUnit`^2** - ie, the "raw" sizeFactor would be an area in units of lsu^2 - by multiplying by `metersPerUnit`^2, we would get an area in units of m^2 - for "line-like" lights with with zero-surface area, but a "length": - **normalization sizeFactor multiplied by `metersPerUnit`** - ie, the "raw" sizeFactor would be a length in units of lsu - by multiplying by `metersPerUnit`, we would get a length in units of m - lights that meet this condition: - CylinderLight with length != 0 and treatAsLine == true - for other lights: - **normalization sizeFactor unaffected by `metersPerUnit`** ## When composing lighting scenes with different `metersPerUnit`, artists / end users need to: - artist action always required: **apply compensating scale xform** - ie, the current "standard behavior" taken to preserve real-world units for any reference with different `metersPerUnit` - additonal artist action required for normalized area lights: **None** - The compensatory scale xform already ensured that the size of the lights, in real-world units, remained unchanged - The renderer will automatically apply the additional factor required to scale the normalization sizeFactor by the `metersPerUnit`, at render time (see above) - So no extra action needed on part of artist ## Backwards compatibility behavior - Area lights with normalize on, and a scale other than `metersPerUnit=1`, will be significantly brighter or darker in "old" vs "new" UsdLux - `newLuminance = oldLuminance / metersPerUnit^2` - ie, for scenes with default cm-scale (`metersPerUnit=.01`), normalized lights in "new" usdLux will have 10,000x higher luminance than with "old" UsdLux ------------------------------------------------------------------------------- # Summary and Analysis ## Summary of differences Here's a summary of differences, with my subjective rating of which option has the superior behavior in each area: | Normalized Area Units| 1: Scene-Relative (lsu^2) | 2: Fixed (m^2) | |---------------------------|----------------|-----------| | Additional renderer action | None | Multiply area by metersPerUnit^2 when normalizing | | Artist actions needed when composing lights into a stage with different `metersPerUnit` | <li> Add compensating scale xform (as normal) <li> Manually override intensity on all normalized lights | <li> Add compensating scale xform (as normal) | | Backwards Compatibility Issues | Full (current behavior) | Normalized lights significantly change luminance compared to old behavior (ie, scenes with default cm-scale become 10,000x brighter) | ## Analysis ### Big win for [Option 2 (Normalized Fixed Units)][Option2]: no manual overrides on lights to preserve correct real-world units - The need for [Option 1][Option1] to treat normalized units as different, and to have to manually calculate and apply overrides PER-NORMALIZED-LIGHT, is a significant extra burden - thus, [Option 2][Option2] - is a big winner here. ### Big win for [Option 1 (Normalized Scene-relative units)][Option1]: better backwards compatibility of normalized light intensity for "most" scenes - Unless a stage has a LSU of meters (ie, `metersPerUnit=1`), the brightness of normalized lights under [Option 2][Option2] will [change by orders of magnitude](#backwards-compatibility-behavior-1) - As the default LSU is centimeters (`metersPerUnit=1`), it is assumed that "many" / "most" scenes will have their normalized lights change significantly under [Option 2][Option2] ### Minor win for [Option 1 (Normalized Scene-relative units)][Option1]: renderers need no additional unit-aware changes - In the absence of other factors, obviously the fewer changes we require the renderers to make, the better - So the fact that [Option 1][Option1] requires no renderer-side changes is a win for it - ...however, it feels a relatively minor win, as it's a relatively straightforward / easy change, and we're already requiring a lot of other renderer-side changes ## Conclusion - We have a choice between backwards compatibility ([Option 1][Option1]) vs better / more correct behavior going forward ([Option 2][Option2]) - The UsdLux clarification project is about providing better behavior going forward, at the cost of some backward compatibility, so overall we feel [Option 2][Option2] is the better choice long-term. [Option1]: #normalized-area-light-option-1-normalized-inputsintensity-is-in-scene-relative-power-units-current-behavior [Option2]: #normalized-area-light-option-2-normalized-inputsintensity-is-in-fixed-power-units
1 parent 152930f commit 90bfc67

File tree

3 files changed

+63
-15
lines changed

3 files changed

+63
-15
lines changed

pxr/usd/usdLux/generatedSchema.usda

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class "LightAPI" (
166166
displayName = "Normalize Power"
167167
doc = """Normalizes the emission such that the power of the light
168168
remains constant while altering the size of the light, by dividing the
169-
luminance by the world-space surface area of the light.
169+
luminance by the world-space surface area of the light, in meters².
170170

171171
This makes it easier to independently adjust the brightness and size
172172
of the light, by causing the total illumination provided by a light to
@@ -195,19 +195,35 @@ class "LightAPI" (
195195
### Area Lights:
196196

197197
For an area light, the `sizeFactor` is the surface area (in world
198-
space) of the shape of the light, including any scaling applied to the
199-
light by its transform stack. This includes the boundable light types
198+
space, expressed in meters²) of the shape of the light, including any
199+
scaling applied to the light by its transform stack. The area should
200+
then be multiplied by the scene's `metersPerUnit^2` to convert the
201+
surface area into meters². Area lights include the boundable light types
200202
which have a calculable surface area:
201203

202204
- MeshLightAPI
203205
- DiskLight
204206
- RectLight
205207
- SphereLight
206-
- CylinderLight
208+
- CylinderLight with treatAsLine == false
207209
- (deprecated) GeometryLight
208210

209211
<center><b>
210-
sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light)
212+
sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light) * metersPerUnit²
213+
</b></center>
214+
215+
### Line Lights:
216+
217+
Lights that simulate 1-dimensional emissive \"lines\" have a `sizeFactor`
218+
equal to the length (in world space, expressed in meters) of the shape
219+
of the light, including any scaling applied to the light by its
220+
transform stack. The area should then be multiplied by the scene's
221+
`metersPerUnit` to convert the length into meters. Line lights include:
222+
223+
- CylinderLight with length != 0 and treatAsLine == True
224+
225+
<center><b>
226+
sizeFactor<sub>line</sub> = worldSpaceLength(light) * metersPerUnit
211227
</b></center>
212228

213229
### DistantLight:

pxr/usd/usdLux/lightAPI.h

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ class UsdLuxLightAPI : public UsdAPISchemaBase
424424
// --------------------------------------------------------------------- //
425425
/// Normalizes the emission such that the power of the light
426426
/// remains constant while altering the size of the light, by dividing the
427-
/// luminance by the world-space surface area of the light.
427+
/// luminance by the world-space surface area of the light, in meters².
428428
///
429429
/// This makes it easier to independently adjust the brightness and size
430430
/// of the light, by causing the total illumination provided by a light to
@@ -453,19 +453,35 @@ class UsdLuxLightAPI : public UsdAPISchemaBase
453453
/// ### Area Lights:
454454
///
455455
/// For an area light, the `sizeFactor` is the surface area (in world
456-
/// space) of the shape of the light, including any scaling applied to the
457-
/// light by its transform stack. This includes the boundable light types
456+
/// space, expressed in meters²) of the shape of the light, including any
457+
/// scaling applied to the light by its transform stack. The area should
458+
/// then be multiplied by the scene's `metersPerUnit^2` to convert the
459+
/// surface area into meters². Area lights include the boundable light types
458460
/// which have a calculable surface area:
459461
///
460462
/// - MeshLightAPI
461463
/// - DiskLight
462464
/// - RectLight
463465
/// - SphereLight
464-
/// - CylinderLight
466+
/// - CylinderLight with treatAsLine == false
465467
/// - (deprecated) GeometryLight
466468
///
467469
/// <center><b>
468-
/// sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light)
470+
/// sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light) * metersPerUnit²
471+
/// </b></center>
472+
///
473+
/// ### Line Lights:
474+
///
475+
/// Lights that simulate 1-dimensional emissive "lines" have a `sizeFactor`
476+
/// equal to the length (in world space, expressed in meters) of the shape
477+
/// of the light, including any scaling applied to the light by its
478+
/// transform stack. The area should then be multiplied by the scene's
479+
/// `metersPerUnit` to convert the length into meters. Line lights include:
480+
///
481+
/// - CylinderLight with length != 0 and treatAsLine == True
482+
///
483+
/// <center><b>
484+
/// sizeFactor<sub>line</sub> = worldSpaceLength(light) * metersPerUnit
469485
/// </b></center>
470486
///
471487
/// ### DistantLight:

pxr/usd/usdLux/schema.usda

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ class "LightAPI" (
252252
displayName = "Normalize Power"
253253
doc = """Normalizes the emission such that the power of the light
254254
remains constant while altering the size of the light, by dividing the
255-
luminance by the world-space surface area of the light.
255+
luminance by the world-space surface area of the light, in meters².
256256

257257
This makes it easier to independently adjust the brightness and size
258258
of the light, by causing the total illumination provided by a light to
@@ -281,19 +281,35 @@ class "LightAPI" (
281281
### Area Lights:
282282

283283
For an area light, the `sizeFactor` is the surface area (in world
284-
space) of the shape of the light, including any scaling applied to the
285-
light by its transform stack. This includes the boundable light types
284+
space, expressed in meters²) of the shape of the light, including any
285+
scaling applied to the light by its transform stack. The area should
286+
then be multiplied by the scene's `metersPerUnit^2` to convert the
287+
surface area into meters². Area lights include the boundable light types
286288
which have a calculable surface area:
287289

288290
- MeshLightAPI
289291
- DiskLight
290292
- RectLight
291293
- SphereLight
292-
- CylinderLight
294+
- CylinderLight with treatAsLine == false
293295
- (deprecated) GeometryLight
294296

295297
<center><b>
296-
sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light)
298+
sizeFactor<sub>area</sub> = worldSpaceSurfaceArea(light) * metersPerUnit²
299+
</b></center>
300+
301+
### Line Lights:
302+
303+
Lights that simulate 1-dimensional emissive "lines" have a `sizeFactor`
304+
equal to the length (in world space, expressed in meters) of the shape
305+
of the light, including any scaling applied to the light by its
306+
transform stack. The area should then be multiplied by the scene's
307+
`metersPerUnit` to convert the length into meters. Line lights include:
308+
309+
- CylinderLight with length != 0 and treatAsLine == True
310+
311+
<center><b>
312+
sizeFactor<sub>line</sub> = worldSpaceLength(light) * metersPerUnit
297313
</b></center>
298314

299315
### DistantLight:

0 commit comments

Comments
 (0)