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",
    )
    apply material
    version 4
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.
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"
    )
    apply material
    version 4

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.

The misss_fast_shader works conceptually 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 plugin 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.

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 plugin 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:

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"
    )
    version 4
    apply lightmap
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"
    )
    version 4
    apply texture
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"
    )
    version 4
    apply material
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"
    )
    version 2
    apply material, texture, environment, photon, shadow, displace
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

[1] The sample shader, misss_lambert_gamma is optional. Any illumination shader can be used.

Copyright (©) 1986-2008 by mental images GmbH