forked from google/filament
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Materials.md.html
2078 lines (1602 loc) · 90.8 KB
/
Materials.md.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<meta charset="utf-8">
<style>img { max-width: 100%; }</style>
**Filament Materials Guide**
![](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)
- [Mathias Agopian](https://github.com/pixelflinger), [@romainguy](https://twitter.com/darthmoosious)
# 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
- Specular glossiness (legacy)
## 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_)
**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
**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
**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
**ior** | Index of refraction for refractive objects
**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
**absorption** | Absorption factor for refractive objects
**microThickness** | Thickness of the thin layer of refractive objects
**thickness** | Thickness of the solid volume of refractive objects
[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] |
**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
**bentNormal** | 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..n], a=[0..1] | Linear RGB intensity in nits, alpha encodes the exposure weight
**postLightingColor** | float4 | [0..1] | Pre-multiplied linear RGB
**ior** | float | [1..n] | Optional, usually deduced from the reflectance
**transmission** | float | [0..1] |
**absorption** | float3 | [0..n] |
**microThickness** | float | [0..n] |
**thickness** | float | [0..n] |
[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.
!!! Note: About `absorption`
The light attenuation through the material is defined as $e^{-absorption \cdot distance}$,
and the distance depends on the `thickness` parameter. If `thickness` is not provided, then
the `absorption` parameter is used directly and the light attenuation through the material
becomes $1 - absorption$. To obtain a certain color at a desired distance, the above
equation can be inverted such as $absorption = -\frac{ln(color)}{distance}$.
!!! Note: About `ior` and `reflectance`
The index of refraction (IOR) and the reflectance represent the same physical attribute,
therefore they don't need to be both specified. Typically, only the reflectance is specified
and the IOR is deduced automatically. When only the IOR is specified, the reflectance is then
deduced automatically. It is possible to specify both, in which case their values are kept
as-is, which can lead to physically impossible materials, however, this might be desirable
for artistic reasons.
!!! Note: About `thickness` and `microThickness` for refraction
`thickness` represents the thickness of solid objects in the direction of the normal, for
satisfactory results, this should be provided per fragment (e.g.: as a texture) or at least per
vertex. `microThickness` represent the thickness of the thin layer of an object, and can
generally be provided as a constant value. For example, a 1mm thin hollow sphere of radius 1m,
would have a `thickness` of 1 and a `microThickness` of 0.001. Currently `thickness` is not
used when `refractionType` is set to `thin`.
### 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)
### Refraction
When refraction through an object is enabled (using a `refractonType` of `thin` or `solid`), the
`roughness` property will also affect the refractions, as shown in figure
[roughnessRefractionProperty] (click on the image to see a larger version).
![Figure [roughnessRefractionProperty]: Refractive sphere with `roughness` varying from 0.0
(left) to 1.0 (right)](images/materials/refraction_roughness.png)
### Reflectance
The `reflectance` property only affects non-metallic surfaces. This property can be used to control
the specular intensity and index of refraction of materials. 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 | IOR | Linear value
--------------------------:|:-----------------|:-----------------|:----------------
Water | 2% | 1.33 | 0.35
Fabric | 4% to 5.6% | 1.5 to 1.62 | 0.5 to 0.59
Common liquids | 2% to 4% | 1.33 to 1.5 | 0.35 to 0.5
Common gemstones | 5% to 16% | 1.58 to 2.33 | 0.56 to 1.0
Plastics, glass | 4% to 5% | 1.5 to 1.58 | 0.5 to 0.56
Other dielectric materials | 2% to 5% | 1.33 to 1.58 | 0.35 to 0.56
Eyes | 2.5% | 1.38 | 0.39
Skin | 2.8% | 1.4 | 0.42
Hair | 4.6% | 1.55 | 0.54
Teeth | 5.8% | 1.63 | 0.6
Default value | 4% | 1.5 | 0.5
[Table [commonMatReflectance]: Reflectance of common materials]
Note that the `reflectance` property also defines the index of refraction of the surface.
When this property is defined it is not necessary to define the `ior` property. Setting
either of these properties will automatically compute the other property. It is possible
to specify both, in which case their values are kept as-is, which can lead to physically
impossible materials, however, this might be desirable for artistic reasons.
The `reflectance` property is designed as a normalized property in the range 0..1 which makes
it easy to define from a texture.
See the Index of refraction section for more information about the `ior` property and refractive
indices.
### 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.
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.
### Bent normal
The `bentNormal` property defines the average unoccluded direction at a point on the surface. It is
used to improve the accuracy of indirect lighting. Bent normals can also improve the quality of
specular ambient occlusion (see section [Lighting: specularAmbientOcclusion] about
`specularAmbientOcclusion`).
Bent normals can greatly increase the visual fidelity of an asset with various cavities and concave
areas, as shown in figure [bentNormalMapped]. See the areas of the ears, nostrils and eyes for
instance.
![Figure [bentNormalMapped]: Example of a model rendered with and without a bent normal map. Both
versions use the same ambient occlusion map.](images/material_bent_normal.gif)
### 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 intensity in nits as well as an exposure
weight (in the alpha channel).
The intensity in nits allows an emissive surface to function as a light and can be used to recreate
real world surfaces. For instance a computer display has an intensity between 200 and 1,000 nits.
If you prefer to work in EV (or f-stops), you can simplify multiply your emissive color by the
output of the API `filament::Exposure::luminance(ev)`. This API returns the luminance in nits of
the specific EV. You can perform this conversion yourself using the following formula, where $L$
is the final intensity in nits: $ L = 2^{EV - 3} $.
The exposure weight carried in the alpha channel can be used to undo the camera exposure, and thus
force an emissive surface to bloom. When the exposure weight is set to 0, the emissive intensity is
not affected by the camera exposure. When the weight is set to 1, the intensity is multiplied by
the camera exposure like with any regular light.
### Post-lighting color
The `postLightingColor` can be used to modify the surface color after lighting computations. This
property has no physical meaning and only exists to implement specific effects or to help with
debugging. This property is defined as a `float4` value containing a pre-multiplied RGB color in
linear space.
The post-lighting color is blended with the result of lighting according to the blending mode
specified by the `postLightingBlending` material option. Please refer to the documentation of
this option for more information.
!!! Tip
`postLightingColor` can be used as a simpler `emissive` property by setting
`postLightingBlending` to `add` and by providing an RGB color with alpha set to `0.0`.
### Index of refraction
The `ior` property only affects non-metallic surfaces. This property can be used to control the
index of refraction and the specular intensity of materials. The `ior` property is intended to
be used with refractive (transmissive) materials, which are enabled when the `refractionMode` is
set to `cubemap` or `screenspace`.
The index of refraction (or refractive index) of a material is a dimensionless number that describes
how fast light travels through that material. The higher the number, the slower light travels
through the medium. More importantly for rendering materials, the refractive index determines how
the path light travels is bent when entering the material. Higher indices of refraction will cause
light to bend further away from the initial path.
Table [commonMatIOR] describes acceptable refractive indices for various types of materials.
Material | IOR
--------------------------:|:-----------------
Air | 1.0
Water | 1.33
Common liquids | 1.33 to 1.5
Common gemstones | 1.58 to 2.33
Plastics, glass | 1.5 to 1.58
Other dielectric materials | 1.33 to 1.58
[Table [commonMatIOR]: Index of refraction of common materials]
The appearance of a refractive material will greatly depend on the `refractionType` and
`refractionMode` settings of the material. Refer to the Blending and transparency: refractionType
section and the Blending and transparency: refractionMode section for more information.
The effect of `ior` when `refractionMode` is set to `cubemap` and `refractionType` is set to `solid`
can be seen in figure [iorProperty2] (click on the image to see a larger version).
![Figure [iorProperty2]: `transmission` varying from 1.0
(left) to 1.5 (right)](images/materials/ior.png)
Figure [iorProperty] shows the comparison of a sphere of `ior` 1.0 with a sphere of `ior` 1.33, with
the `refractionMode` set to `screenspace` and the `refractionType` set to `solid`
(click on the image to see a larger version).
![Figure [iorProperty]: `ior` of 1.0 (left) and 1.33 (right)](images/material_ior.png)
Note that the `ior` property also defines the reflectance (or specular intensity) of the surface.
When this property is defined it is not necessary to define the `reflectance` property. Setting
either of these properties will automatically compute the other property. It is possible to specify
both, in which case their values are kept as-is, which can lead to physically impossible materials,
however, this might be desirable for artistic reasons.
See the Reflectance section for more information on the `reflectance` property.
!!! Tip
Refractive materials are affected by the `roughness` property. Rough materials will scatter
light, creating a diffusion effect useful to recreate "blurry" appearances such as frosted
glass, certain plastics, etc.
### Transmission
The `transmission` property defines what ratio of diffuse light is transmitted through a refractive
material. This property only affects materials with a `refractionMode` set to `cubemap` or
`screenspace`.
When `transmission` is set to 0, no amount of light is transmitted and the diffuse component of
the surface is 100% visible. When `transmission` is set to 1, all the light is transmitted and the
diffuse component is not visible anymore, only the specular component is.
The effect of `transmission` on a glossy dielectric (`ior` of 1.5, `refractionMode` set to
`cubemap`, `refractionType` set to `solid`) is shown in figure [transmissionProperty]
(click on the image to see a larger version).
![Figure [transmissionProperty]: `transmission` varying from 0.0
(left) to 1.0 (right)](images/materials/transmission.png)
!!! Tip
The `transmission` property is useful to create decals, paint, etc. at the surface of refractive
materials.
### Absorption
The `absorption` property defines the absorption coefficients of light transmitted through the
material. Figure [absorptionExample] shows the effect of `absorption` on a refracting object with
an index of refraction of 1.5 and a base color set to white.
![Figure [absorptionExample]: Refracting object without (left)
and with (right) absorption](images/material_absorption.png)
Transmittance through a volume is exponential with respect to the optical depth (defined either
with `microThickness` or `thickness`). The computed color follows the following formula:
$$color \cdot e^{-absorption \cdot distance}$$
Where `distance` is either `microThickness` or `thickness`, that is the distance light will travel
through the material at a given point. If no thickness/distance is specified, the computed color
follows this formula instead:
$$color \cdot (1 - absorption)$$
The effect of varying the `absorption` coefficients is shown in figure [absorptionProperty]
(click on the image to see a larger version). In this picture, the object has a fixed `thickness`
of 4.5 and an index of refraction set to 1.3.
![Figure [absorptionProperty]: `absorption` varying from (0.0, 0.02, 0.14)
(left) to (0.0, 0.36, 2.3) (right)](images/materials/absorption.png)
Setting the absorption coefficients directly can be unintuitive which is why we recommend working
with a _transmittance color_ and a _"at distance"_ factor instead. These two parameters allow an
artist to specify the precise color the material should have at a specified distance through the
volume. The value to pass to `absorption` can be computed this way:
$$absorption = -\frac{ln(transmittanceColor)}{atDistance}$$
While this computation can be done in the material itself we recommend doing it offline whenever
possible. Filament provides an API for this purpose, `Color::absorptionAtDistance()`.
### Micro-thickness and thickness
The `microThickness` and `thickness` properties define the optical depth of the material of a
refracting object. `microThickness` is used when `refractionType` is set to `thin`, and `thickness`
is used when `refractionType` is set to `volume`.
`thickness` represents the thickness of solid objects in the direction of the normal, for
satisfactory results, this should be provided per fragment (e.g.: as a texture) or at least per
vertex.
`microThickness` represent the thickness of the thin layer (shell) of an object, and can generally
be provided as a constant value. For example, a 1mm thin hollow sphere of radius 1m, would have a
`thickness` of 1 and a `microThickness` of 0.001. Currently `thickness` is not used when
`refractionType` is set to `thin`. Both properties are made available for possible future use.
Both `thickness` and `microThickness` are used to compute the transmitted color of the material
when the `absorption` property is set. In solid volumes, `thickness` will also affect how light
rays are refracted.
The effect `thickness` in a solid volume with `refractionMode` set to `screenSpace` is shown in
figure [thicknessProperty] (click on the image to see a larger version). Note how the `thickness`
value not only changes the effect of `absorption` but also modifies the direction of the refracted
light.
![Figure [thicknessProperty]: `thickness` varying from 0.0
(left) to 2.0 (right)](images/materials/thickness.png)
Figure [varyingThickness] shows what a prism with spatially varying `thickness` looks like when
the `refractionType` is set to `solid` and `absorption` coefficients are set.
![Figure [varyingThickness]: `thickness` varying from 0.0 at the top of the prism to 3.0 at the
bottom of the prism](images/material_thickness.png)
## 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 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.
!!! 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
**postLightingColor** | Additional color to blend with base color and emissive
[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..n], a=[0..1] | Linear RGB intensity in nits, alpha encodes the exposure weight
**postLightingColor** | float4 | [0..1] | Pre-multiplied linear RGB
[Table [unlitPropertiesTypes]: Range and type of the unlit model's properties]
The value of `postLightingColor` is blended with the sum of `emissive` and `baseColor` according to
the blending mode specified by the `postLightingBlending` material option.
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)
## Specular glossiness
This alternative lighting model exists to comply with legacy standards. Since it is not a
physically-based formulation, we do not recommend using it except when loading legacy assets.
This model encompasses the parameters previously defined for the standard lit mode except for
_metallic_, _reflectance_, and _roughness_. It adds parameters for _specularColor_ and _glossiness_.
Parameter | Definition
---------------------:|:---------------------
**baseColor** | Surface diffuse color
**specularColor** | Specular tint (defaults to black)
**glossiness** | Glossiness (defaults to 0.0)
[Table [glossinessProperties]: Properties of the specular-glossiness shading model]
The type and range of each property is described in table [glossinessPropertiesTypes].
Property | Type | Range | Note
---------------------:|:--------:|:------------------------:|:-------------------------
**baseColor** | float4 | [0..1] | Pre-multiplied linear RGB
**specularColor** | float3 | [0..1] | Linear RGB
**glossiness** | float | [0..1] | Inverse of roughness
[Table [glossinessPropertiesTypes]: Range and type of the specular-glossiness model's properties]
# 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.
### General: 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"
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: shadingModel
Type
: `string`
Value
: Any of `lit`, `subsurface`, `cloth`, `unlit`, `specularGlossiness`. Defaults to `lit`.
Description
: Selects the material model as described in the Material models section.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
shadingModel : unlit
}
material {
shadingModel : "subsurface"
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### General: 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;