Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents
minLevel3

Final opacity

Bxdfs not only compute the scattering of light, but are also allowed to provide:

...

In RenderMan RIS 22, this has been unified, and presence and opacity are now combined into a single property, the final opacity. This final opacity can be used for both probabilistic hit-testing and traditional 'blending' opacity.

...

  • the RixOpacity API still exposes two hooks (for each of the presence/scalar and opacity/colored component of the final opacity), and depending on the instance hint returned by the RixBxdfFactory, and on the ray type, only one of this hook may be called.
  • the shading mode (RixSCShadingMode) passed to RixBxdfFactory::BeginOpacity() is a hint as to the renderer's intentions for the RixOpacity object:

    • if the shading mode is k_RixSCPresenceQuery, only the RixOpacity::GetPresence() method will be calledRixBxdfFactory::BeginOpacity() need only evaluate the pattern inputs relevant to computing the presence component.
    • if the shading mode is k_RixSCOpacityQuery, either RixOpacity::GetPresence()RixOpacity::GetOpacity() (or both) will be executed on the object, and pattern inputs relevant to both presence and opacity components should be fully evaluated.

Presence (scalar 

...

Final Opacity)

Consider the case of trying to render a tree leaf. Rather than model it as a polygon mesh, it's common to represent a leaf as a cheap bilinear patch with an associated mask texture representing the leaf shape. Where the mask is zero, there is no leaf. We use the term presence rather than opacity to capture this use case. The leaf-shaped map is a scalar presence map.

...

  • 1 is fully present
  • 0 is fully absent
  • any value in between would usually denotes a probabilistic presence for anti-aliasing

Presence vs. Continuation

When dealing with opaque objects using presence maps, it is usually the case that the objects are either entirely present or not present at all. In practical terms: the presence map is used as a cut-out map, and consists mostly of 0-or-1 values. RenderMan takes advantage of this by combining presence with probabilistic hit-testing, actually interpreting the presence value as the probability that we actually hit a surface.

The compelling advantage of this approach is that for camera rays and indirect rays, the renderer only needs to shade the surface and run the associated bxdf when the surface is actually hit (due to a non-zero presence). This means the renderer doesn't need to institute a policy of automatic continuation rays.

Presence should not be used for cases where the intention is to model a thin semi-transparent surface (rather than an opaque object). Instead, the bxdf should generate a transmitted bxdf sample, with the appropriate properties (transmission color for example). Even if those samples are generated in the exact same direction as the incoming ray, without refraction (i.e. to model a thin translucency), they have to be generated by RixBxdf::GenerateSample(), which means that the presence needs to be 1. Depending on the intention, this transmitted sample may be generated as a continuation sample.

Cached Presence

RenderMan offers an additional service that may improve performances for scenes making heavy use of presence (e.g. a forest of trees with presence-mapped leaves). By having RixBxdfFactory::GetInstanceHints() return a bit vector that includes the k_PresenceCanBeCached bit, the bxdf can request RenderMan to cache presence values. This would prevent re-evaluation of the presence values for every ray that intersects the surface.

However, note that as with most of the caching systems, this may introduce bias, manifesting itself as blurred results due to interpolation from the cached values. Presence caching efficiency is driven by the opacitycachememory setting – a speed vs memory trade-off.

Opacity

Opacity (colored Final Opacity)

As explained in the Presence section, it would be the responsibility of a semi-translucent thin glass-like bxdf to capture light transport across its surface (instead of using presence). However, when it comes to transmission rays, requiring a similar responsibility is problematic for two reasons:

...

Nonetheless, it can be desirable to have a method by which approximate colored shadows can be efficiently produced. These are often preferable to the physically realistic, but noisy, color shadows produced by considering indirect paths. RenderMan allows the bxdf to return an opacity color, which will to influence the colors of shadow resulting from tracing transmission rays. An opaque object would yield black shadows, as if returning an opacity of [1 1 1], i.e. white.

...

Note that when writing a bxdf for a thin translucent surface, careful consideration should be given as to whether indirect rays should also be fired through the surface. If colored opacity is being used (and depending on the circumstances) it is quite likely that such rays should not be fired, otherwise the lighting contribution will be doubled.

Historically, colored final opacity would only be used for transmission rays, but it is now possible for it to affect camera and indirect rays. Similarly to the explanation above, special care needs to be taken by the bxdf to make sure there is no double contribution.

 

Volumetric crepuscular rays, efficiently rendered using direct lighting by means of stained glass using colored opacity

...

  • 1 is opaque
  • 0 is non-opaque
  • any value in between will yield colored transmission shadows (the shadow color is 1 - opacity)

Combined presence and opacity

When the RixOpacity API returns both a presence and an opacity value, they are combined (multiplied) together. In this case, one could thing of the presence component as the 'intensity' and the opacity component as the 'color'.

