Skip to content

Commit

Permalink
Fix transmission implementation and improve specification (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
portsmouth authored Feb 9, 2024
1 parent 23cf223 commit 656945e
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 14 deletions.
21 changes: 11 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@

Many real-world objects are made of several different materials arranged in patches, e.g. metal and oxide regions on a rusty object, and it is convenient to model the appearance of such objects by texturing the type of each material on their surfaces. While the material transitions are typically abrupt in reality, the ability to continuously mix materials is useful for artistic purposes as well as for anti-aliasing.

The mix operation models this as a linear blend between two materials at the mesoscopic level. The physical picture is that the mesosurface consists of randomly distributed patches of each material in proportion to the blend weight, which thus exhibits heterogeneity in the "horizontal" direction.
The mix operation models this as a linear blend between two materials at the mesoscopic level. The physical picture is that the mesosurface consists of randomly distributed patches of each material in proportion to the blend weight, which thus exhibits heterogeneity in the "horizontal" direction.
The mix operation of two slabs $S_0$ and $S_1$ with weight $w_1$, generating a new “horizontally” heterogeneous composite material $M$, is denoted:
\begin{equation}
M = \mathrm{\mathbf{mix}}(S_0, S_1, w_1)
Expand Down Expand Up @@ -405,7 +405,7 @@
\begin{equation} \label{openpbr-anisotropy-formula}
\alpha_t = r^2 \sqrt{\frac{2}{1 + (1 - a)^2}} \;\ , \quad \alpha_b = (1 - a) \, \alpha_t \ .
\end{equation}
This formulation satisfies $\alpha_t^2 + \alpha_b^2 = 2\alpha^2$, to preserve the average roughness regardless of the anisotropy. A rationale is that if a renderer doesn't support anisotropy (or if the feature is turned off for performance considerations, such as level of detail), using only the roughness parameter should result in an isotropic specular highlight perceptually close to the original anisotropic one. Figure [ndf_anisotropy] shows the resulting shape of the highlight (technically, these are contour lines of the NDF $D_\mathrm{GGX}(m)$ in the 2D slope space).
This formulation satisfies $\alpha_t^2 + \alpha_b^2 = 2\alpha^2$, to preserve the average roughness regardless of the anisotropy. A rationale is that if a renderer doesn't support anisotropy (or if the feature is turned off for performance considerations, such as level of detail), using only the roughness parameter should result in an isotropic specular highlight perceptually close to the original anisotropic one. Figure [ndf_anisotropy] shows the resulting shape of the highlight (technically, these are contour lines of the NDF $D_\mathrm{GGX}(m)$ in the 2D slope space).

![Figure [ndf_anisotropy]: NDF shapes as a function of roughness $r$ and anisotropy $a$.](images/anisotropy.png width=60%)

Expand Down Expand Up @@ -509,7 +509,7 @@

- The specular lobe shape is controlled by the roughness properties of the surface, parametrized by **`specular_roughness`**, **`specular_anisotropy`**, and **`specular_rotation`** (see the section on the [Microfacet model](index.html#model/microfacetmodel) NDF).

- The **`specular_ior`** parameter controls the index of refraction of the dielectric, which in this case only affects the Fresnel factor. The **`specular_ior_level`** parameter additionally provides a convenient $[0, 1]$ control for dialing the dielectric reflectivity (at normal incidence) to zero at the minimum and double the original reflectivity at the maximum, by modulating the IOR. This is useful for texturing the specular reflectivity in a more physically correct way than via the **`specular_weight`** (since low **`specular_weight`** suppresses the entire specular lobe at all viewing angles, while low **`specular_ior_level`** still retains the Fresnel highlights at grazing angles).
- The **`specular_ior`** parameter controls the index of refraction of the dielectric, which in this case only affects the Fresnel factor. The **`specular_ior_level`** parameter additionally provides a convenient $[0, 1]$ control for dialing the dielectric reflectivity (at normal incidence) to zero at the minimum and double the original reflectivity at the maximum, by modulating the IOR. This is useful for texturing the specular reflectivity in a more physically correct way than via the **`specular_weight`** (since low **`specular_weight`** suppresses the entire specular lobe at all viewing angles, while low **`specular_ior_level`** still retains the Fresnel highlights at grazing angles).

The formula for the specular IOR modulation is as follows. Given the existing **`specular_ior`**, the ratio $\eta_s$ of this to the IOR of the surrounding medium is computed (which should take into account the presence of the coat, according to equation [effective_coat_ior] in the Coat section).
Given this ratio, the dielectric Fresnel reflection factor of $f_\mathrm{dielectric}$ at normal incidence is given by
Expand Down Expand Up @@ -660,12 +660,13 @@
The index of refraction of $V^\infty_\mathrm{dielectric}$ is specified by **`specular_ior`** (as for the entire dielectric-base).

The volumetric properties of $V^\infty_\mathrm{dielectric}$ are specified as follows.
The RGB **`transmission_color`** $\mathbf{T}$ and scalar **`transmission_depth`** $\lambda$ parameter pair is a commonly used artist-friendly way to set the volumetric medium extinction coefficient $\boldsymbol{\mu}_t$ (such that the Beer's law extinction produces the specified transmission color at the specified depth):
The RGB **`transmission_color`** $\mathbf{T}$ and scalar **`transmission_depth`** $\lambda$ parameter pair is a commonly used artist-friendly way to set the volumetric medium extinction coefficient $\boldsymbol{\mu}_t$.

The **`transmission_depth`** is the distance traveled inside the medium by white light before its color becomes exactly **`transmission_color`** by Beer's law, determining the extinction coefficient of the interior medium $\boldsymbol{\mu}_t$ as follows:
\begin{equation}
\boldsymbol{\mu}_t = - \frac{\ln \mathbf{T}} {\lambda} \ .
\end{equation}
Being a length, **`transmission_depth`** can be any value greater than or equal to zero. For convenience, we make the soft range $[0, 1]$, thus covering common cases.
However when **`transmission_depth`** $\lambda$ is zero, it is assumed that the interior medium is absent ($\boldsymbol{\mu}_t=0$) and **`transmission_color`** is used instead to non-physically tint the dielectric refraction Fresnel factor multiplicatively by a constant amount (ignoring the dielectric energy balance).
Being a length, **`transmission_depth`** can be any value greater than or equal to zero. For convenience, we make the soft range $[0, 1]$, thus covering common cases. However when **`transmission_depth`** $\lambda$ is zero, it is assumed that the interior medium is absent ($\boldsymbol{\mu}_t=0$) and **`transmission_color`** is used instead to non-physically tint the dielectric refraction Fresnel factor multiplicatively by a constant amount (ignoring the dielectric energy balance).

The **`transmission_scatter`** parameter $\mathbf{S}$ directly sets the medium scattering coefficient $\boldsymbol{\mu}_s$ (as a multiple of the inverse **`transmission_depth`**):
\begin{equation}
Expand Down Expand Up @@ -712,7 +713,7 @@
\begin{equation}
V_d = \frac{\mathtt{transmission\_dispersion\_abbe\_number}} {\mathtt{transmission\_dispersion\_scale}} \ .
\end{equation}
At the default **`transmission_dispersion_scale`** of zero, the Abbe number is infinite, which corresponds to no dispersion. At the maximum of 1, the Abbe number peaks at $V_d = \mathtt{transmission\_dispersion\_abbe\_number}$ which defaults to 20.
At the default **`transmission_dispersion_scale`** of zero, the Abbe number is infinite, which corresponds to no dispersion. At the maximum of 1, the Abbe number peaks at $V_d$ = **`transmission_dispersion_abbe_number`** which defaults to 20.

The default 20 was chosen since common real materials with the highest dispersion have Abbe numbers roughly greater than or equal to this (for example, different types of glass have Abbe numbers between 20 and 91 [#Schott2023], water and diamond both have Abbe numbers between 55 and 56, while the oxide mineral rutile, composed of titanium dioxide, exhibits extremely high dispersion with an Abbe number of 9.87 [#Polyanskiy2023]). In most cases the **`transmission_dispersion_scale`** therefore functions as a convenient roughly linear slider from low to high dispersion. For those special cases where the Abbe number of a specific material is wanted, the Abbe number itself can be changed via **`transmission_dispersion_abbe_number`**.

Expand All @@ -726,11 +727,11 @@
------------------------------------------|------------------|----------|:---------------:|:-----------:|:-------------:|----------------------------------------------
**`transmission_weight`** | Weight | `float` | $ [0, 1] $ | | $ 0 $ | Mix weight between translucent base and opaque base slabs
**`transmission_color`** | Color | `color3` | $ [0, 1]^3 $ | | $ (1, 1, 1) $ | Transmission color, specifies the extinction of $V^\infty_\mathrm{dielectric}$
**`transmission_depth`** | Depth | `float` | $ [0, \infty) $ | $ [0, 1] $ | $ 0 $ | Distance traveled inside the medium by white light before its color becomes exactly **`transmission_color`** by Beer's law, determining the extinction coefficient of the interior medium; if zero, **`transmission_color`** acts as a constant (on-surface) transmission tint
**`transmission_depth`** | Depth | `float` | $ [0, \infty) $ | $ [0, 1] $ | $ 0 $ | Controls the depth into the volume at which the **`transmission_color`** is realized; if zero, acts as a constant (on-surface) transmission tint
**`transmission_scatter`** | Scatter | `color3` | $ [0, 1]^3 $ | | $ (0, 0, 0) $ | Scattering coefficient of the interior medium
**`transmission_scatter_anisotropy`** | Anisotropy | `float` | $ [-1, 1] $ | | $ 0 $ | Anisotropy of the Henyey-Greenstein phase function of the interior medium $V^\infty_\mathrm{dielectric}$
**`transmission_dispersion_abbe_number`** | Abbe number | `float` | $ [0, \infty) $ | $ [9, 91] $ | $ 20 $ | Abbe number of the medium, inversely proportional to how much the index of refraction varies across wavelengths when **`transmission_dispersion_scale`** is `1`; defaults to approximately the highest Abbe number of any real clear dielectric so that any realistic amount of dispersion can be achieved by varying **`transmission_dispersion_scale`** in $[0, 1]$
**`transmission_dispersion_scale`** | Dispersion scale | `float` | $ [0, 1] $ | | $ 0 $ | Linearly scales the amount of dispersion by setting the final Abbe number for rendering to **`transmission_abbe_number`** divided by **`transmission_dispersion_scale`**
**`transmission_dispersion_scale`** | Dispersion scale | `float` | $ [0, 1] $ | | $ 0 $ | Linearly scales the amount of dispersion
**`transmission_dispersion_abbe_number`** | Abbe number | `float` | $ [0, \infty) $ | $ [9, 91] $ | $ 20 $ | Physical Abbe number of the base dielectric medium


Metal
Expand Down
2 changes: 1 addition & 1 deletion parametrization.md.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
| `transmission_depth` | Depth | `float` | $ [0, \infty) $ | $ [0, 1] $ | $ 0 $ | length |
| `transmission_scatter` | Scatter | `color3` | $ [0, 1]^3 $ | | $ (0, 0, 0) $ | |
| `transmission_scatter_anisotropy` | Anisotropy | `float` | $ [-1, 1] $ | | $ 0 $ | |
| `transmission_dispersion_abbe_number` | Abbe number | `float` | $ (0, \infty) $ | $ [9, 91] $ | $ 20 $ | |
| `transmission_dispersion_scale` | Dispersion scale | `float` | $ [0, 1] $ | | $ 0 $ | |
| `transmission_dispersion_abbe_number` | Abbe number | `float` | $ (0, \infty) $ | $ [9, 91] $ | $ 20 $ | |
| **Subsurface** |
| `subsurface_weight` | Weight | `float` | $ [0, 1] $ | | $ 0 $ | |
| `subsurface_color` | Color | `color3` | $ [0, 1] $ | | $ (0.8, 0.8, 0.8) $ | |
Expand Down
8 changes: 5 additions & 3 deletions reference/open_pbr_surface.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
doc="Specifies the distance light travels inside the transparent base before it becomes exactly the transmission_color according to Beer's law." />
<input name="transmission_scatter" type="color3" value="0, 0, 0" uimin="0,0,0" uimax="1,1,1" uiname="Transmission Scatter" uifolder="Transmission" uiadvanced="true"
doc="Controls the color of light volumetrically scattered inside the transparent base. Suitable for materials with visually significant scattering such as honey, fruit juice, murky water, opalescent glass, or milky glass." />
<input name="transmission_scatter_anisotropy" type="float" value="0.0" uimin="0.0" uimax="1.0" uiname="Transmission Anisotropy" uifolder="Transmission" uiadvanced="true"
<input name="transmission_scatter_anisotropy" type="float" value="0.0" uimin="-1.0" uimax="1.0" uiname="Transmission Anisotropy" uifolder="Transmission" uiadvanced="true"
doc="The amount of directional bias, or anisotropy, of the volumetric scattering in the transparent base." />
<input name="transmission_dispersion" type="float" value="0.0" uimin="0.0" uisoftmax="100.0" uiname="Transmission Dispersion" uifolder="Transmission" uiadvanced="true"
doc="Dispersion amount, describing how much the dielectric index of refraction varies across wavelengths." />
<input name="transmission_dispersion_scale" type="float" value="0.0" uimin="0.0" uimax="1.0" uiname="Transmission Dispersion Scale" uifolder="Transmission" uiadvanced="true"
doc="Linearly scales the amount of dispersion." />
<input name="transmission_dispersion_abbe_number" type="float" value="0.0" uimin="0.0" uisoftmin="9.0" uisoftmax="91.0" uiname="Transmission Dispersion Abbe Number" uifolder="Transmission" uiadvanced="true"
doc="Physical Abbe number of the dielectric medium, describing how much the dielectric index of refraction varies across wavelengths." />
<input name="subsurface_weight" type="float" value="0" uimin="0.0" uimax="1.0" uiname="Subsurface" uifolder="Subsurface Weight" uiadvanced="true"
doc="Mixture weight which dials the opaque dielectric base between diffuse reflection and subsurface scattering. A value of 1.0 indicates full subsurface scattering and a value 0 for diffuse reflection only." />
<input name="subsurface_color" type="color3" value="0.8, 0.8, 0.8" uimin="0,0,0" uimax="1,1,1" uiname="Subsurface Color" uifolder="Subsurface" uiadvanced="true"
Expand Down

0 comments on commit 656945e

Please sign in to comment.