Component Shaders
Fast Scatter
This is the main shader that does the actual scattering. It is highly
modular and works with several plug-in shaders, and it can even be
cascaded into itself for multi-layer scattering (as is done in
misss_fast_skin_phen).
It layers the results from the plug-in shaders with the scattered light
from the lightmap (optionally nonlinearly, in what is known as "screen"
transfer mode in various compositing applications) and presents the
result as a final composited color.
misss_fast_shader
color "misss_fast_shader" (
color texture "lightmap",
color texture "depthmap",
shader "bump",
shader "diffuse_illum",
color "diffuse_color",
shader "specular_illum",
scalar "diffuse_weight",
color "front_sss_color",
scalar "front_sss_weight",
scalar "front_sss_radius",
color "back_sss_color",
scalar "back_sss_weight",
scalar "back_sss_radius",
scalar "back_sss_depth",
scalar "scale_conversion",
boolean "screen_composit",
boolean "output_sss_only",
scalar "falloff",
integer "samples"
shader "fallback_shader")
- lightmap
depthmap - are the light and depthmap pair from which
to extract the data. For more details, read about
misss_lightmap_write and the section
on Automatic lightmap generation.
- bump
- is a shader that perturbs the normal. While one could use a
shader list and something like mib_bump_passthrough before this
shader, for large scattering radii it is preferred that the shader is
aware of the normal vector before bump mapping. When a bump mapping shader
is assigned to this parameter instead,
misss_fast_shader will know the
normal both before and after bump mapping.
- diffuse_illum
- passes any normal illumination shader (returning a color)
for the diffuse illumination, generally a named shader based on
mib_illum_lambert. If nothing is
passed, it automatically defaults to Lambert.
- diffuse_color
- is an overall color that is applied to
all diffuse light, including the scattered contributions.
- specular_illum
- passes any normal illumination shader
(returning a color) for the specular and reflective components.
If nothing is passed, no specular shading happens. This is
layered on top of any diffuse contributions.
- diffuse_weight
- is a simple scalar multiplier for the
color returned by the diffuse_illum shader, for easier
tweaking.
- front_sss_color
front_sss_weight - are the
color and weight for the front surface scattering.
- front_sss_radius
- is the scatter radius in the front
surface. Light will scatter this distance (in whatever units the
model is made) along the surface.
- back_sss_color
back_sss_weight - are the color
and weight of the back surface (or through) scattering.
- back_sss_radius
- is the scatter radius and
back_sss_depth the depth in the back surface. Generally,
the radius and depth are set to the same value (and if the depth
is not specified, it defaults to the radius) but can be set
separately for increased control.
- scale_conversion
- is a simple utility function allowing
linear division of all distances. Since scattering is distance
dependent, loading a material designed for a model made in inches
will not work on a model where the unit is meters, and vice
versa. Here one can pass the conversion factor.
- screen_composit
- when turned on, chooses Screen
compositing. When simply adding together the contribution of many
layers of light, it is very easy to quickly blow out and
overexpose into white, but the human eye is inherently nonlinear
and perceives intensities in a different way. This option allows
use of what is known in many compositing applications as a screen
transfer mode between the layers, which yields a softer, more
pleasing result. If it is turned off, normal addition is used. If
rendering in a high dynamic range, and a proper tone-operator is
applied in the final output stage already compressing the final
luminance, use off. If not, turning this option on yields a more
pleasing result.
- output_sss_only
- is for debugging and testing or for
preparing for external compositing; If it is on, only the
scattered contribution is shown.
- falloff
- sets the shape of the distance falloff along
the scatter radius. Higher values yield a sharper falloff, and
lower values a smoother falloff, but also make the perceived
scatter distance shorter, so one must compensate by increasing
the actual scatter distance for a slightly softer look. For high
values (1.0 to 10.0), almost all samples within the scatter
radius are weighted equally. For low values (0.1 to 1.0), the
samples near the edge of the scatter radius are weighted a
less.
- samples
- sets how many samples from the lightmap are
considered (maximum) per rendered ray, ideally, a power of two.
32 is probably the lowest useful value, 128 is plenty.
- fallback_shader
- is a shader used for cases where no
stored lightmap samples can be found within the scatter radius.
If this parameter is not set, a built-in Lambert shader is
used. If this parameter is set, the value returned by the attached
shader is used. For best results, this should be the same shader
used as lightmap sampling shader in the lightmapping stage.
misss_fast_shader_x
struct {
color "result", # composited color
color "diffuse_result", # diffuse layer
color "diffuse_raw",
color "diffuse_level",
color "specular_result", # specular is not altered by the shader, but
# passed through from "specular_illum" sub-shader
color "front_result", # the "front" SSS layer
color "front_raw",
color "front_level",
color "back_result", # the "back" SSS layer
color "back_raw",
color "back_level"
}
"misss_fast_shader_x" (
color texture "lightmap",
color texture "depthmap",
shader "bump",
shader "diffuse_illum",
color "diffuse_color",
shader "specular_illum",
scalar "diffuse_weight",
color "front_sss_color",
scalar "front_sss_weight",
scalar "front_sss_radius",
color "back_sss_color",
scalar "back_sss_weight",
scalar "back_sss_radius",
scalar "back_sss_depth",
scalar "scale_conversion",
boolean "screen_composit",
boolean "output_sss_only",
scalar "falloff",
integer "samples",
shader "fallback_shader")
This shader has identical behavior to
misss_fast_shader
but provides individual components of the shading results as output
values before compositing them into the final color value. This supports
multi-channel rendering approaches where compositing is performed in
external packages.
Fast Scatter 2
misss_fast_shader2
This is an updated and slightly more physical version of the fast scatter
shaders. The primary differences is that scatter radii are defined per
color (with individual scatter radii for the red, green and blue components).
Also, the falloff in energy of the light is always exponential, unlike
the older misss_fast_shader
which has an explicit parameter to modify the falloff.
The primary benefit with this new shader is that it allows a more
realistic effect, since scattering in the real world is exponential, and
wavelength-dependent. This also lowers the number of scattering layers
needed for a realistic effect; in the past at least two layers were needed
to simulate skin, to allow the red color to scatter further. This is
no longer necessary with this new shader (although multiple can still be
used for greater artistic control.)
Comparison between old (left) and new (right) shaders
On the left we see the older shader. Light that bleeds into the
shadow is uniform in color (gray in this image), and light bleeding
through the object is red only due to the fact that the default
back_sss_color is red. In contrast, on the right, we see
the wavelength dependent scattering. Light that scatters into the
shadow have a range of colors from white to yellow to red, which
is also true for light scattering through the object. These
red-shifts exists because the red, green and blue scatter radii
are different; in the right image, all scatter colors are set to
white.
Here are the parameters of misss_fast_shader2:
color "misss_fast_shader2" (
color texture "lightmap",
color texture "depthmap",
shader "bump",
shader "diffuse_illum",
color "diffuse_color" default 1 1 1,
shader "specular_illum",
scalar "diffuse_weight" default 0.5,
color "front_sss_color" default 0.8 0.8 0.8,
scalar "front_sss_weight" default 0.5,
vector "front_sss_radius" default 20 10 5,
color "front_sss_radius_mod" default 1 1 1,
color "back_sss_color" default 0.8 0.8 0.8,
scalar "back_sss_weight" default 0.5,
vector "back_sss_radius" default 20 10 5,
color "back_sss_radius_mod" default 1 1 1,
scalar "back_sss_depth", # unassigned (zero) means "same as radius"
scalar "sampling_radius_mult" default 3.0,
scalar "scale_conversion" default 1.0,
boolean "screen_composit" default off,
boolean "output_sss_only",
integer "samples" default 64,
shader "fallback_shader"
)
Most parameters are identical in behavior to
misss_fast_shader
with these exceptions and notes:
- front_sss_radius
- is not a scalar but a vector, with three different radii,
for the red, green and blue light respectively. Generally, red scatters the most,
green less, and blue very little. Note that the falloff is exponential
and has no hard stop (unlike the old shader), so the value set here is at which
distance the light has diminished to 10 precent of its original intensity, not
where the intensity is zero.
- front_sss_radius_mod
- is a color parameter allowing the modification
of the scatter radii. This exists to ease applying a texture map for changing
the scatter radii across the surface; the texture can vary within a normal
black-to-white range, which is multiplied by the values set in the
front_sss_radius parameters.
- back_sss_radius
- is a vector with three different radii for the red, green
and blue component of the back scattering. Values work the same as front_sss_radius.
- back_sss_radius_mod
- is a radius modification input, working the same as
front_sss_radius_mod.
- sampling_radius_mult
- is a multiplier for the largest radii set
in either of the front_sss_radius and back_sss_radius for within
which any samples are actually taken. So if the largest of any these radii is
e.g. 10 units, setting this parameter to 2.0 will cause samples to actually be taken
within 20 units distance, completely ignoring any light outside that radius.
Setting this value too small, can yield a visible hard cutoff to the scattering.
Setting it too large, and too many samples are wasted in far away samples with
extremely small contribution; since the falloff is exponential, and the scattering
radii parameters are defined as "distance until 10 percent contribution" the
furthest samples would have a weight of 10 percent raised to the power of this
parameter (2 = 1 percent, 3 = 0.1 percent, 4 = 0.01 percent etc)
misss_fast_shader2_x
struct {
color "result", # composited color
color "diffuse_result", # diffuse layer
color "diffuse_raw",
color "diffuse_level",
color "specular_result", # specular is not altered by the shader, but
# passed through from "specular_illum" sub-shader
color "front_result", # the "front" SSS layer
color "front_raw",
color "front_level",
color "back_result", # the "back" SSS layer
color "back_raw",
color "back_level"
}
"misss_fast_shader_x" (
color texture "lightmap",
color texture "depthmap",
shader "bump",
shader "diffuse_illum",
color "diffuse_color" default 1 1 1,
shader "specular_illum",
scalar "diffuse_weight" default 0.5,
color "front_sss_color" default 0.8 0.8 0.8,
scalar "front_sss_weight" default 0.5,
vector "front_sss_radius" default 20 10 5,
color "front_sss_radius_mod" default 1 1 1,
color "back_sss_color" default 0.8 0.8 0.8,
scalar "back_sss_weight" default 0.5,
vector "back_sss_radius" default 20 10 5,
color "back_sss_radius_mod" default 1 1 1,
scalar "back_sss_depth", # unassigned (zero) means "same as radius"
scalar "sampling_radius_mult" default 3.0,
scalar "scale_conversion" default 1.0,
boolean "screen_composit" default off,
boolean "output_sss_only",
integer "samples" default 64,
shader "fallback_shader"
)
This shader is identical in behavior to
misss_fast_shader2
but with the multiple outputs as described in
misss_fast_shader_x.
Shader Usage
The misss_fast_shader(..)
family of shaders conceptually work with the layering of several light
contributions, all stacked on top of each other. The actual
compositing can be done with simple addition or with the softer
looking screen compositing.
Conceptual layering of misss_fast_shader
Plug-in shaders provide the actual contribution for the
various layers. bump, diffuse_illum and
specular_illum are the main plug-in shaders that provide
the shading model.
The bump shader affects the surface normal and is
called before the "... _illum" shaders and hence affects
their shading. However, no bump mapping is performed on the
scattered light, since this happens under the surface. It
is possible to include the effect of bump mapping in the light
before it is scattered by including a bump map shader in
the lightmapping phase.
To create the subsurface scattering itself, light from
specially prepared lightmaps is gathered, weighted by distance,
and tinted. The whole stack is finally layered together as
follows, from top to bottom.
- Layer 1: What the specular_illum shader returns.
- Layer 2: What the diffuse_illum shader returns.
- Layer 3: The front layer, which is the scattering within
the facing side of the object.
- Layer 4: The back layer, which is light shining through the object.
The following two observations are noteworthy: First, keep in
mind that the contributions from layers 2, 3 and 4 are all
multiplied with the " diffuse_color" parameter as an
overall tinting and attenuation color for the diffuse
contributions. Second, since the plug-in shaders are simply called
and layered in, it is possible to cascade several shaders
together to create multiple layers as follows:
Cascading of misss_fast_shader
This graph shows how a 2nd iteration of
misss_fast_shader is used as the
diffuse_illum parameter of the 1st. This works because the
scattering function receives its diffuse illumination from the
lightmaps, and does not care about what diffuse_illum
actually returns. It simply layers it into the mix.
This is precisely how the skin Phenomenon is implemented. A
second shader is cascaded into the first, giving an extra layer.
In principle, there is nothing preventing the stacking of an
arbitrary number of shaders.
Lightmap Creation
This is the lightmapping shader. It is required for the fast subsurface
scattering to work [1]. It creates a lightmap
and stores the front and back surfaces, their depth, and irradiant
light intensities in one or more specially formatted lightmaps.
Two modes of behavior are supported:
- Passing a single writable texture that must be floating
point (32 bits) to the lightmap parameter.
- Passing a lightmap_group and a lightmap_size,
causing the internal creation of an in-memory light and depthmap
pair. To use this option, the shader must be enclosed in a
Phenomenon where the lightmap and depthmap are the first two
parameters. See
Automatic lightmap generation.
misss_lightmap_write
struct {
vector "point",
vector "normal"
}
"misss_lightmap_write" (
color texture "lightmap",
color texture "depthmap",
string "lightmap_group",
scalar "lightmap_size",
integer "write_lightmap",
scalar "scatter_bias",
shader "input")
- lightmap
- should point to a writable color texture and
depthmap be unassigned or both should be assigned to a
pair of Phenomenon interface parameters as detailed in
Automatic lightmap generation.
- lightmap_group
- is a string with a scatter group name
with automatic lightmap generation. All objects and materials
that use the same scatter group will scatter light into each
other.
- lightmap_size
- is the size, in percent of render size,
for the automatically generated lightmap.
- write_lightmap
- is currently reserved for future use.
- scatter_bias
- adjusts the light in the lightmap to favor
back scattering (light from behind the camera scatters back
towards the camera) when using negative values and forward
scattering when using positive values. The technical range is -1
to 1, but generally only small values (-0.2 to 0.2) make visual
sense.
- input
- is the shader that actually samples the lighting
in the model for the lightmap. Generally
misss_lambert_gamma is used, but
any illumination shader can be used, for example
mib_illum_lambert or even experiment
with mib_illum_phong and scattering
of specular reflections.
Lambert Illumination
This is the supplied lightmap sampling shader. Any illumination shader
can be used like mib_illum_lambert
but this one is specially tuned for the job and has additional options for
lightmap gamma correction, normal flipping and indirect light inclusion.
misss_lambert_gamma
color "misss_lambert_gamma" (
color "ambient",
color "ambience",
color "diffuse",
boolean "indirect",
scalar "diffuse_curve",
integer "flip",
integer "mode",
array light "lights")
- diffuse
- is the diffuse color.
- ambient
ambience - are
multiplied with each other to yield a final contribution of
ambient light.
- indirect
- if on, will cause indirect illumination (such
as final gathering and photons) to be included in the lightmap,
at the expense of increased rendering time.
- diffuse_curve
- is the gamma curve for diffuse light. The
Lambertian cosine is raised to the power of this value (i.e.
pow(dot_nl, diffuse_curve)) to flatten (for values less
than 1.0) or narrow (for values above 1.0) the curve for greater
control.
- flip
- can be one of the following: 0, normals are not
flipped; 1, normals are flipped; or 2, both the unflipped and
flipped-normal sides are lightmapped. This can be useful for
translucency in thin objects such as leaves.
- mode
- is the mode selector for the
light lists.
- lights
- list of lights directly linked to the shader.
Specular Skin
This is a function geared towards recreating the peculiar specular
characteristics of skin. It contains two specular highlights and glossy
reflections with edge enhancement.
The shader can be used anywhere where specular highlights are
needed. It has no diffuse component and hence needs to be layered
together with another shader that provides the diffuse shading.
misss_skin_specular
color "misss_skin_specular" (
scalar "overall_weight",
scalar "edge_factor",
color "primary_spec_color",
scalar "primary_weight",
scalar "primary_edge_weight",
scalar "primary_shinyness",
color "secondary_spec_color",
scalar "secondary_weight",
scalar "secondary_edge_weight",
scalar "secondary_shinyness",
scalar "reflect_weight",
scalar "reflect_edge_weight",
scalar "reflect_shinyness",
boolean "reflect_environment_only",
integer "mode",
array light "lights")
- overall_weight
- is the overall level of specularity and
reflections. Generally, any specularity map is included here and
will affect the level of all specularity options that follow
below.
- edge_factor
- sets the edge width of the edge reflection
effects. Skin reflects more when watched in angles nearly
perpendicular to it (known as a "Fresnel effect") and this
parameter sets the narrowness of this edge. Higher values yield a
thinner edge. This edge width applies to all the edge weights
listed below.
- primary_spec_color
primary_spec_weight
- are the color and base weight for the first layer of specularity.
The skin specularity functions are two-layered, allowing simulation
of both the broad soft specularity of skin and any
near-reflective specularities of top layer oiliness and
wetness.
- primary_edge_weight
- sets the additional multiplier for
the edge, where final specularity at the edge is the sum of
weight and edge weight.
- primary_shinyness
- is the specular exponent (higher
values yield a smaller and sharper specular highlight, which is a
modified Phong with edge softening).
- secondary_spec_color
secondary_spec_weight
secondary_edge_weight
secondary_shinyness
- work exactly like the parameters that begin with primary_
and are for the second layer of specularity.
- reflect_weight
reflect_edge_weight
- the weight and edge weight for reflections. If it is nonzero, then
actual (glossy) reflections are added.
- reflect_shinyness
- is the shinyness value for glossy reflections. When it is 0.0,
standard raytraced mirror reflections are used, but for nonzero values
glossy reflections are generated, which increases render time.
- reflect_environment_only
- if true only the current environment map is sampled for reflections,
and no actual rays are traced.
- mode
- is the mode selector for the
light lists.
- lights
- array of lights directly linked to the shader.
Call Shader
This is a utility "pass through" shader for Phenomenon building. It allows
passing shaders as parameters to material Phenomena for items
such as environment, photons, and displacement.
misss_call_shader
color "misss_call_shader" (
shader "shader",
shader "default_shader",
integer "mode")
- shader
- is the shader to be called.
- default_shader
- is the shader that is called if shader
is not specified.
- mode
- is the shader calling mode, where 0 is "automatic".
Any other number maps to a shader calling mode miShader_type.
See the shader.h include file.
Here is an example in pseudo code of using this shader in a Phenomenon:
declare phenomenon
material "my_phenomenon" (
color "my_special_color",
scalar "my_size",
shader "optional_environment",
...
)
shader "default_environment" "...." (
.... some environment shader ...
)
shader "env" "misss_call_shader" (
# call the passed shader
"shader" = interface "optional_environment",
# if none was passed, call our default
"default_shader" "default_environment"
)
environment = "env"
end declare
The sample shader,
misss_lambert_gamma is optional. Any illumination shader
can be used.
Copyright © 1986, 2015
NVIDIA ARC GmbH. All rights reserved.