* Add clear coat normal map support This change allows to set a separate normal map for the clear coat layer of a material. * Document the new clearCoatNormal property * Fix typo
1544 lines
64 KiB
HTML
1544 lines
64 KiB
HTML
<meta charset="utf-8">
|
|
|
|
<style>img { max-width: 100%; }</style>
|
|
|
|

|
|
|
|
# About
|
|
|
|
This document is part of the [Filament project](https://github.com/google/filament). To report errors in this document please use the [project's issue tracker](https://github.com/google/filament/issues).
|
|
|
|
## Authors
|
|
|
|
- [Romain Guy](https://github.com/romainguy), [@romainguy](https://twitter.com/romainguy)
|
|
|
|
# Overview
|
|
|
|
Filament is a physically based rendering (PBR) engine for Android. Filament offers a customizable
|
|
material system that you can use to create both simple and complex materials. This document
|
|
describes all the features available to materials and how to create your own material.
|
|
|
|
## Core concepts
|
|
|
|
Material
|
|
: A material defines the visual appearance of a surface. To completely describe and render a
|
|
surface, a material provides the following information:
|
|
- Material model
|
|
- Set of use-controllable named parameters
|
|
- Raster state (blending mode, backface culling, etc.)
|
|
- Vertex shader code
|
|
- Fragment shader code
|
|
|
|
Material model
|
|
: Also called _shading model_ or _lighting model_, the material model defines the intrinsic
|
|
properties of a surface. These properties have a direct influence on the way lighting is
|
|
computed and therefore on the appearance of a surface.
|
|
|
|
Material definition
|
|
: A text file that describes all the information required by a material. This is the file that you
|
|
will directly author to create new materials.
|
|
|
|
Material package
|
|
: At runtime, materials are loaded from _material packages_ compiled from material definitions
|
|
using the `matc` tool. A material package contains all the information required to describe a
|
|
material, and shaders generated for the target runtime platforms. This is necessary because
|
|
different platforms (Android, macOS, Linux, etc.) use different graphics APIs or different
|
|
variants of similar graphics APIs (OpenGL vs OpenGL ES for instance).
|
|
|
|
Material instance
|
|
: A material instance is a reference to a material and a set of values for the different values of
|
|
that material. Material instances are not covered in this document as they are created and
|
|
manipulated directly from code using Filament's APIs.
|
|
|
|
# Material models
|
|
|
|
Filament materials can use one of the following material models:
|
|
- Lit (or standard)
|
|
- Subsurface
|
|
- Cloth
|
|
- Unlit
|
|
|
|
## Lit model
|
|
|
|
The lit model is Filament's standard material model. This physically-based shading model was
|
|
designed after to offer good interoperability with other common tools and engines such as _Unity 5_,
|
|
_Unreal Engine 4_, _Substance Designer_ or _Marmoset Toolbag_.
|
|
|
|
This material model can be used to describe a large number of non-metallic surfaces (_dielectrics_)
|
|
or metallic surfaces (_conductors_).
|
|
|
|
The appearance of a material using the standard model is controlled using the properties described
|
|
in table [standardProperties].
|
|
|
|
|
|
Property | Definition
|
|
-----------------------:|:---------------------
|
|
**baseColor** | Diffuse albedo for non-metallic surfaces, and specular color for metallic surfaces
|
|
**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
|
|
**roughness** | Perceived smoothness (1.0) or roughness (0.0) of a surface. Smooth surfaces exhibit sharp reflections
|
|
**reflectance** | Fresnel reflectance at normal incidence for dielectric surfaces. This directly controls the strength of the reflections
|
|
**clearCoat** | Strength of the clear coat layer
|
|
**clearCoatRoughness** | Perceived smoothness or roughness of the clear coat layer
|
|
**anisotropy** | Amount of anisotropy in either the tangent or bitangent direction
|
|
**anisotropyDirection** | Local surface direction
|
|
**ambientOcclusion** | Defines how much of the ambient light is accessible to a surface point. It is a per-pixel shadowing factor between 0.0 and 1.0
|
|
**normal** | A detail normal used to perturb the surface using _bump mapping_ (_normal mapping_)
|
|
**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
|
|
**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
|
|
[Table [standardProperties]: Properties of the standard model]
|
|
|
|
The type and range of each property is described in table [standardPropertiesTypes].
|
|
|
|
Property | Type | Range | Note
|
|
-----------------------:|:--------:|:------------------------:|:-------------------------
|
|
**baseColor** | float4 | [0..1] | Pre-multiplied linear RGB
|
|
**metallic** | float | [0..1] | Should be 0 or 1
|
|
**roughness** | float | [0..1] |
|
|
**reflectance** | float | [0..1] | Prefer values > 0.35
|
|
**clearCoat** | float | [0..1] | Should be 0 or 1
|
|
**clearCoatRoughness** | float | [0..1] | Remaps to [0..0.6]
|
|
**anisotropy** | float | [-1..1] | Anisotropy is in the tangent direction when this value is positive
|
|
**anisotropyDirection** | float3 | [0..1] | Linear RGB, encodes a direction vector in tangent space
|
|
**ambientOcclusion** | float | [0..1] |
|
|
**normal** | float3 | [0..1] | Linear RGB, encodes a direction vector in tangent space
|
|
**clearCoatNormal** | float3 | [0..1] | Linear RGB, encodes a direction vector in tangent space
|
|
**emissive** | float4 | rgb=[0..1], a=[-n..n] | Alpha is the exposure compensation
|
|
[Table [standardPropertiesTypes]: Range and type of the standard model's properties]
|
|
|
|
|
|
!!! Note: About linear RGB
|
|
Several material model properties expect RGB colors. Filament materials use RGB colors in linear
|
|
space and you must take proper care of supplying colors in that space. See the Linear colors
|
|
section for more information.
|
|
|
|
!!! Note: About pre-multiplied RGB
|
|
Filament materials expect colors to use pre-multiplied alpha. See the Pre-multiplied alpha
|
|
section for more information.
|
|
|
|
### Base color
|
|
|
|
The `baseColor` property defines the perceived color of an object (sometimes called albedo). The
|
|
effect of `baseColor` depends on the nature of the surface, controlled by the `metallic` property
|
|
explained in the Metallic section.
|
|
|
|
Non-metals (dielectrics)
|
|
: Defines the diffuse color of the surface. Real-world values are typically found in the range
|
|
$[10..240]$ if the value is encoded between 0 and 255, or in the range $[0.04..0.94]$ between 0
|
|
and 1. Several examples of base colors for non-metallic surfaces can be found in
|
|
table [baseColorsDielectrics].
|
|
|
|
Metal | sRGB | Hexadecimal | Color
|
|
----------:|:-------------------:|:------------:|-------------------------------------------------------
|
|
Coal | 0.19, 0.19, 0.19 | #323232 | <div style="background-color: #323232; width: 60px"> </div>
|
|
Rubber | 0.21, 0.21, 0.21 | #353535 | <div style="background-color: #353535; width: 60px"> </div>
|
|
Mud | 0.33, 0.24, 0.19 | #553d31 | <div style="background-color: #875c3c; width: 60px"> </div>
|
|
Wood | 0.53, 0.36, 0.24 | #875c3c | <div style="background-color: #c4c6c6; width: 60px"> </div>
|
|
Vegetation | 0.48, 0.51, 0.31 | #7b824e | <div style="background-color: #7b824e; width: 60px"> </div>
|
|
Brick | 0.58, 0.49, 0.46 | #947d75 | <div style="background-color: #947d75; width: 60px"> </div>
|
|
Sand | 0.69, 0.66, 0.52 | #b1a884 | <div style="background-color: #b1a884; width: 60px"> </div>
|
|
Concrete | 0.75, 0.75, 0.73 | #c0bfbb | <div style="background-color: #c0bfbb; width: 60px"> </div>
|
|
[Table [baseColorsDielectrics]: `baseColor` for common non-metals]
|
|
|
|
Metals (conductors)
|
|
: Defines the specular color of the surface. Real-world values are typically found in the range
|
|
$[170..255]$ if the value is encoded between 0 and 255, or in the range $[0.66..1.0]$ between 0 and
|
|
1. Several examples of base colors for metallic surfaces can be found in table [baseColorsConductors].
|
|
|
|
Metal | sRGB | Hexadecimal | Color
|
|
----------:|:-------------------:|:------------:|-------------------------------------------------------
|
|
Silver | 0.97, 0.96, 0.91 | #f7f4e8 | <div style="background-color: #faf9f5; width: 60px"> </div>
|
|
Aluminum | 0.91, 0.92, 0.92 | #e8eaea | <div style="background-color: #f4f5f5; width: 60px"> </div>
|
|
Titanium | 0.76, 0.73, 0.69 | #c1baaf | <div style="background-color: #cec8c2; width: 60px"> </div>
|
|
Iron | 0.77, 0.78, 0.78 | #c4c6c6 | <div style="background-color: #c0bdba; width: 60px"> </div>
|
|
Platinum | 0.83, 0.81, 0.78 | #d3cec6 | <div style="background-color: #d6d1c8; width: 60px"> </div>
|
|
Gold | 1.00, 0.85, 0.57 | #ffd891 | <div style="background-color: #fedc9d; width: 60px"> </div>
|
|
Brass | 0.98, 0.90, 0.59 | #f9e596 | <div style="background-color: #f4e4ad; width: 60px"> </div>
|
|
Copper | 0.97, 0.74, 0.62 | #f7bc9e | <div style="background-color: #fbd8b8; width: 60px"> </div>
|
|
[Table [baseColorsConductors]: `baseColor` for common metals]
|
|
|
|
### Metallic
|
|
|
|
The `metallic` property defines whether the surface is a metallic (_conductor_) or a non-metallic
|
|
(_dielectric_) surface. This property should be used as a binary value, set to either 0 or 1.
|
|
Intermediate values are only truly useful to create transitions between different types of surfaces
|
|
when using textures.
|
|
|
|
This property can dramatically change the appearance of a surface. Non-metallic surfaces have
|
|
chromatic diffuse reflection and achromatic specular reflection (reflected light does not change
|
|
color). Metallic surfaces do not have any diffuse reflection and chromatic specular reflection
|
|
(reflected light takes on the color of the surfaced as defined by `baseColor`).
|
|
|
|
The effect of `metallic` is shown in figure [metallicProperty] (click on the image to see a
|
|
larger version).
|
|
|
|
![Figure [metallicProperty]: `metallic` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/metallic.png)
|
|
|
|
### Roughness
|
|
|
|
The `roughness` property controls the perceived smoothness of the surface. When `roughness` is set
|
|
to 0, the surface is perfectly smooth and highly glossy. The rougher a surface is, the "blurrier"
|
|
the reflections are. This property is often called _glossiness_ in other engines and tools, and is
|
|
simply the opposite of the roughness (`roughness = 1 - glossiness`).
|
|
|
|
### Non-metals
|
|
|
|
The effect of `roughness` on non-metallic surfaces is shown in figure [roughnessProperty] (click
|
|
on the image to see a larger version).
|
|
|
|
![Figure [roughnessProperty]: Dielectric `roughness` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/dielectric_roughness.png)
|
|
|
|
### Metals
|
|
|
|
The effect of `roughness` on metallic surfaces is shown in figure [roughnessConductorProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [roughnessConductorProperty]: Conductor `roughness` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/conductor_roughness.png)
|
|
|
|
### Reflectance
|
|
|
|
The `reflectance` property only affects non-metallic surfaces. This property can be used to control
|
|
the specular intensity. This value is defined between 0 and 1 and represents a remapping of a
|
|
percentage of reflectance. For instance, the default value of 0.5 corresponds to a reflectance of
|
|
4%. Values below 0.35 (2% reflectance) should be avoided as no real-world materials have such
|
|
low reflectance.
|
|
|
|
The effect of `reflectance` on non-metallic surfaces is shown in figure [reflectanceProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [reflectanceProperty]: `reflectance` varying from 0.0 (left)
|
|
to 1.0 (right)](images/materials/reflectance.png)
|
|
|
|
Figure [reflectance] shows common values and how they relate to the mapping function.
|
|
|
|
![Figure [reflectance]: Common reflectance values](images/diagram_reflectance.png)
|
|
|
|
Table [commonMatReflectance] describes acceptable reflectance values for various types of materials
|
|
(no real world material has a value under 2%).
|
|
|
|
|
|
Material | Reflectance | Property value
|
|
--------------------------:|:-----------------|:----------------
|
|
Water | 2% | 0.35
|
|
Fabric | 4% to 5.6% | 0.5 to 0.59
|
|
Common liquids | 2% to 4% | 0.35 to 0.5
|
|
Common gemstones | 5% to 16% | 0.56 to 1.0
|
|
Plastics, glass | 4% to 5% | 0.5 to 0.56
|
|
Other dielectric materials | 2% to 5% | 0.35 to 0.56
|
|
Eyes | 2.5% | 0.39
|
|
Skin | 2.8% | 0.42
|
|
Hair | 4.6% | 0.54
|
|
Teeth | 5.8% | 0.6
|
|
Default value | 4% | 0.5
|
|
[Table [commonMatReflectance]: Reflectance of common materials]
|
|
|
|
### Clear coat
|
|
|
|
Multi-layer materials are fairly common, particularly materials with a thin translucent
|
|
layer over a base layer. Real world examples of such materials include car paints, soda cans,
|
|
lacquered wood and acrylic.
|
|
|
|
The `clearCoat` property can be used to describe materials with two layers. The clear coat layer
|
|
will always be isotropic and dielectric.
|
|
|
|
![Figure [clearCoat]: Comparison of a carbon-fiber material under the standard material model
|
|
(left) and the clear coat model (right)](images/material_carbon_fiber.png)
|
|
|
|
The `clearCoat` property controls the strength of the clear coat layer. This should be treated as a
|
|
binary value, set to either 0 or 1. Intermediate values are useful to control transitions between
|
|
parts of the surface that have a clear coat layers and parts that don't.
|
|
|
|
The effect of `clearCoat` on a rough metal is shown in figure [clearCoatProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [clearCoatProperty]: `clearCoat` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/clear_coat.png)
|
|
|
|
!!! Warning
|
|
The clear coat layer effectively doubles the cost of specular computations. Do not assign a
|
|
value, even 0.0, to the clear coat property if you don't need this second layer.
|
|
|
|
### Clear coat roughness
|
|
|
|
The `clearCoatRoughness` property is similar to the `roughness` property but applies only to the
|
|
clear coat layer. In addition, since clear coat layers are never completely rough, the value between
|
|
0 and 1 is remapped internally to an actual roughness of 0 to 0.6.
|
|
|
|
The effect of `clearCoatRoughness` on a rough metal is shown in figure [clearCoatRoughnessProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [clearCoatRoughnessProperty]: `clearCoatRoughness` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/clear_coat_roughness.png)
|
|
|
|
### Anisotropy
|
|
|
|
Many real-world materials, such as brushed metal, can only be replicated using an anisotropic
|
|
reflectance model. A material can be changed from the default isotropic model to an anisotropic
|
|
model by using the `anisotropy` property.
|
|
|
|
![Figure [anisotropic]: Comparison of isotropic material
|
|
(left) and anistropic material (right)](images/material_anisotropic.png)
|
|
|
|
The effect of `anisotropy` on a rough metal is shown in figure [anisotropyProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [anisotropyProperty]: `anisotropy` varying from 0.0
|
|
(left) to 1.0 (right)](images/materials/anisotropy.png)
|
|
|
|
The figure [anisotropyDir] below shows how the direction of the anisotropic highlights can be
|
|
controlled by using either positive or negative values: positive values define anisotropy in the
|
|
tangent direction and negative values in the bitangent direction.
|
|
|
|
![Figure [anisotropyDir]: Positive (left) vs negative
|
|
(right) `anisotropy` values](images/screenshot_anisotropy_direction.png)
|
|
|
|
!!! Tip
|
|
The anisotropic material model is slightly more expensive than the standard material model. Do
|
|
not assign a value (even 0.0) to the `anisotropy` property if you don't need anisotropy.
|
|
|
|
### Anisotropy direction
|
|
|
|
The `anisotropyDirection` property defines the direction of the surface at a given point and thus
|
|
control the shape of the specular highlights. It is specified as vector of 3 values that usually
|
|
come from a texture, encoding the directions local to the surface.
|
|
|
|
The effect of `anisotropyDirection` on a metal is shown in figure [anisotropyDirectionProperty]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [anisotropyDirectionProperty]: Anisotropic metal rendered
|
|
with a direction map](images/screenshot_anisotropy.png)
|
|
|
|
The result shown in figure [anisotropyDirectionProperty] was obtained using the direction map shown
|
|
in figure [anisotropyDirectionProperty].
|
|
|
|
![Figure [anisotropyDirectionProperty]: Example of a direction map](images/screenshot_anisotropy_map.jpg)
|
|
|
|
### Ambient occlusion
|
|
|
|
The `ambientOcclusion` property defines how much of the ambient light is accessible to a surface
|
|
point. It is a per-pixel shadowing factor between 0.0 (fully shadowed) and 1.0 (fully lit). This
|
|
property only affects diffuse indirect lighting (image-based lighting), not direct lights such as
|
|
directional, point and spot lights, nor specular lighting.
|
|
|
|
![Figure [aoExample]: Comparison of materials without diffuse ambient occlusion
|
|
(left) and with (right)](images/screenshot_ao.jpg)
|
|
|
|
### Normal
|
|
|
|
The `normal` property defines the normal of the surface at a given point. It usually comes from a
|
|
_normal map_ texture, which allows to vary the property per-pixel. The normal is supplied in tangent
|
|
space, which means that +Z points outside of the surface.
|
|
|
|
For example, let's imagine that we want to render a piece of furniture covered in tufted leather.
|
|
Modeling the geometry to accurately represent the tufted pattern would require too many triangles
|
|
so we instead bake a high-poly mesh into a normal map. Once the base map is applied to a simplified
|
|
mesh, we get the result in figure [normalMapped].
|
|
|
|
Note that the `normal` property affects the _base layer_ and not the clear coat layer.
|
|
|
|
![Figure [normalMapped]: Low-poly mesh without normal mapping (left)
|
|
and with (right)](images/screenshot_normal_mapping.jpg)
|
|
|
|
!!! Warning
|
|
Using a normal map increases the runtime cost of the material model.
|
|
|
|
### Clear coat normal
|
|
|
|
The `clearCoatNormal` property defines the normal of the clear coat layer at a given point. It
|
|
behaves otherwise like the `normal` property.
|
|
|
|
![Figure [clearCoatNormalMapped]: A material with a clear coat normal
|
|
map and a surface normal map](images/screenshot_clear_coat_normal.jpg)
|
|
|
|
!!! Warning
|
|
Using a clear coat normal map increases the runtime cost of the material model.
|
|
|
|
### Emissive
|
|
|
|
The `emissive` property can be used to simulate additional light emitted by the surface. It is
|
|
defined as a `float4` value that contains an RGB color (in linear space) as well as an exposure
|
|
compensation value (in the alpha channel).
|
|
|
|
Even though an exposure value actually indicates combinations of camera settings, it is often used
|
|
by photographers to describe light intensity. This is why cameras let photographers apply an
|
|
exposure compensation to over or under-expose an image. This setting can be used for artistic
|
|
control but also to achieve proper exposure (snow for instance will be exposed for as
|
|
18% middle-grey).
|
|
|
|
The exposure compensation value of the emissive property can be used to force the emissive color
|
|
to be brighter (positive values) or darker (negative values) than the current exposure. If the bloom
|
|
effect is enabled, using a positive exposure compensation can force the surface to bloom.
|
|
|
|
## Subsurface model
|
|
|
|
### Thickness
|
|
|
|
### Subsurface color
|
|
|
|
### Subsurface power
|
|
|
|
## Cloth model
|
|
|
|
All the material models described previously are designed to simulate dense surfaces, both at a
|
|
macro and at a micro level. Clothes and fabrics are however often made of loosely connected threads
|
|
that absorb and scatter incident light. When compared to hard surfaces, cloth is characterized by
|
|
a softer specular lob with a large falloff and the presence of fuzz lighting, caused by
|
|
forward/backward scattering. Some fabrics also exhibit two-tone specular colors
|
|
(velvets for instance).
|
|
|
|
Figure [materialCloth] shows how the standard material model fails to capture the appearance of a
|
|
sample of denim fabric. The surface appears rigid (almost plastic-like), more similar to a tarp
|
|
than a piece of clothing. This figure also shows how important the softer specular lobe caused by
|
|
absorption and scattering is to the faithful recreation of the fabric.
|
|
|
|
![Figure [materialCloth]: Comparison of denim fabric rendered using the standard model
|
|
(left) and the cloth model (right)](images/screenshot_cloth.png)
|
|
|
|
Velvet is an interesting use case for a cloth material model. As shown in figure [materialVelvet]
|
|
this type of fabric exhibits strong rim lighting due to forward and backward scattering. These
|
|
scattering events are caused by fibers standing straight at the surface of the fabric. When the
|
|
incident light comes from the direction opposite to the view direction, the fibers will forward
|
|
scatter the light. Similarly, when the incident light from from the same direction as the view
|
|
direction, the fibers will scatter the light backward.
|
|
|
|
![Figure [materialVelvet]: Velvet fabric showcasing forward and
|
|
backward scattering](images/screenshot_cloth_velvet.png)
|
|
|
|
It is important to note that there are types of fabrics that are still best modeled by hard surface
|
|
material models. For instance, leather, silk and satin can be recreated using the standard or
|
|
anisotropic material models.
|
|
|
|
The cloth material model encompasses all the parameters previously defined for the standard
|
|
material mode except for _metallic_ and _reflectance_. Two extra parameters described in
|
|
table [clothProperties] are also available.
|
|
|
|
|
|
Parameter | Definition
|
|
---------------------:|:---------------------
|
|
**sheenColor** | Specular tint to create two-tone specular fabrics (defaults to $\sqrt{baseColor}$)
|
|
**subsurfaceColor** | Tint for the diffuse color after scattering and absorption through the material
|
|
[Table [clothProperties]: Cloth model parameters]
|
|
|
|
The type and range of each property is described in table [clothPropertiesTypes].
|
|
|
|
Property | Type | Range | Note
|
|
---------------------:|:--------:|:------------------------:|:-------------------------
|
|
**sheenColor** | float3 | [0..1] | Linear RGB
|
|
**subsurfaceColor** | float3 | [0..1] | Linear RGB
|
|
[Table [clothPropertiesTypes]: Range and type of the cloth model's properties]
|
|
|
|
To create a velvet-like material, the base color can be set to black (or a dark color).
|
|
Chromaticity information should instead be set on the sheen color. To create more common fabrics
|
|
such as denim, cotton, etc. use the base color for chromaticity and use the default sheen color
|
|
or set the sheen color to the luminance of the base color.
|
|
|
|
!!! Warning
|
|
The cloth material model is more expensive than the standard material model.
|
|
|
|
!!! Tip
|
|
To see the effect of the `roughness` parameter make sure the `sheenColor` is brighter than
|
|
`baseColor`. This can be used to create a fuzz effect. Taking the luminance of `baseColor`
|
|
as the `sheenColor` will produce a fairly natural effect that works for common cloth. A dark
|
|
`baseColor` combined with a bright/saturated `sheenColor` can be used to create velvet.
|
|
|
|
!!! Tip
|
|
The `subsurfaceColor` parameter should be used with care. High values can interfere with shadows
|
|
in some areas. It is best suited for subtle transmission effects through the material.
|
|
|
|
### Sheen color
|
|
|
|
The `sheenColor` property can be used to directly modify the specular reflectance. It offers
|
|
better control over the appearance of cloth and gives give the ability to create
|
|
two-tone specular materials.
|
|
|
|
The effect of `sheenColor` is shown in figure [materialClothSheen]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [materialClothSheen]: Blue fabric without (left) and with (right) sheen](images/screenshot_cloth_sheen.png)
|
|
|
|
### Subsurface color
|
|
|
|
The `subsurfaceColor` property is not physically-based and can be used to simulate the scattering,
|
|
partial absorption and re-emission of light in certain types of fabrics. This is particularly
|
|
useful to create softer fabrics.
|
|
|
|
!!! Warning
|
|
The cloth material model is more expensive to compute when the `subsurfaceColor` property is used.
|
|
|
|
The effect of `subsurfaceColor` is shown in figure [materialClothSubsurface]
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [materialClothSubsurface]: White cloth (left column) vs white cloth with
|
|
brown subsurface scatting (right)](images/screenshot_cloth_subsurface.png)
|
|
|
|
## Unlit model
|
|
|
|
The unlit material model can be used to turn off all lighting computations. Its primary purpose is
|
|
to render pre-lit elements such as a cubemap, external content (such as a video or camera stream),
|
|
user interfaces, visualization/debugging etc. The unlit model exposes only two properties described
|
|
in table [unlitProperties].
|
|
|
|
Property | Definition
|
|
---------------------:|:---------------------
|
|
**baseColor** | Surface diffuse color
|
|
**emissive** | Additional diffuse color to simulate emissive surfaces. This property is mostly useful in an HDR pipeline with a bloom pass
|
|
[Table [unlitProperties]: Properties of the standard model]
|
|
|
|
The type and range of each property is described in table [unlitPropertiesTypes].
|
|
|
|
Property | Type | Range | Note
|
|
---------------------:|:--------:|:------------------------:|:-------------------------
|
|
**baseColor** | float4 | [0..1] | Pre-multiplied linear RGB
|
|
**emissive** | float4 | rgb=[0..1], a=N/A | Pre-multiplied linear RGB, alpha is ignored
|
|
[Table [unlitPropertiesTypes]: Range and type of the unlit model's properties]
|
|
|
|
The value of `emissive` is simply added to `baseColor` when present. The main use of `emissive`
|
|
is to force an unlit surface to bloom if the HDR pipeline is configured with a bloom pass.
|
|
|
|
Figure [materialUnlit] shows an example of the unlit material model
|
|
(click on the image to see a larger version).
|
|
|
|
![Figure [materialUnlit]: The unlit model is used to render debug information](images/screenshot_unlit.jpg)
|
|
|
|
# Material definitions
|
|
|
|
A material definition is a text file that describes all the information required by a material:
|
|
|
|
- Name
|
|
- User parameters
|
|
- Material model
|
|
- Required attributes
|
|
- Interpolants (called _variables_)
|
|
- Raster state (blending mode, etc.)
|
|
- Shader code (fragment shader, optionally vertex shader)
|
|
|
|
## Format
|
|
|
|
The material definition format is a format loosely based on [JSON](https://www.json.org/) that we
|
|
call _JSONish_. At the top level a material definition is composed of 3 different blocks that use
|
|
the JSON object notation:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
// material properties
|
|
}
|
|
|
|
vertex {
|
|
// vertex shader, optional
|
|
}
|
|
|
|
fragment {
|
|
// fragment shader
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
A minimum viable material definition must contain a `material` section and a `fragment` block. The
|
|
`vertex` block is optional.
|
|
|
|
### Differences with JSON
|
|
|
|
In JSON, an object is made of key/value _pairs_. A JSON pair has the following syntax:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
"key" : value
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Where value can be a string, number, object, array or a literal (`true`, `false` or `null`). While
|
|
this syntax is perfectly valid in a material definition, a variant without quotes around strings is
|
|
also accepted in JSONish:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
key : value
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Quotes remain mandatory when the string contains spaces.
|
|
|
|
The `vertex` and `fragment` blocks contain unescaped, unquoted GLSL code, which is not valid in JSON.
|
|
|
|
Single-line C++-style comments are allowed.
|
|
|
|
The key of a pair is case-sensitive.
|
|
|
|
The value of a pair is not case-sensitive.
|
|
|
|
### Example
|
|
|
|
The following code listing shows an example of a valid material definition. This definition uses
|
|
the _lit_ material model (see Lit model section), uses the default opaque blending mode, requires
|
|
that a set of UV coordinates be presented in the rendered mesh and defines 3 user parameters. The
|
|
following sections of this document describe the `material` and `fragment` blocks in detail.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
name : "Textured material",
|
|
parameters : [
|
|
{
|
|
type : sampler2d,
|
|
name : texture
|
|
},
|
|
{
|
|
type : float,
|
|
name : metallic
|
|
},
|
|
{
|
|
type : float,
|
|
name : roughness
|
|
}
|
|
],
|
|
requires : [
|
|
uv0
|
|
],
|
|
shadingModel : lit,
|
|
blending : opaque
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor = texture(materialParams_texture, getUV0());
|
|
material.metallic = materialParams.metallic;
|
|
material.roughness = materialParams.roughness;
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
## Material block
|
|
|
|
The material block is mandatory block that contains a list of property pairs to describe all
|
|
non-shader data.
|
|
|
|
### name
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any string. Double quotes are required if the name contains spaces.
|
|
|
|
Description
|
|
: Sets the name of the material. The name is retained at runtime for debugging purpose.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
name : stone
|
|
}
|
|
|
|
material {
|
|
name : "Wet pavement"
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### shadingModel
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `lit`, `subsurface`, `cloth`, `unlit`. Defaults to `lit`.
|
|
|
|
Description
|
|
: Selects the material model as described in the Material models section.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
shadingModel : unlit
|
|
}
|
|
|
|
material {
|
|
shadingModel : "subsurface"
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### parameters
|
|
|
|
Type
|
|
: array of parameter objects
|
|
|
|
Value
|
|
: Each entry is an object with the properties `name` and `type`, both of `string` type. The
|
|
name must be a valid GLSL identifier. The type must be one of the types described in
|
|
table [materialParamsTypes].
|
|
|
|
Type | Description
|
|
:----------------------|:---------------------------------
|
|
bool | Single boolean
|
|
bool2 | Vector of 2 booleans
|
|
bool3 | Vector of 3 booleans
|
|
bool4 | Vector of 4 booleans
|
|
float | Single float
|
|
float2 | Vector of 2 floats
|
|
float3 | Vector of 3 floats
|
|
float4 | Vector of 4 floats
|
|
int | Single integer
|
|
int2 | Vector of 2 integers
|
|
int3 | Vector of 3 integers
|
|
int4 | Vector of 4 integers
|
|
uint | Single unsigned integer
|
|
uint2 | Vector of 2 unsigned integers
|
|
uint3 | Vector of 3 unsigned integers
|
|
uint4 | Vector of 4 unsigned integers
|
|
float3x3 | Matrix of 3x3 floats
|
|
float4x4 | Matrix of 4x4 floats
|
|
sampler2d | 2D texture
|
|
samplerExternal | External texture (platform-specific)
|
|
samplerCubemap | Cubemap texture
|
|
[Table [materialParamsTypes]: Material parameter types]
|
|
|
|
Samplers
|
|
: Sampler types can also specify a `format` (defaults to `float`) and a `precision` (defaults
|
|
to `default`). The format can be one of `int`, `float`. The precision can be one of `default`
|
|
(best precision for the platform, typically `high` on desktop, `medium` on mobile),
|
|
`low`, `medium`, `high`.
|
|
|
|
Arrays
|
|
: A parameter can define an array of values by appending `[size]` after the type name, where
|
|
`size` is a positive integer. For instance: `float[9]` declares an array of nine `float`
|
|
values. Arrays of samplers are _not_ supported at the moment.
|
|
|
|
Description
|
|
: Lists the parameters required by your material. These parameters can be set at runtime using
|
|
Filament's material API. Accessing parameters from the shaders varies depending on the type of
|
|
parameter:
|
|
|
|
- **Samplers types**: use the parameter name prefixed with `materialParams_`. For instance,
|
|
`materialParams_myTexture`.
|
|
- **Other types**: use the parameter name as the field of a structure called `materialParams`.
|
|
For instance, `materialParams.myColor`.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
parameters : [
|
|
{
|
|
type : float4,
|
|
name : albedo
|
|
},
|
|
{
|
|
type : sampler2d,
|
|
format : float,
|
|
precision : high,
|
|
name : roughness
|
|
},
|
|
{
|
|
type : float2,
|
|
name : metallicReflectance
|
|
}
|
|
],
|
|
requires : [
|
|
uv0
|
|
],
|
|
shadingModel : lit,
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor = materialParams.albedo;
|
|
material.roughness = texture(materialParams_roughness, getUV0());
|
|
material.metallic = materialParams.metallicReflectance.x;
|
|
material.reflectance = materialParams.metallicReflectance.y;
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
### requires
|
|
|
|
Type
|
|
: array of `string`
|
|
|
|
Value
|
|
: Each entry must be any of `uv0`, `uv1`, `color`, `position`, `tangents`.
|
|
|
|
Description
|
|
: Lists the vertex attributes required by the material. The `position` attribute is always
|
|
required and does not need to be specified. The `tangents` attribute is automatically required
|
|
when selecting any shading model that is not `unlit`. See the shader sections of this document
|
|
for more information on how to access these attributes from the shaders.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
parameters : [
|
|
{
|
|
type : sampler2d,
|
|
name : texture
|
|
},
|
|
],
|
|
requires : [
|
|
uv0
|
|
],
|
|
shadingModel : lit,
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor = texture(materialParams_texture, getUV0());
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### variables
|
|
|
|
Type
|
|
: array of `string`
|
|
|
|
Value
|
|
: Up to 4 strings, each must be a valid GLSL identifier.
|
|
|
|
Description
|
|
: Defines custom interpolants (or variables) that are output by the material's vertex shader.
|
|
Each entry of the array defines the name of an interpolant. The full name in the fragment
|
|
shader is the name of the interpolant with the `variable_` prefix. For instance, if you
|
|
declare a variable called `eyeDirection` you can access it in the fragment shader using
|
|
`variable_eyeDirection`. In the vertex shader, the interpolant name is simply a member of
|
|
the `MaterialVertexInputs` structure (`material.eyeDirection` in your example). Each
|
|
interpolant is of type `float4` (`vec4`) in the shaders.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
name : Skybox,
|
|
parameters : [
|
|
{
|
|
type : samplerCubemap,
|
|
name : skybox
|
|
}
|
|
],
|
|
variables : [
|
|
eyeDirection
|
|
],
|
|
vertexDomain : device,
|
|
depthWrite : false,
|
|
shadingModel : unlit
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
float3 sky = texture(materialParams_skybox, variable_eyeDirection.xyz).rgb;
|
|
material.baseColor = vec4(sky, 1.0);
|
|
}
|
|
}
|
|
|
|
vertex {
|
|
void materialVertex(inout MaterialVertexInputs material) {
|
|
float3 p = getPosition().xyz;
|
|
float3 u = mulMat4x4Float3(getViewFromClipMatrix(), p).xyz;
|
|
material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### blending
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `opaque`, `transparent`, `fade`, `add`, `masked`. Defaults to `opaque`.
|
|
|
|
Description
|
|
: Defines how/if the rendered object is blended with the content of the render target.
|
|
The possible blending modes are:
|
|
|
|
- **Opaque**: blending is disabled, the alpha channel of the material's output is ignored.
|
|
- **Transparent**: blending is enabled. The material's output is alpha composited with the
|
|
render target, using Porter-Duff's `source over` rule. This blending mode assumes
|
|
pre-multiplied alpha.
|
|
- **Fade**: acts as `transparent` but transparency is also applied to specular lighting. In
|
|
`transparent` mode, the material's alpha values only applies to diffuse lighting. This
|
|
blending mode is useful to fade lit objects in and out.
|
|
- **Add**: blending is enabled. The material's output is added to the content of the
|
|
render target.
|
|
- **Masked**: blending is disabled. This blending mode enables alpha masking. The alpha channel
|
|
of the material's output defines whether a fragment is discarded or not. See the maskThreshold
|
|
section for more information.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
blending : transparent
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### vertexDomain
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `object`, `world`, `view`, `device`. Defaults to `object`.
|
|
|
|
Description
|
|
: Defines the domain (or coordinate space) of the rendered mesh. The domain influences how the
|
|
vertices are transformed in the vertex shader. The possible domains are:
|
|
|
|
- **Object**: the vertices are defined in the object (or model) coordinate space. The
|
|
vertices are transformed using the rendered object's transform matrix
|
|
- **World**: the vertices are defined in world coordinate space. The vertices are not
|
|
transformed using the rendered object's transform.
|
|
- **View**: the vertices are defined in view (or eye or camera) coordinate space. The
|
|
vertices are not transformed using the rendered object's transform.
|
|
- **Device**: the vertices are defined in normalized device (or clip) coordinate space.
|
|
The vertices are not transformed using the rendered object's transform.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
vertexDomain : device
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### interpolation
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `smooth`, `flat`. Defaults to `smooth`.
|
|
|
|
Description
|
|
: Defines how interpolants (or variables) are interpolated between vertices. When this property
|
|
is set to `smooth`, a perspective correct interpolation is performed on each interpolant.
|
|
When set to `flat`, no interpolation is performed and all the fragments within a given
|
|
triangle will be shaded the same.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
interpolation : flat
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### culling
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `none`, `front`, `back`, `frontAndBack`. Defaults to `back`.
|
|
|
|
Description
|
|
: Defines which triangles should be culled: none, front-facing triangles, back-facing
|
|
triangles or all.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
culling : none
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### colorWrite
|
|
|
|
Type
|
|
: `boolean`
|
|
|
|
Value
|
|
: `true` or `false`. Defaults to `true`.
|
|
|
|
Description
|
|
: Enables or disables writes to the color buffer.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
colorWrite : false
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### depthWrite
|
|
|
|
Type
|
|
: `boolean`
|
|
|
|
Value
|
|
: `true` or `false`. Defaults to `true`.
|
|
|
|
Description
|
|
: Enables or disables writes to the depth buffer.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
depthWrite : false
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### depthCulling
|
|
|
|
Type
|
|
: `boolean`
|
|
|
|
Value
|
|
: `true` or `false`. Defaults to `true`.
|
|
|
|
Description
|
|
: Enables or disables depth testing. When depth testing is disabled, an object rendered with
|
|
this material will always appear on top of other opaque objects.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
depthCulling : false
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### doubleSided
|
|
|
|
Type
|
|
: `boolean`
|
|
|
|
Value
|
|
: `true` or `false`. Defaults to `false`.
|
|
|
|
Description
|
|
: Enables or disables two-sided rendering. When set to `true`, `culling` is automatically set to
|
|
`none`; if the triangle is back-facing, the triangle's normal is automatically flipped to
|
|
become front-facing.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
doubleSided : true
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### transparency
|
|
|
|
Type
|
|
: `string`
|
|
|
|
Value
|
|
: Any of `default`, `twoPassesOneSide` or `twoPassesTwoSides`. Defaults to `default`.
|
|
|
|
Description
|
|
: Controls how transparent objects are rendered. It is only valid when the `blending` mode is
|
|
not `opaque`. None of these methods can accurately render concave geometry, but in practice
|
|
they are often good enough.
|
|
|
|
The three possible transparency modes are:
|
|
- `default`: the transparent object is rendered normally (as seen in figure [transparencyDefault]),
|
|
honoring the `culling` mode, etc.
|
|
- `twoPassesOneSide`: the transparent object is first rendered in the depth buffer, then again in
|
|
the color buffer, honoring the `cullling` mode. This effectively renders only half of the
|
|
transparent object as shown in figure [transparencyTwoPassesOneSide].
|
|
- `twoPassesTwoSides`: the transparent object is rendered twice in the color buffer: first with its
|
|
back faces, then with its front faces. This mode lets you render both set of faces while reducing
|
|
or eliminating sorting issues, as shown in figure [transparencyTwoPassesTwoSides].
|
|
`twoPassesTwoSides` can be combined with `doubleSided` for better effect.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
transparency : twoPassesOneSide
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
![Figure [transparencyDefault]: This double sided model shows the type of sorting issues transparent
|
|
objects can be subject to in `default` mode](images/screenshot_transparency_default.png)
|
|
|
|
![Figure [transparencyTwoPassesOneSide]: In `twoPassesOneSide` mode, only one set of faces is visible
|
|
and correctly sorted](images/screenshot_twopasses_oneside.png)
|
|
|
|
![Figure [transparencyTwoPassesTwoSides]: In `twoPassesTwoSides` mode, both set of faces are visible
|
|
and sorting issues are minimized or eliminated](images/screenshot_twopasses_twosides.png)
|
|
|
|
### maskThreshold
|
|
|
|
Type
|
|
: `number`
|
|
|
|
Value
|
|
: A value between `0.0` and `1.0`. Defaults to `0.4`.
|
|
|
|
Description
|
|
: Sets the minimum alpha value a fragment must have to not be discarded when the `blending` mode
|
|
is set to `masked`. When the blending mode is not `masked`, this value is ignored. This value
|
|
can be used to controlled the appearance of alpha-masked objects.
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
blending : masked,
|
|
maskThreshold : 0.5
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### shadowMultiplier
|
|
|
|
Type
|
|
: `boolean`
|
|
|
|
Value
|
|
: `true` or `false`. Defaults to `false`.
|
|
|
|
Description
|
|
: Only available in the `unlit` shading model. If this property is enabled, the final color
|
|
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
|
|
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
name : "Invisible shadow plane",
|
|
shadingModel : unlit,
|
|
shadowMultiplier : true,
|
|
blending : transparent
|
|
}
|
|
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
// baseColor defines the color and opacity of the final shadow
|
|
material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### variantFilter
|
|
|
|
Type
|
|
: array of `string`
|
|
|
|
Value
|
|
: Each entry must be any of `dynamicLighting`, `directionalLighting`, `shadowReceiver` or `skinning`.
|
|
|
|
Description
|
|
: Used to specify a list of shader variants that the application guarantees will never be
|
|
needed. These shader variants are skipped during the code generation phase, thus reducing
|
|
the overall size of the material.
|
|
Note that some variants may automatically be filtered out. For instance, all lighting related
|
|
variants (`directionalLighting`, etc.) are filtered out when compiling an `unlit` material.
|
|
Use the variant filter with caution, filtering out a variant required at runtime may lead
|
|
to crashes.
|
|
|
|
Description of the variants:
|
|
- `directionalLighting`, used when a directional light is present in the scene
|
|
- `dynamicLighting`, used when a non-directional light (point, spot, etc.) is present in the scene
|
|
- `shadowReceiver`, used when an object can receive shadows
|
|
- `skinning`, used when an object is animated using GPU skinning
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
|
material {
|
|
name : "Invisible shadow plane",
|
|
shadingModel : unlit,
|
|
shadowMultiplier : true,
|
|
blending : transparent,
|
|
variantFilter : [ skinning ]
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
## Vertex block
|
|
|
|
The vertex block is optional and can be used to control the vertex shading stage of the material.
|
|
The vertex block must contain valid
|
|
[ESSL 3.0](https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf) code
|
|
(the version of GLSL supported in OpenGL ES 3.0). You are free to create multiple functions inside
|
|
the vertex block but you **must** declare the `materialVertex` function:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
vertex {
|
|
void materialVertex(inout MaterialVertexInputs material) {
|
|
// vertex shading code
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
This function will be invoked automatically at runtime by the shading system and gives you the
|
|
ability to read and modify material properties using the `MaterialVertexInputs` structure. This full
|
|
definition of the structure can be found in the Material vertex inputs section.
|
|
|
|
You can use this structure to compute your custom variables/interpolants or to modify the value of
|
|
the attributes. For instance, the following vertex blocks modifies both the color and the UV
|
|
coordinates of the vertex over time:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
material {
|
|
requires : [uv0, color]
|
|
}
|
|
vertex {
|
|
void materialVertex(inout MaterialVertexInputs material) {
|
|
material.color *= sin(getTime());
|
|
material.uv0 *= sin(getTime());
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In addition to the `MaterialVertexInputs` structure, your vertex shading code can use all the public
|
|
APIs listed in the Shader public APIs section.
|
|
|
|
### Material vertex inputs
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
struct MaterialVertexInputs {
|
|
float4 color; // if the color attribute is required
|
|
float2 uv0; // if the uv0 attribute is required
|
|
float2 uv1; // if the uv1 attribute is required
|
|
float3 worldNormal; // only if the shading model is not unlit
|
|
float4 worldPosition; // always available
|
|
// variable* names are replaced with actual names
|
|
float4 variable0; // if 1 or more variables is defined
|
|
float4 variable1; // if 2 or more variables is defined
|
|
float4 variable2; // if 3 or more variables is defined
|
|
float4 variable3; // if 4 or more variables is defined
|
|
};
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
## Fragment block
|
|
|
|
The fragment block must be used to control the fragment shading stage of the material. The vertex
|
|
block must contain valid
|
|
[ESSL 3.0](https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf)
|
|
code (the version of GLSL supported in OpenGL ES 3.0). You are free to create multiple functions
|
|
inside the vertex block but you **must** declare the `material` function:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
// fragment shading code
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
This function will be invoked automatically at runtime by the shading system and gives you the
|
|
ability to read and modify material properties using the `MaterialInputs` structure. This full
|
|
definition of the structure can be found in the Material fragment inputs section. The full
|
|
definition of the various members of the structure can be found in the Material models section
|
|
of this document.
|
|
|
|
The goal of the `material()` function is to compute the material properties specific to the selected
|
|
shading model. For instance, here is a fragment block that creates a glossy red metal using the
|
|
standard lit shading model:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
prepareMaterial(material);
|
|
material.baseColor.rgb = vec3(1.0, 0.0, 0.0);
|
|
material.metallic = 1.0;
|
|
material.roughness = 0.0;
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### prepareMaterial function
|
|
|
|
Note that you **must** call `prepareMaterial(material)` before exiting the `material()` function.
|
|
This `prepareMaterial` function sets up the internal state of the material mdoel. Some of the APIs
|
|
described in the Fragment APIs section - like `shading_normal` for instance - can only be accessed
|
|
_after_ invoking `prepareMaterial()`.
|
|
|
|
It is also important to remember that the `normal` property - as described in the Material fragment
|
|
inputs section - only has an effect when modified _before_ calling `prepareMaterial()`. Here is an
|
|
example of a fragment shader that properly modifies the `normal` property to implement a glossy red
|
|
plastic with bump mapping:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
fragment {
|
|
void material(inout MaterialInputs material) {
|
|
// fetch the normal in tangent space
|
|
vec3 normal = texture(materialParams_normalMap, getUV0()).xyz;
|
|
material.normal = normal * 2.0 - 1.0;
|
|
|
|
// prepare the material
|
|
prepareMaterial(material);
|
|
|
|
// from now on, shading_normal, etc. can be accessed
|
|
material.baseColor.rgb = vec3(1.0, 0.0, 0.0);
|
|
material.metallic = 0.0;
|
|
material.roughness = 1.0;
|
|
}
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
### Material fragment inputs
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
struct MaterialInputs {
|
|
float4 baseColor; // default: float4(1.0)
|
|
float4 emissive; // default: float4(0.0)
|
|
|
|
// no other field is available with the unlit shading model
|
|
float roughness; // default: 1.0
|
|
float metallic; // default: 0.0, not available with cloth
|
|
float reflectance; // default: 0.5, not available with cloth
|
|
float ambientOcclusion; // default: 0.0
|
|
|
|
// not available when the shading model is subsurface or cloth
|
|
float clearCoat; // default: 1.0
|
|
float clearCoatRoughness; // default: 0.0
|
|
float3 clearCoatNormal; // default: float3(0.0, 0.0, 1.0)
|
|
float anisotropy; // default: 0.0
|
|
float3 anisotropyDirection; // default: float3(1.0, 0.0, 0.0)
|
|
|
|
// only available when the shading model is subsurface
|
|
float thickness; // default: 0.5
|
|
float subsurfacePower; // default: 12.234
|
|
float3 subsurfaceColor; // default: float3(1.0)
|
|
|
|
// only available when the shading model is cloth
|
|
float3 sheenColor; // default: sqrt(baseColor)
|
|
float3 subsurfaceColor; // default: float3(0.0)
|
|
|
|
// not available when the shading model is unlit
|
|
// must be set before calling prepareMaterial()
|
|
float3 normal; // default: float3(0.0, 0.0, 1.0)
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
## Shader public APIs
|
|
|
|
### Types
|
|
|
|
While GLSL types can be used directly (`vec4` or `mat4`) we recommend the use of the following
|
|
type aliases:
|
|
|
|
Name | GLSL type | Description
|
|
:--------------------------------|:------------:|:------------------------------------
|
|
**bool2** | bvec2 | A vector of 2 booleans
|
|
**bool3** | bvec3 | A vector of 3 booleans
|
|
**bool4** | bvec4 | A vector of 4 booleans
|
|
**int2** | ivec2 | A vector of 2 integers
|
|
**int3** | ivec3 | A vector of 3 integers
|
|
**int4** | ivec4 | A vector of 4 integers
|
|
**uint2** | uvec2 | A vector of 2 unsigned integers
|
|
**uint3** | uvec3 | A vector of 3 unsigned integers
|
|
**uint4** | uvec4 | A vector of 4 unsigned integers
|
|
**float2** | float2 | A vector of 2 floats
|
|
**float3** | float3 | A vector of 3 floats
|
|
**float4** | float4 | A vector of 4 floats
|
|
**float4x4** | mat4 | A 4x4 float matrix
|
|
**float3x3** | mat3 | A 3x3 float matrix
|
|
|
|
### Math
|
|
Name | Type | Description
|
|
:-----------------------------------------|:--------:|:------------------------------------
|
|
**PI** | float | A constant that represent $\pi$
|
|
**HALF_PI** | float | A constant that represent $\frac{\pi}{2}$
|
|
**saturate(float x)** | float | Clamps the specified value between 0.0 and 1.0
|
|
**pow5(float x)** | float | Computes $x^5$
|
|
**sq(float x)** | float | Computes $x^2$
|
|
**max3(float3 v)** | float | Returns the maximum value of the specified `float3`
|
|
**mulMat4x4Float3(float4x4 m, float3 v)** | float4 | Returns $m * v$
|
|
**mulMat3x3Float3(float4x4 m, float3 v)** | float4 | Returns $m * v$
|
|
|
|
### Matrices
|
|
|
|
Name | Type | Description
|
|
:-----------------------------------|:--------:|:------------------------------------
|
|
**getViewFromWorldMatrix()** | float4x4 | Matrix that converts from world space to view/eye space
|
|
**getWorldFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to world space
|
|
**getClipFromViewMatrix()** | float4x4 | Matrix that converts from view/eye space to clip (NDC) space
|
|
**getViewFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to view/eye space
|
|
**getClipFromWorldMatrix()** | float4x4 | Matrix that converts from world to clip (NDC) space
|
|
**getWorldFromClipMatrix()** | float4x4 | Matrix that converts from clip (NDC) space to world space
|
|
|
|
### Frame constants
|
|
|
|
Name | Type | Description
|
|
:-----------------------------------|:--------:|:------------------------------------
|
|
**getResolution()** | float4 | Resolution of the view in pixels: `width`, `height`, `1 / width`, `1 / height`
|
|
**getWorldCameraPosition()** | float3 | Position of the camera/eye in world space
|
|
**getTime()** | float | Current time in seconds, may be reset regularly to avoid precision loss
|
|
**getExposure()** | float | Photometric exposure of the camera
|
|
**getEV100()** | float | [Exposure value at ISO 100](https://en.wikipedia.org/wiki/Exposure_value) of the camera
|
|
|
|
### Vertex only
|
|
|
|
The following APIs are only available from the vertex block:
|
|
|
|
Name | Type | Description
|
|
:-----------------------------------|:--------:|:------------------------------------
|
|
**getPosition()** | float4 | Vertex position in the domain defined by the material (default: object/model space)
|
|
**getWorldFromModelMatrix()** | float4x4 | Matrix that converts from model (object) space to world space
|
|
**getWorldFromModelNormalMatrix()** | float3x3 | Matrix that converts normals from model (object) space to world space
|
|
|
|
### Fragment only
|
|
|
|
The following APIs are only available from the fragment block:
|
|
|
|
Name | Type | Description
|
|
:--------------------------------|:--------:|:------------------------------------
|
|
**getWorldTangentFrame()** | float3x3 | Matrix containing in each column the `tangent` (`frame[0]`), `bi-tangent` (`frame[1]`) and `normal` (`frame[2]`) of the vertex in world space. If the material does not compute a tangent space normal for bump mapping or if the shading is not anisotropic, only the `normal` is valid in this matrix.
|
|
**getWorldPosition()** | float3 | Position of the fragment in world space
|
|
**getWorldViewVector()** | float3 | Normalized vector in world space from the fragment position to the eye
|
|
**getWorldNormalVector()** | float3 | Normalized normal in world space, after bump mapping (must be used after `prepareMaterial()`)
|
|
**getWorldReflectedVector()** | float3 | Reflection of the view vector about the normal (must be used after `prepareMaterial()`)
|
|
**getNdotV()** | float | The result of `dot(normal, view)`, always strictly greater than 0 (must be used after `prepareMaterial()`)
|
|
**getColor()** | float4 | Interpolated color of the fragment, if the color attribute is required
|
|
**getUV0()** | float2 | First interpolated set of UV coordinates, if the uv0 attribute is required
|
|
**getUV1()** | float2 | First interpolated set of UV coordinates, if the uv1 attribute is required
|
|
**inverseTonemap(float3)** | float3 | Applies the inverse tone mapping operator to the specified linear sRGB color. This operation may be an approximation
|
|
**inverseTonemapSRGB(float3)** | float3 | Applies the inverse tone mapping operator to the specified non-linear sRGB color. This operation may be an approximation
|
|
**luminance(float3)** | float | Computes the luminance of the specified linear sRGB color
|
|
|
|
# Compiling materials
|
|
|
|
Material packages can be compiled from material definitions using the command line tool called
|
|
`matc`. The simplest way to use `matc` is to specify an input material definition (`car_paint.mat`
|
|
in the example below) and an output material package (`car_paint.filamat` in the example below):
|
|
|
|
```text
|
|
$ matc -o ./materials/bin/car_paint.filamat ./materials/src/car_paint.mat
|
|
```
|
|
|
|
## Shader validation
|
|
|
|
`matc` attempts to validate shaders when compiling a material package. The example below shows an
|
|
example of an error message generated when compiling a material definition containing a typo in the
|
|
fragment shader (`metalic` instead of `metallic`). The reported line numbers are line numbers in the
|
|
source material definition file.
|
|
|
|
```text
|
|
ERROR: 0:13: 'metalic' : no such field in structure
|
|
ERROR: 0:13: '' : compilation terminated
|
|
ERROR: 2 compilation errors. No code generated.
|
|
|
|
Could not compile material metal.mat
|
|
```
|
|
|
|
## Flags
|
|
|
|
The command line flags relevant to application development are described in table [matcFlags].
|
|
|
|
Flag | Value | Usage
|
|
-------------------------------:|:------------------:|:---------------------
|
|
**-o**, **--output** | [path] | Specify the output file path
|
|
**-p**, **--platform** | desktop/mobile/all | Select the target platform(s)
|
|
**-a**, **--api** | opengl/vulkan/all | Specify the target graphics API
|
|
**-O**, **--optimize** | N/A | Optimize compiled material for performance
|
|
**-S**, **--optimize-size** | N/A | Optimize compiled material for size and performance
|
|
**-E**, **--preprocessor-only** | N/A | Optimize compiled material by running only the preprocessor
|
|
**-r**, **--reflect** | parameters | Outputs the specified metadata as JSON
|
|
**-v**, **--variant-filter** | [variant] | Filters out the specified, comma-separated variants
|
|
[Table [matcFlags]: List of `matc` flags]
|
|
|
|
`matc` offers a few other flags that are irrelevant to application developers and for internal
|
|
use only.
|
|
|
|
### --platform
|
|
|
|
By default, `matc` generates material packages containing shaders for all supported platforms. If
|
|
you wish to reduce the size of your material packages, it is recommended to select only the
|
|
appropriate target platform. For instance, to compile a material package for Android only, run
|
|
the following command:
|
|
|
|
```text
|
|
$ matc -p mobile -O -o ./materials/bin/car_paint.filamat ./materials/src/car_paint.mat
|
|
```
|
|
|
|
### --api
|
|
|
|
By default, `matc` generates material packages containing shaders for the OpenGL API. You can choose
|
|
to generate shaders for the Vulkan API in addition to the OpenGL shaders. If you intend on targeting
|
|
only Vulkan capable devices, you can reduce the size of the material packages by generating only
|
|
the set of Vulkan shaders:
|
|
|
|
```text
|
|
$ matc -a vulkan -O -o ./materials/bin/car_paint.filamat ./materials/src/car_paint.mat
|
|
```
|
|
|
|
### --optimize
|
|
|
|
This flag runs a separate optimization pass on the compiled material. This optimization pass applies
|
|
many optimization techniques to attempt to make the generated shaders faster to compile and execute
|
|
at runtime. In some cases using this flag might increase the size of the compiled material file.
|
|
It is recommended to use this flag when compiling your application in release mode.
|
|
|
|
### --optimize-size
|
|
|
|
This flag is similar to `--optimize` but applies fewer optimization techniques to try and keep the
|
|
final material as small as possible. If the compiled material is deemed too large with `--optimize`,
|
|
using this flag might be a good compromise between runtime performance and size.
|
|
|
|
### --preprocessor-only
|
|
|
|
This flags optimizes the compiled material by running only the preprocessor on the generated
|
|
shaders. This flag may result in compiled materials that are smaller than with `--optimize-size`.
|
|
This flag is only recommended if the size of the compiled material is more important than runtime
|
|
performance and if `--optimize-size` does not deliver satisfactory results.
|
|
|
|
### --reflect
|
|
|
|
This flag was designed to help build tools around `matc`. It allows you to print out specific
|
|
metadata in JSON format. The example below prints out the list of parameters defined in Filament's
|
|
standard skybox material. It produces a list of 2 parameters, named `showSun` and `skybox`,
|
|
respectively a boolean and a cubemap texture.
|
|
|
|
```text
|
|
$ matc --reflect parameters filament/src/materials/skybox.mat
|
|
{
|
|
"parameters": [
|
|
{
|
|
"name": "showSun",
|
|
"type": "bool",
|
|
"size": "1"
|
|
},
|
|
{
|
|
"name": "skybox",
|
|
"type": "samplerCubemap",
|
|
"format": "float",
|
|
"precision": "default"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### --variant-filter
|
|
|
|
This flag can be used to further reduce the size of a compiled material. It is used to specify a
|
|
list of shader variants that the application guarantees will never be needed. These shader variants
|
|
are skipped during the code generation phase of `matc`, thus reducing the overall size of the
|
|
material.
|
|
|
|
The variants must be specified as a comma-separated list, using one of the following available
|
|
variants:
|
|
|
|
- `directionalLighting`, used when a directional light is present in the scene
|
|
- `dynamicLighting`, used when a non-directional light (point, spot, etc.) is present in the scene
|
|
- `shadowReceiver`, used when an object can receive shadows
|
|
- `skinning`, used when an object is animated using GPU skinning
|
|
|
|
Example:
|
|
```
|
|
--variant-filter=skinning,shadowReceiver
|
|
```
|
|
|
|
Note that some variants may automatically be filtered out. For instance, all lighting related
|
|
variants (`directionalLighting`, etc.) are filtered out when compiling an `unlit` material.
|
|
|
|
When this flag is used, the specified variant filters are merged with the variant filters specified
|
|
in the material itself.
|
|
|
|
Use this flag with caution, filtering out a variant required at runtime may lead to crashes.
|
|
|
|
# Handling colors
|
|
|
|
## Linear colors
|
|
|
|
If the color data comes from a texture, simply make sure you use an sRGB texture to benefit from
|
|
automatic hardware conversion from sRGB to linear. If the color data is passed as a parameter to
|
|
the material you can convert from sRGB to linear by running the following algorithm on each
|
|
color channel:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
float sRGB_to_linear(float color) {
|
|
return color <= 0.04045 ? color / 12.92 : pow((color + 0.055) / 1.055, 2.4);
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Alternatively you can use one of the two cheaper but less accurate versions shown below:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
// Cheaper
|
|
linearColor = pow(color, 2.2);
|
|
// Cheapest
|
|
linearColor = color * color;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
## Pre-multiplied alpha
|
|
|
|
A color uses pre-multiplied alpha if its RGB components are multiplied by the alpha channel:
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GLSL
|
|
// Compute pre-multiplied color
|
|
color.rgb *= color.a;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If the color is sampled from a texture, you can simply ensure that the texture data is
|
|
pre-multiplied ahead of time. On Android, any texture uploaded from a
|
|
[Bitmap](https://developer.android.com/reference/android/graphics/Bitmap.html) will be
|
|
pre-multiplied by default.
|
|
|
|
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="../third_party/markdeep/markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
|