Skip to content

[usdLux] normalized lights divide by surfaceArea expressed in meters^2 #3587

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

pmolodo
Copy link
Contributor

@pmolodo pmolodo commented Apr 3, 2025

Description of Change(s)

This allows normalized lights to compose correctly into stages with a different metersPerUnit setting, at a backwards-compatibility cost of a change in luminance of normalized lights before this, in layers with metersPerUnit != 1

(See below for a full discussion.)

Link to proposal (if applicable)

PixarAnimationStudios/OpenUSD-proposals#77

Checklist

Intro + Background

Neither the current UsdLux implementation, or the current version of the UsdLux clarifications and changes in this OpenUSD proposal (md) (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 (md) (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. 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, 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
      • 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
  • Add compensating scale xform (as normal)
  • Manually override intensity on all normalized lights
  • 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): no manual overrides on lights to preserve correct real-world units

    • The need for Option 1 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 - is a big winner here.

    Big win for Option 1 (Normalized Scene-relative units): 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 will change by orders of magnitude
    • 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

    Minor win for Option 1 (Normalized Scene-relative units): 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 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) vs better / more correct behavior going forward (Option 2)

    • The UsdLux clarification project is about providing better behavior going forward, at the cost of some backward compatibility, so overall we feel Option 2 is the better choice long-term.

    This allows normalized lights to compose correctly into stages with
    a different metersPerUnit setting, at a backwards-compatibility cost of
    a change in luminance of normalized lights before this, in layers with
    metersPerUnit != 1
    @pmolodo pmolodo force-pushed the pr/normalize-lights-using-fixed-meters-squared branch from 581b73f to facd5eb Compare April 3, 2025 20:54
    @jesschimein
    Copy link
    Collaborator

    Filed as internal issue #USD-10863

    (This is an automated message. See here for more information.)

    @jesschimein
    Copy link
    Collaborator

    /AzurePipelines run

    @spitzak
    Copy link

    spitzak commented Apr 7, 2025

    I'm pretty certain everybody wants option 1. The light does not change when the meters per unit changes, even if you are working with "real world light units". Yes the total amount of light emitted will increase by the square of the scale, but the distance of that light from any objects will also increase by the scale and thus drop off by the square of the scale.
    For every light an "area" is computed, and if "normalize" is on then when a ray hits the light, the color/intensity/etc settings are divided by this "area" to get the emitted value. What is missing in USD is the settings where "area" is 1.0. It would also be useful to pin down exactly how the "area" is computed (for instance does the cone angle change it?). Also any indication of how accurate the "area" of a mesh light needs to be, I suspect assuming it is a bounding-box-filling ellipsoid is good enough.

    @anderslanglands
    Copy link
    Contributor

    anderslanglands commented Apr 7, 2025

    Hi @spitzak, could you explain a bit more what you'r suggesting here? You seem to be saying that option 1 preserves brightness when a normalized light is scaled, which is not the case.

    @tallytalwar
    Copy link
    Contributor

    /AzurePipelines run

    2 similar comments
    @tallytalwar
    Copy link
    Contributor

    /AzurePipelines run

    @jesschimein
    Copy link
    Collaborator

    /AzurePipelines run

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    5 participants