Probabilistic hit-testing vs. blend-and-continue

The final opacity can be used in two ways:

  • as a probability that the surface is present (historical use of the presence scalar component)
  • as a coloring of the light transmitted through the surface (historical use of the opacity color component)

The former would usually use probabilistic hit-testing, where each camera ray would use the (scalar) presence value as a probability to hit the surface, and either result in an actual hit, or a continuation (without a hit). In this case, for each original ray, only one shading event is computed (on the actual hit), although multiple presence evaluations may have happened.

The latter would usually usually use blending-and-continuation. On hitting a surface with (colored) opacity, shading would be computed, and weighted by (1 - opacity). A continuation ray would then be traced from this hit point (carrying a colored weight equal to opacity), and the process repeats, until hitting a surface with full opacity. In this case, for each original ray, multiple shading events may be computed (and special care needs to be taken to prevent a combinatoric explosion of the number of rays and shading events).

In Renderman RIS 22, it is possible to use both approaches in all cases, independently of the final opacity being scalar or colored. This means:

  • a colored final opacity can be used with probabilistic-hit testing. In this case, additional colored weights are provided through the RixShadingContext so that the (converged) results are identical to the ones obtained with the blending-and-continuation approach.
  • a scalar final opacity can be used with blending-and-continuation. In this case, a mono-chromatic value is used for blending, and continuation rays are traced. This would yield results identical to the ones obtained with probabilistic-hit testing, with a lot less noise, at the cost of additional shading computations.

Note that:

  • if the final opacity is zero, the renderer will always skip the hit. This means RixShadingContext should never yield hits whose (final) opacity is zero.
  • using blending-and-continuation for indirect rays may yield a combinatoric explosion of rays and shading event

Cached Presence and Opacity

As with cached presence, RenderMan offers an additional service that may improve performance performances for scenes making heavy use of presence/opacity/final opacity (e.g. a forest of trees with presence-mapped leaves).

By having  By having RixBxdfFactory::GetInstanceHints() return  return a bit vector that includes the k_PresenceCanBeCached bit, the bxdf can request RenderMan to cache presence values. This would prevent re-evaluation of the presence component for every ray that intersects the surface.

By having RixBxdfFactory::GetInstanceHints() return a bit vector that includes the k_OpacityCanBeCached bit bit, the bxdf can request RenderMan to cache cache opacity values values. This would prevent re-evaluation of the the opacity values  component for every ray that intersects the surface.

However, note that as with most of the caching systems, this may introduce bias, manifesting itself as blurred shadows results due to interpolation of from the cached opacity values. Opacity caching efficiency  Presence and opacity caching efficiency is driven by the opacitycachememory setting --the the opacitycachememory setting – a speed vs memory trade-off. The more memory is allocated to this cache, the more efficient the opacity reuse will be.

...

[Historical] Using Both Presence and Opacity

Bxdfs are allowed to compute both both presence and  and opacity. In this case, when dealing with with transmission rays, both both presence and  and opacity are  are separately computed, and combined by the renderer into the transmission result across the surface.

Note that the shading mode (RixSCShadingMode) passed to RixBxdfFactory::BeginOpacity() is a hint as to the renderer's intentions for the RixOpacity object:

  • if the shading mode is k_RixSCPresenceQuery, only the RixOpacity::GetPresence() method will be called. RixBxdfFactory::BeginOpacity() need only evaluate the pattern inputs relevant to computing presence.
  • if the shading mode is k_RixSCOpacityQuery, either RixOpacity::GetPresence(), RixOpacity::GetOpacity() (or both) will be executed on the object, and pattern inputs relevant to both presence and opacity should be fully evaluated.


[Historical] Presence vs. Bxdf Continuation

When dealing with opaque objects using presence maps, it is usually the case that the objects are either entirely present or not present at all. In practical terms: the presence map is used as a cut-out map, and consists mostly of 0-or-1 values. RenderMan takes advantage of this by combining presence with probabilistic hit-testing, actually interpreting the presence value as the probability that we actually hit a surface.

The compelling advantage of this approach is that for camera rays and indirect rays, the renderer only needs to shade the surface and run the associated bxdf when the surface is actually hit (due to a non-zero presence). This means the renderer doesn't need to institute a policy of automatic continuation rays.

Presence should not be used for cases where the intention is to model a thin semi-transparent surface (rather than an opaque object). Instead, the bxdf should generate a transmitted bxdf sample, with the appropriate properties (transmission color for example). Even if those samples are generated in the exact same direction as the incoming ray, without refraction (i.e. to model a thin translucency), they have to be generated by RixBxdf::GenerateSample(), which means that the presence needs to be 1. Depending on the intention, this transmitted sample may be generated as a continuation sample.

...