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.
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")
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.
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.)
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:
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.
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.
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:
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.
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:
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")
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.
color "misss_lambert_gamma" (
color "ambient",
color "ambience",
color "diffuse",
boolean "indirect",
scalar "diffuse_curve",
integer "flip",
integer "mode",
array light "lights")
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.
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")
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.
color "misss_call_shader" (
shader "shader",
shader "default_shader",
integer "mode")
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
[1] The sample shader,
misss_lambert_gamma is optional. Any illumination shader
can be used.
Copyright © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.