Files
filament/docs/Materials.md.html
Romain Guy 4585b8f896 Add clearCoatNormal property (#131)
* 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
2018-08-24 08:56:44 -07:00

1544 lines
64 KiB
HTML

<meta charset="utf-8">
<style>img { max-width: 100%; }</style>
![](images/filament_logo.png)
# 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">&nbsp;</div>
Rubber | 0.21, 0.21, 0.21 | #353535 | <div style="background-color: #353535; width: 60px">&nbsp;</div>
Mud | 0.33, 0.24, 0.19 | #553d31 | <div style="background-color: #875c3c; width: 60px">&nbsp;</div>
Wood | 0.53, 0.36, 0.24 | #875c3c | <div style="background-color: #c4c6c6; width: 60px">&nbsp;</div>
Vegetation | 0.48, 0.51, 0.31 | #7b824e | <div style="background-color: #7b824e; width: 60px">&nbsp;</div>
Brick | 0.58, 0.49, 0.46 | #947d75 | <div style="background-color: #947d75; width: 60px">&nbsp;</div>
Sand | 0.69, 0.66, 0.52 | #b1a884 | <div style="background-color: #b1a884; width: 60px">&nbsp;</div>
Concrete | 0.75, 0.75, 0.73 | #c0bfbb | <div style="background-color: #c0bfbb; width: 60px">&nbsp;</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">&nbsp;</div>
Aluminum | 0.91, 0.92, 0.92 | #e8eaea | <div style="background-color: #f4f5f5; width: 60px">&nbsp;</div>
Titanium | 0.76, 0.73, 0.69 | #c1baaf | <div style="background-color: #cec8c2; width: 60px">&nbsp;</div>
Iron | 0.77, 0.78, 0.78 | #c4c6c6 | <div style="background-color: #c0bdba; width: 60px">&nbsp;</div>
Platinum | 0.83, 0.81, 0.78 | #d3cec6 | <div style="background-color: #d6d1c8; width: 60px">&nbsp;</div>
Gold | 1.00, 0.85, 0.57 | #ffd891 | <div style="background-color: #fedc9d; width: 60px">&nbsp;</div>
Brass | 0.98, 0.90, 0.59 | #f9e596 | <div style="background-color: #f4e4ad; width: 60px">&nbsp;</div>
Copper | 0.97, 0.74, 0.62 | #f7bc9e | <div style="background-color: #fbd8b8; width: 60px">&nbsp;</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>