├── CLA_Corporate.pdf
├── CLA_Individual.pdf
├── LICENSE.txt
├── README.md
├── images
├── autodesk-logo.svg
├── coat1.jpg
├── coat2.jpg
├── coat3.jpg
├── diagram_closure_mix.svg
├── diagram_model.svg
├── diagrams.pdf
├── emission.jpg
├── metals.jpg
├── sheen1.jpg
├── sheen2.jpg
├── sheen3.jpg
├── spec_ior1.jpg
├── spec_ior2.jpg
├── spec_ior3.jpg
├── subsurface1.jpg
├── subsurface2.jpg
├── subsurface3.jpg
├── thin_film1.jpg
├── thin_film2.jpg
├── thin_film3.jpg
├── thin_walled1.jpg
├── thin_walled2.jpg
├── title.jpg
├── transmission1.jpg
├── transmission2.jpg
├── transmission3.jpg
├── transparency1.jpg
├── transparency2.jpg
└── transparency3.jpg
├── index.html
├── reference
├── standard_surface.mtlx
└── standard_surface.osl
└── style
├── fonts
├── Artifakt
│ ├── Artifakt Element Bold.woff2
│ ├── Artifakt Element Medium.woff2
│ ├── Artifakt Element Regular.woff2
│ └── Artifakt Legend Bold.woff2
├── PTSerif
│ ├── PTSerif-Bold.woff2
│ ├── PTSerif-Italic.woff2
│ └── PTSerif-Regular.woff2
└── RobotoMono
│ ├── RobotoMono-Bold.woff2
│ └── RobotoMono-Regular.woff2
├── markdeep-1.04.min.js
└── style.css
/CLA_Corporate.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/CLA_Corporate.pdf
--------------------------------------------------------------------------------
/CLA_Individual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/CLA_Individual.pdf
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2019 Autodesk
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Autodesk Standard Surface
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | A white paper specifying an uber surface shader that aims to provide a material representation capable of accurately modeling the vast majority of materials used in practical visual effects and feature animation productions. It follows the design of the Standard Surface shader in the Arnold renderer, whose implementation is relatively uncomplicated and whose user interface consists of a small set of parameters with intuitive meanings and ranges. The white paper is versioned and will be updated as the specification evolves.
12 |
13 |
14 | ### Resources
15 |
16 | * **[White paper](https://autodesk.github.io/standard-surface/)** – typeset in [Markdeep](https://casual-effects.com/markdeep/), mobile and print friendly
17 | * **[Reference implementation](reference/standard_surface.osl)** – written in [OSL](https://github.com/imageworks/OpenShadingLanguage), work in progress
18 |
19 | ### Discussion
20 | * **[GitHub issues](https://github.com/Autodesk/standard-surface/issues)**
21 | * **[Google group](https://groups.google.com/a/arnoldrenderer.com/forum/#!forum/standard.surface)**
22 |
23 |
24 |
25 | [](LICENSE.txt)
26 |
--------------------------------------------------------------------------------
/images/autodesk-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/coat1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/coat1.jpg
--------------------------------------------------------------------------------
/images/coat2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/coat2.jpg
--------------------------------------------------------------------------------
/images/coat3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/coat3.jpg
--------------------------------------------------------------------------------
/images/diagram_model.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/images/diagrams.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/diagrams.pdf
--------------------------------------------------------------------------------
/images/emission.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/emission.jpg
--------------------------------------------------------------------------------
/images/metals.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/metals.jpg
--------------------------------------------------------------------------------
/images/sheen1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/sheen1.jpg
--------------------------------------------------------------------------------
/images/sheen2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/sheen2.jpg
--------------------------------------------------------------------------------
/images/sheen3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/sheen3.jpg
--------------------------------------------------------------------------------
/images/spec_ior1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/spec_ior1.jpg
--------------------------------------------------------------------------------
/images/spec_ior2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/spec_ior2.jpg
--------------------------------------------------------------------------------
/images/spec_ior3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/spec_ior3.jpg
--------------------------------------------------------------------------------
/images/subsurface1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/subsurface1.jpg
--------------------------------------------------------------------------------
/images/subsurface2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/subsurface2.jpg
--------------------------------------------------------------------------------
/images/subsurface3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/subsurface3.jpg
--------------------------------------------------------------------------------
/images/thin_film1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/thin_film1.jpg
--------------------------------------------------------------------------------
/images/thin_film2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/thin_film2.jpg
--------------------------------------------------------------------------------
/images/thin_film3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/thin_film3.jpg
--------------------------------------------------------------------------------
/images/thin_walled1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/thin_walled1.jpg
--------------------------------------------------------------------------------
/images/thin_walled2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/thin_walled2.jpg
--------------------------------------------------------------------------------
/images/title.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/title.jpg
--------------------------------------------------------------------------------
/images/transmission1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transmission1.jpg
--------------------------------------------------------------------------------
/images/transmission2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transmission2.jpg
--------------------------------------------------------------------------------
/images/transmission3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transmission3.jpg
--------------------------------------------------------------------------------
/images/transparency1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transparency1.jpg
--------------------------------------------------------------------------------
/images/transparency2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transparency2.jpg
--------------------------------------------------------------------------------
/images/transparency3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/images/transparency3.jpg
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | **Autodesk Standard Surface**
6 | Iliyan Georgiev, Jamie Portsmouth, Zap Andersson, Adrien Herubel, Alan King, Shinji Ogaki, Frederic Servant
7 |
8 | *version 1.0.1.1*
9 | 
10 | 
11 |
12 |
13 | This document is a specification of an uber surface shader that aims to provide a material representation capable of accurately modeling the vast majority of materials used in practical visual effects and feature animation productions. It follows the design of the Standard Surface shader in the Arnold renderer, whose implementation is relatively uncomplicated and whose user interface consists of a small set of parameters with intuitive meanings and ranges. This document is versioned and will be updated as the specification evolves.
14 |
15 | We provide OSL and MaterialX reference implementations [#Georgiev2019], whose intention is to specify enough detail to allow for implementation in other renderers that matches the look to a reasonable level of fidelity depending on the purpose.
16 |
17 |
18 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 |
20 |
21 | Historical background and objectives
22 | ================================================================================
23 |
24 | Interchange of computer graphics scene assets between different facilities remains a significant problem today, especially with regard to surface appearance. Different renderers and 3D engines use different shading systems, shading languages, and fixed-function pipelines. Furthermore, accurately modeling surface appearance remains a complex and pertinent problem, and is a topic of active scientific research. However, there is a strong need *today* for the industry to find a standardized material model that both covers most common use cases in day-to-day workflows and is easy to use.
25 |
26 | Over the years, certain de-facto standard appearance definition frameworks have emerged as different vendors have come to the consensus of separating the definition of materials from the light transport simulation in the scene. Such general frameworks include MaterialX, Material Definition Language (MDL), and Open Shading Language (OSL) [#Gritz2010], which allow specifying the material as a combination of primitive surface reflectance models. These frameworks alone however are not sufficient for look development by end users who should not be expected to build surface shaders from the ground up for day-to-day tasks. There is a need for a standard uber-shader parametrization with a well-defined set of parameters that can be tweaked to represent most real-world (as well as imaginary) materials. In this proposal we aim to fill this gap; one of our reference implementations is written in OSL [#Georgiev2019].
27 |
28 | Our proposed model follows closely the Arnold 5 Standard Surface shader, which has strong spiritual predecessors in Anders Langlands' alSurface [#Langlands2014] and Autodesk 3ds Max's Physical Material [#Andersson2016]. The alSurface shader has served as a de-facto standard in the industry for a while but is no longer actively developed. 3ds Max's Physical Material in turn has been strongly inspired by Allegorithmic's PBR shading model [#McDermott2018], Disney's Principled Shader [#Burley2012], and general industry trends in several real-time 3D engines, and has been production proven with support by all major render engines for 3ds Max.
29 |
30 | In this proposal, rather than providing parameters for every conceivable case, we intentionally try to boil the set of parameters down to only those that are most useful in practice. We also fix the combination of primitive reflectance models to ensure that the users work within the bounds of what is physically plausible as much as possible. We aim for the overall behavior to be simple, logical, intuitive, and understandable, so that the model covers most day-to-day use cases. For the few it does not cover, one may need to use a renderer-specific shader, or build a bespoke shading network.
31 |
32 |
33 | Layered mixture model
34 | ================================================================================
35 |
36 | Our goal is to create a surface shading model that is able to faithfully represent a wide variety of real-world materials. The light scattering characteristics at the surfaces of basic materials like metal, glass, or wall paint are well studied and can be accurately represented via simple analytical models. Other materials, such as finished wood, cloth, or skin, comprise semi-transparent layers of matter stacked on top of each other. The more intricate behavior of such materials is the result of light scattering at the interfaces between these layers and propagating through them, and each such scattering interface can typically be represented by an analytical model. Additionally, many real-world objects are made of several different materials, e.g. metal and plastic, and it is convenient to model the appearance of such objects by texturing the type of each material on their surfaces. While the material transitions are typically abrupt, the ability to continuously mix materials is useful for artistic purposes as well as for anti-aliasing.
37 |
38 | The two basic operations -- layering and mixing -- provide a language for modeling diverse materials with complex appearance. For a stack of layers to be physically meaningful, it should have an opaque (e.g. metal) or transparent (e.g. glass or skin) bulk at the bottom, with a set of dielectric slabs on top of it. Any light that is not reflected at an interface between two layers is transmitted down through the lower layer, with optional absorption inside its corresponding medium. The mixture operation can be thought of as statistical mix of two materials, even though not all combinations make physical sense. Being a linear interpolation, this operation automatically maintains energy conservation.
39 |
40 | Our shader models a material consisting of ten components that are layered and mixed hierarchically as illustrated in Figure [diagram_model]. The properties of individual components can vary across the surface.
41 |
42 | ![Figure [diagram_model]: Schematic illustration of the idealized material model that our shader emulates. Horizontal stacking of components represents statistical mixture and vertical stacking represents layering. Components marked with an asterisk are optional, as discussed in Section [Compatibility mode].](images/diagram_model.svg width="100%")
43 |
44 |
45 | Closure mixture representation
46 | --------------------------------------------------------------------------------
47 |
48 | Given a shading point and a view direction, the evaluation result of our shader is a *bidirectional scattering distribution function* (BSDF) that describes the light scattering properties of the surface at that point and direction (plus an emission component and a subsurface scattering distribution [^bsdf1]). This resultant BSDF represents the aggregate light scattering behavior at the topmost interface due to propagation and scattering inside the entire structure of the material.
49 |
50 | Accurately simulating the light propagation inside layered materials is generally difficult and computationally expensive, and remains a topic of active research. Our shader takes the common pragmatic approach that the resultant BSDF can be represented as a simple mixture (i.e. linear combination) of "atomic", building-block BSDFs -- one for each component in Figure [diagram_model]. We still try to emulate the most important physical effects of layering -- color tinting, reflection/transmission blurring, and angle-dependent layer transparency -- by adjusting the properties and linear combination weights of the atomic BSDFs.
51 |
52 | Each atomic BSDF, often informally referred to as a "lobe", is either a reflection or a transmission distribution function, i.e. BRDF or BTDF (except for emission and subsurface scattering). In our implementation, these BSDFs are represented by *closures*. A closure is a "black-box" object that contains renderer-specific routines for evaluating and sampling the underlying BSDF [^bsdf2]. It is defined and used by the renderer but is *instantiated* by the shader with a set of parameters of basic data types, such as floats, vectors, and colors.
53 |
54 | Our shader returns a list of closure objects, each with an associated (color) weight. The closures' instantiation parameters and weights can be controlled by the user via a set of shader-level parameters to simulate a wide variety of physically plausible materials. The sum of weighted closures fully describes the light emission and scattering properties at the given surface point. The closure list, shown in Table [closures], is ultimately passed to the renderer for integrating the light transport around the shading point.
55 |
56 |
57 | Component | Closure | Description
58 | -----------------------|-----------------|-----------------------------------
59 | Transparency | `transparency` | simple pass-through (can be thought of as a delta BTDF)
60 | Coating | `specular_brdf` | dielectric microfacet BRDF (GGX)
61 | Emission | `emission` | diffuse emission
62 | Metal | `metal_brdf` | conductor microfacet BRDF (GGX)
63 | Specular reflection | `specular_brdf` | dielectric microfacet BRDF (GGX)
64 | Specular transmission* | `specular_btdf` | dielectric microfacet BTDF (GGX)
65 | Sheen* | `sheen_brdf` | retro-reflective dielectric microfacet BRDF [#Estevez2017]
66 | Subsurface scattering* | `subsurface` | subsurface scattering (e.g. diffusion or random-walk)
67 | Diffuse transmission* | `diffuse_btdf` | diffuse microfacet BTDF (Oren-Nayar)
68 | Diffuse reflection | `diffuse_brdf` | diffuse microfacet BRDF (Oren-Nayar)
69 | [Table [closures]: The list of closures representing each component of the material model illustrated in Figure [diagram_model]. Closures marked with an asterisk are optional, as discussed in Section [Compatibility mode].]
70 |
71 | The closure weights are computed by a formula designed to satisfy energy conservation by construction while approximately simulating the effects of light propagation between layers. Arguably, the most prominent such effect is the directionally varying transparency of specular (dielectric) layers, which is a result of their Fresnel-governed hemispherical-directional reflectance (a.k.a. directional albedo). We weigh the corresponding BRDF closures against the underlying closures based on their reflectance, and our implementation assumes that a `reflectance(brdf)` function is available to compute it. When an analytical expression for the reflectance integral is not available for a closure, it can be approximated, e.g. via Monte Carlo estimation.
72 |
73 | The closure weight computation logic of our shader is most easily visualized as a tree, where every leaf node is a closure and every inner node is a linear combination of its two children, with weights specified at the edges. We illustrate this tree structure in Figure [diagram_closure_mix]. The final weight of each closure is the product of edge weights along the path between its corresponding leaf note and the root node. In Section [Closures] below we describe the individual closures and edge weights in more detail.
74 |
75 | ![Figure [diagram_closure_mix]: Our shader returns the root closure `standard_surface`, which is a weighted sum of "atomic" closures shown as leaf nodes in the tree. The weight of each closure is the product of edge weights along the path from its corresponding leaf to the root node. The edge weights are parameterized by shader-level parameters, shown in bold.](images/diagram_closure_mix.svg width="100%")
76 |
77 |
78 | Compatibility mode
79 | --------------------------------------------------------------------------------
80 |
81 | Our model aims to be relatively simple for production-grade applications, however the number of its closures and parameters can be too much to handle for real-time engines. For such applications, we define a "preview" level of compatibility that simplifies our shader to a reasonable level of visual similarity in typical cases. The simplification amounts to zeroing the combination weight parameters **`transmission`**, **`sheen`**, and **`subsurface`**, which effectively eliminates the `specular_btdf`, `sheen_brdf`, `subsurface`, and `diffuse_btdf` closures. In this compatibility mode we also ignore certain parameters in other closures, which are marked with asterisks in the parameter tables in the following section.
82 |
83 |
84 | Closures
85 | ================================================================================
86 |
87 | In this section, we describe the individual closures used by our shader, listed in Table [closures], their parameters and how they are weighted against each other. Some parameters are reused among closures, hence they appear multiple times in the subsections below. We denote shader-level parameters with bold font, e.g. **`opacity`**.
88 |
89 |
90 | Transparency
91 | --------------------------------------------------------------------------------
92 |
93 | The `transparency` closure has no instantiation parameters and makes the surface fully transparent at the shading point, i.e. the input ray is transmitted un-deflected and un-tinted. The effect is illustrated in Figure [opacity]. The **`opacity`** shader parameter controls the relative weight (via a linear "alpha" blend) of all other closures, hence the transparency weight is `1-`**`opacity`**.
94 |
95 | The combination of transparency and coat closures via the following formula is the top level mixture which yields the final `standard_surface` closure combination:
96 |
97 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
98 | standard_surface = (1 - opacity) * transparency() + opacity * coat_layer
99 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 |
101 | where the `coat_layer` closure is defined in the following subsection.
102 |
103 | (###) Shader parameters: transparency
104 |
105 | Name | Type | Default | Description
106 | ---------------|-------|---------|-------------
107 | **`opacity`** | color | `1,1,1` | the (colored) opacity of the surface (fully opaque by default)
108 |
109 |
110 |   
111 |
112 | ![Figure [opacity]: Opacity vs. transmission. From left to right: sphere with transmission only, (binary) opacity mask, sphere with transmission and masked opacity.](dummy)
113 |
114 |
115 |
116 | Coating
117 | --------------------------------------------------------------------------------
118 |
119 | The topmost scattering layer is a dielectric coating with a GGX microfacet BRDF closure `coat_brdf`. As a dielectric, this BRDF is not energy preserving (i.e. its directional reflectance is generally less than one) as it obeys Fresnel reflection laws. The layer is assumed to be infinitely thin, and the remaining non-reflected light is passed directly to the underlying layer without refraction. The reflection color is fixed to white, though the coat medium color can be user controlled.
120 |
121 | The closure combination formula is
122 |
123 |
126 |
127 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
128 | coat_layer = coat * coat_brdf(...) + lerp(white, coat_color * (1 - reflectance(coat_brdf)), coat) * emission_specular_mixture
129 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130 |
131 | where `lerp(a, b, t) = (1 - t) * a + t * b`, and the `emission_specular_mixture` closure is defined in the following subsection.
132 |
133 | In the above closure formula, `white` denotes a constant white color. The coat layer is then effectively a statistical mix between a "no-op" passthrough (when the `coat` parameter goes to zero) and a dielectric slab with an embedded absorbing medium.
134 |
135 | In a real physical material, light scattered by underlying layers is tinted and blurred when transmitted through a colored/rough coating. Capturing these effects accurately in a renderer requires simulating the light interactions between the individual layers in order. Since our model is a simple linear combination of closures that are evaluated independently, we emulate these effects:
136 |
137 |
138 |
139 | Tinting all layers below the coating is achieved by scaling their closures by the **`coat_color`** parameter, which can be interpreted as the absorption effect within the coat medium tinting the reflection from the underlying layers (i.e. energy is absorbed by a tinted coat layer).
140 |
141 |
142 | With a dielectric coating on top of a substrate, a fraction of the light exhibits internal reflection inside the coating and goes back down to the substrate to reflect again, becoming darker and more saturated. This effect can be emulated via the **`coat_affect_color`** parameter, which is used as an exponent to the substrate color, currently limited to diffuse reflection and sub-surface scattering:
143 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
144 | base_color = pow(base_color, 1.0 + (coat * coat_affect_color))
145 | subsurface_color = pow(subsurface_color, 1.0 + (coat * coat_affect_color))
146 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
147 |
148 |
149 | We also provide an option for the coating roughness to increase the roughness of the other GGX BSDFs, namely `metal_brdf`, `specular_brdf`, and `specular_btdf`. The remaining BSDFs are not modulated as they are already rough. The formula for modulating a given **`roughness`** is
150 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
151 | roughness = lerp(roughness, 1, coat * coat_affect_roughness * coat_roughness)
152 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153 |
154 |
155 |
156 |
157 | (###) Shader parameters: coating
158 |
159 | Name | Type | Default | Description
160 | -----------------------------|-------|----------|------------
161 | **`coat`** | float | `0` | reflection weight (reflection color is fixed to white)
162 | **`coat_color`** | color | `1,1,1` | tint color for the light coming from all layers below
163 | **`coat_roughness`** | float | `0.1` | coat reflection roughness; squared internally before passed to the BSDF to achieve a more linear perceptual response [#Burley2012]
164 | **`coat_anisotropy`*** | float | `0` | reflection anisotropy of `coat_brdf`; range `[0,1]`
165 | **`coat_rotation`*** | float | `0` | orientation of anisotropy; range `[0,1]` (where `1` means 360 degrees)
166 | **`coat_IOR`** | float | `1.5` | refractive index of `coat_brdf`
167 | **`coat_normal`** | vector | `0,0,0` | shading normal for the coating reflections; optional, overrides the default shading normal; has no effect on the closure combination weights
168 | **`coat_affect_color`*** | float | `0` | how much to additionally modulate diffuse reflection and subsurface scattering saturation; range `[0,1]`
169 | **`coat_affect_roughness`*** | float | `0` | how much to affect the roughness of the specular reflection layers below; range `[0,1]`
170 |
171 |   
172 |
173 | ![Figure [coat]: Various effects that can be achieved by combining a coat and a specular layer. From left to right: flakes, raindrops, carbon fiber.](dummy)
174 |
175 |
176 |
177 | Emission
178 | --------------------------------------------------------------------------------
179 |
180 | An additive directionally uniform (i.e. Lambertian) emission closure `emission` sits below the coating, but is otherwise unaffected by the energy-conservation logic for the combination weights that is applied to the other closures. We put emission below the coating to allow for the rendering of low-emission materials that are bounded by a reflective surface (e.g. glow sticks) without explicit modeling of the emitter and the bounding object.
181 |
182 | The closure combination involving emission is
183 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
184 | emission_specular_mixture = emission * emission_color * emission() + specular_mixture
185 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
186 |
187 | where the `specular_mixture` closure is defined below.
188 |
189 | (###) Shader parameters: emission
190 |
191 | Name | Type | Default | Description
192 | ---------------------|-------|---------|------------
193 | **`emission`** | float | `0` | emission color multiplier
194 | **`emission_color`** | color | `1,1,1` | emission color
195 |
196 | ![Figure [emission]: Texture map representing hot lava connected to **`emission_color`**.](images/emission.jpg width=40%)
197 |
198 |
199 | Metal
200 | --------------------------------------------------------------------------------
201 |
202 | Metallic reflection from under the coat layer is modeled as a GGX microfacet conductor BRDF `metal_brdf`, whose absorption coefficient and complex index of refraction are computed from the more user-friendly parameters **`base_color`** and **`specular_color`** [#Gulbrandsen2014], defined below. This allows for achieving a desired look by directly specifying the (texturable) colors at normal and grazing incidence. Note that these two color parameters are also used for the non-metallic (i.e. dielectric) specular and diffuse BRDFs, discussed below.
203 |
204 | This non-transmissive metallic BRDF is blended as a statistical mixture with the non-metallic (i.e. dielectric) specular layer model, described in the next section, according to the **`metalness`** parameter as follows:
205 |
206 |
209 |
210 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
211 | specular_mixture = metalness * metal_brdf(...) + (1 - metalness) * specular_reflection_layer
212 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213 |
214 | where the `specular_reflection_layer` closure is defined below.
215 |
216 | Rainbow-like iridescence effects occur, due to interference, when a thin refractive film with thickness on the order of the light wavelength is placed on top of a material. These effects are incorporated in the microfacet closures, which applies to the metal or specular reflection and transmission layers, whichever is present. The thin-film logically sits between the coat and underlying layer, but since the coat layer is assumed to be infinitely thin, the refractive index of the medium exterior to the film is taken to be that of vacuum, i.e. `1.0`. The one interior to it is assumed to be that of the specular layer. The thin-film model is based on that of Belcour and Barla [#Belcour2017].
217 |
218 | (###) Shader parameters: metal
219 |
220 | Name | Type | Default | Description
221 | ---------------------------|-------|---------|------------
222 | **`base`** | float | `1` | scalar multiplier to **`base_color`**
223 | **`base_color`** | color | `0.8,0.8,0.8` | reflection color at normal incidence (i.e. surface seen from straight up)
224 | **`specular`** | float | `1` | scalar multiplier to **`specular_color`**
225 | **`specular_color`** | color | `1,1,1` | reflection color at grazing incidence (i.e. around silhouettes)
226 | **`specular_roughness`** | float | `0.2` | reflection roughness; squared internally before passed to the BSDF in order to achieve a more uniform roughness look over the parameter range
227 | **`specular_anisotropy`*** | float | `0` | reflection anisotropy of `metal_brdf`; range `[0,1]`
228 | **`specular_rotation`*** | float | `0` | orientation of anisotropy; range `[0,1]` (where `1` means 360 degrees)
229 | **`thin_film_thickness`*** | float | `0` | thickness of the film (in nanometres)
230 | **`thin_film_IOR`*** | float | `1.5` | refractive index of the film
231 |
232 | ![Figure [metal]: Metals produced by the metal closure by setting the **`base_color`** and **`specular_color`** parameters. From left to right: aluminium, copper, gold.](images/metals.jpg)
233 |
234 |   
235 |
236 | ![Figure [thinfilm]: The effect of thin-film interference on a surface. From left to right: multi-tone car paint, soap bubbles, and burnt chrome.](dummy)
237 |
238 |
239 |
240 | Specular reflection
241 | --------------------------------------------------------------------------------
242 |
243 | This layer models a GGX microfacet dielectric BRDF `specular_brdf`, conceptually right under the coating. Similarly to the coating, this BRDF is not itself energy conserving due to Fresnel laws, and the energy that is not reflected is completely transmitted to the underlying layers. The closure combination we use which expresses the energy balance between the reflected and transmitted specular lobes is then
244 |
245 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
246 | specular_reflection_layer = specular * specular_color * specular_brdf(...) + (1 - specular_color * specular * reflectance(specular_brdf)) * transmission_sheen_mix
247 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248 |
249 | where the `transmission_sheen_mix` closure is defined below.
250 |
251 | (###) Shader parameters: specular reflection
252 |
253 | Name | Type | Default | Description
254 | ---------------------------|-------|---------|------------
255 | **`specular`** | float | `1` | specular reflection weight
256 | **`specular_color`** | color | `1,1,1` | specular reflection color
257 | **`specular_roughness`** | float | `0.2` | reflection roughness; squared internally before passed to the BSDF to achieve a more uniform roughness look over the parameter range
258 | **`specular_IOR`** | float | `1.5` | refractive index of `specular_brdf`
259 | **`specular_anisotropy`*** | float | `0` | reflection anisotropy of `specular_brdf`; range `[0,1]`
260 | **`specular_rotation`*** | float | `0` | orientation of anisotropy; range `[0,1]` (`1` means 360 degrees)
261 | **`thin_film_thickness`*** | float | `0` | thickness of the film (in nanometres)
262 | **`thin_film_IOR`*** | float | `1.5` | refractive index of the film
263 |
264 |   
265 |
266 | ![Figure [specior]: Varying the specular refractive index. From left to right: 1.0, 1.1, 1.52 (default).](dummy)
267 |
268 |
269 |
270 | Specular transmission
271 | --------------------------------------------------------------------------------
272 |
273 | This layer models a statistical blend (according to the **`transmission`** parameter) of either transmission through the bottom of the specular layer via a GGX microfacet BTDF `specular_btdf`, or scattering from a diffuse base layer (`base_layer`). The closure combination is given by
274 |
275 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
276 | transmission_sheen_mix = transmission * transm_color * specular_btdf(...) + (1 - transmission) * sheen_layer
277 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278 |
279 | where the `sheen_layer` closure is defined in the following subsection and, as explained below,
280 |
281 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
282 | transm_color = (transmission_depth == 0) ? transmission_color : 1
283 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
284 |
285 | The transmission closure `specular_btdf` shares many parameters with `specular_brdf`; for example, the roughness of `spec_btdf` is by default the same as **`specular_roughness`**. It can be additionally increased or decreased via the **`transmission_extra_roughness`** parameter, though this is not physically correct. Just like the specular BRDF, this BTDF can be modulated by a thin film by reusing the same parameters.
286 |
287 | If the **`thin_walled`** boolean parameter is `false`, then the surface is considered to be a boundary of a finite-sized solid object. Thus, light refracts when entering and leaving the object, according to the `specular_btdf` closure. If **`thin_walled`** is `true`, the surface is double-sided, representing an infinitely thin shell (such as an idealized tree leaf or paper), and light therefore does not undergo refraction upon specular transmission to the opposite side. In this case the refractive index is set to that of the surrounding medium (e.g. 1.0 for vacuum), and dispersion and thin film are disabled.
288 |
289 | We also allow specifying the properties of a homogeneous medium interior to the object, with or without scattering. This is useful for modeling a range of materials, ranging from clear or colored (absorbing-only) glass and liquids to materials with visually significant scattering such as honey, a deep body of water, opalescent glass, or milky glass. The **`transmission_color`** and **`transmission_depth`** parameter pair is a commonly used artist-friendly way to set the medium extinction coefficient, while **`transmission_scatter`** directly sets the medium scattering coefficient. When **`transmission_depth`** is zero, the interior medium is nil, and **`transmission_color`** is used to tint refraction multiplicatively by a constant amount, directly in the closure mixture (see above code snippet). When **`transmission_depth`** is positive, the tinting is governed by the interior medium via Beer's law.
290 |
291 | (###) Shader parameters: specular transmission
292 |
293 | Name | Type | Default | Description
294 | ---------------------------------------|---------|---------|------------
295 | **`transmission`*** | float | `0` | transmission weight
296 | **`transmission_color`*** | color | `1,1,1` | transmission color, i.e. tint
297 | **`transmission_depth`*** | float | `0` | the distance travelled inside the material by white light before its color becomes exactly **`transmission_color`** by Beer's law, determining the extinction coefficient of the interior medium; if zero, **`transmission_color`** acts as a constant (on-surface) transmission tint; range `[0,infinity)`
298 | **`transmission_scatter`*** | color | `0,0,0` | scattering coefficient of the interior medium
299 | **`transmission_scatter_anisotropy`*** | float | `0` | the anisotropy of the Henyey-Greenstein phase function of the interior medium; range `[-1,1]`
300 | **`transmission_dispersion`*** | float | `0` | dispersion Abbe number, describing how much the index of refraction varies across wavelengths
301 | **`transmission_extra_roughness`*** | float | `0` | additional (positive or negative) roughness on top of **`specular_roughness`**
302 | **`specular_roughness`** | float | `0.2` | refraction roughness of `specular_btdf`; squared internally before passed to the BTDF to achieve a more uniform roughness look over the parameter range `[0,1]`
303 | **`specular_IOR`** | float | `1.5` | refractive index of `specular_btdf`
304 | **`specular_anisotropy`*** | float | `0` | reflection anisotropy of `specular_btdf`; range `[0,1]`
305 | **`specular_rotation`*** | float | `0` | orientation of anisotropy; range `[0,1]` (where `1` means 360 degrees)
306 | **`thin_film_thickness`*** | float | `0` | thickness of the film
307 | **`thin_film_IOR`*** | float | `1.5` | refractive index of the film
308 | **`thin_walled`*** | boolean | `false` | if `true`, the object is considered infinitely thin and the surface double-sided
309 |
310 |   
311 |
312 | ![Figure [transmission]: The effect of **`transmission_scatter_anisotropy`**. From left to right: -0.5, 0.0, 0.5.](dummy)
313 |
314 |
315 |
316 | Sheen
317 | --------------------------------------------------------------------------------
318 |
319 | The `sheen_brdf` closure is a microfacet sheen BRDF based on that of Estevez and Kulla [#Estevez2017]. It simulates the look of textiles where the surface facets are cylindrical "fibres" oriented with axes primarily parallel to the surface normal, producing a specular highlight at grazing angles. Conceptually this lies on top of a base substrate, and thus the energy transmitted to the substrate is reduced by the sheen reflectance:
320 |
321 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
322 | sheen_layer = sheen * sheen_color * sheen_brdf(...) + (1 - sheen * reflectance(sheen_brdf)) * base_mix
323 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
324 |
325 | where the `base_mix` closure is defined below.
326 |
327 | (###) Shader parameters: sheen
328 |
329 | Name | Type | Default | Description
330 | -----------------------|-------|---------|------------
331 | **`sheen`*** | float | `0.8` | reflection weight of `sheen_brdf`
332 | **`sheen_color`*** | color | `1,1,1` | reflection color of `sheen_brdf`
333 | **`sheen_roughness`*** | float | `0.3` | reflection roughness of `sheen_brdf`; range `[0,1]`
334 |
335 |   
336 |
337 | ![Figure [sheen]: Various textiles rendered using the sheen closure.](dummy)
338 |
339 |
340 |
341 | Diffuse reflection
342 | --------------------------------------------------------------------------------
343 |
344 | The base substrate layer consists of a statistical mixture, according to the **`subsurface`** parameter, of an Oren-Nayar diffuse reflection component and a subsurface component:
345 |
346 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
347 | base_mix = (1 - subsurface) * base * base_color * diffuse_brdf(...) + subsurface * subsurface_mix
348 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
349 |
350 | where the `subsurface_mix` closure is defined below.
351 |
352 | (###) Shader parameters: diffuse reflection
353 |
354 | Name | Type | Default | Description
355 | -------------------------|-------|---------|------------
356 | **`base`** | float | `0.8` | reflection weight of `diffuse_brdf`
357 | **`base_color`** | color | `1,1,1` | reflection color of `diffuse_brdf`
358 | **`diffuse_roughness`*** | float | `0` | reflection roughness of `diffuse_brdf`
359 |
360 |
361 | Diffuse transmission
362 | --------------------------------------------------------------------------------
363 |
364 | The subsurface component degenerates to diffuse transmission if **`thin_walled`** is `true`. This represents an infinitely thin shell (for example an idealized piece of rough paper) through which energy is transmitted into a diffuse lobe.
365 |
366 | The diffuse transmission is modeled via a Oren-Nayar microfacet BRDF flipped about the shading normal to make it a BTDF:
367 |
368 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
369 | subsurface_mix = thin_walled * subsurface_color * diffuse_btdf(...) + (1 - thin_walled) * subsurface(...)
370 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
371 |
372 | where the `subsurface` closure is described below.
373 |
374 | (###) Shader parameters: diffuse transmission
375 |
376 | Name | Type | Default | Description
377 | -------------------------|-------|---------|------------
378 | **`subsurface`*** | float | `0` | diffuse transmission weight
379 | **`subsurface_color`*** | color | `1,1,1` | diffuse transmission color
380 | **`diffuse_roughness`*** | float | `0` | diffuse transmission roughness
381 |
382 |  
383 |
384 | ![Figure [thinwalled]: Opaque paper plane (left) vs diffuse transmission enabled via **`thin_walled`** (right).](dummy)
385 |
386 |
387 |
388 | Subsurface scattering
389 | --------------------------------------------------------------------------------
390 |
391 | For solid objects (for which **`thin_walled`** is `false`), subsurface scattering models the effect of light propagation and diffusion under the surface, where in general the exiting ray leaves at a different surface location than the incident ray. This effect is represented by the `subsurface` closure, for which we do not stipulate a specific rendering model to be used, e.g. based on diffusion-profile surface illumination blurring or brute-force subsurface ray tracing.
392 |
393 | (###) Shader parameters: subsurface scattering
394 |
395 | Name | Type | Default | Description
396 | -----------------------------|-------|---------|------------
397 | **`subsurface`*** | float | `0` | subsurface scattering weight
398 | **`subsurface_color`*** | color | `1,1,1` | subsurface color, used by `subsurface(...)` closure
399 | **`subsurface_radius`*** | color | `1,1,1` | subsurface radii (i.e. mean free paths) of the red, green, and blue channels
400 | **`subsurface_scale`*** | float | `1` | scalar scale for **`subsurface_radius`**
401 | **`subsurface_anisotropy`*** | float | `0` | anisotropy of the subsurface medium phase function; range `[-1,1]`
402 |
403 |   
404 |
405 | ![Figure [subsurface]: The effect of varying the subsurface scattering radius (**`subsurface_radius`**).](dummy)
406 |
407 |
408 |
409 | Discussion
410 | ================================================================================
411 |
412 | Having presented our proposed model, in this section we discuss some of the potential subtleties, caveats and areas for future improvement.
413 |
414 |
415 | Scalar vs. RGB closure weighting
416 | --------------------------------------------------------------------------------
417 |
418 | Consider our formula for the specular reflection layer, in which we have the closure combination:
419 |
420 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C
421 | specular_reflection_layer = specular * specular_color * specular_brdf(...) + (1 - specular_color * specular * reflectance(specular_brdf)) * transmission_sheen_mix
422 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423 |
424 | Here the **`specular_color`** factor multiplying `reflectance(specular_brdf)` is included to ensure energy _preservation_. For example, if the reflection is pure red, only the complementary cyan color is transmitted into the underlayer. This allows preventing the loss of energy in the combined model and creating multi-layer materials with high albedo. But while it is physically correct, it can also make it harder for an artist to control the appearance of a complementary color tint in the underlying lobes.
425 |
426 | An alternative approach we considered (used, e.g., in 3ds Max's Physical Material model), is to keep the multiplicative closure factors as scalars, e.g. in this case **`specular_color`** would be omitted from the closure weight. This then technically violates energy preservation (i.e. energy is unphysically dissipated) and makes it difficult to create high-albedo materials with colored specular reflection. However, such behavior can be more intuitive to artists.
427 |
428 | On balance we prefer the physically correct behaviour, however this is open to debate.
429 |
430 |
431 | Reciprocity
432 | --------------------------------------------------------------------------------
433 |
434 | A physically correct BSDF must satisfy reciprocity (i.e. symmetry under exchange of the incoming and outgoing directions). However, in our proposed model, even if the leaf-level BSDFs are reciprocal, the closure combination is *not*. This is due to the introduction of the `reflectance(...)` function which depends on the incoming direction only. This may present a problem if the shading model were to be incorporated in certain light transport algorithms, such as bidirectional path tracing, which typically rely on this property to hold.
435 |
436 | However, enforcing reciprocity would be likely to significantly complicate the mathematical form of our model, without producing a qualitatively better visual appearance. For many renderers, including Arnold -- a unidirectional path tracer, the physical constraint of reciprocity can be violated, even in the leaf BSDFs, without causing any real problems. Furthermore, enforcing reciprocity of a layered material in a truly physically correct manner [#Jakob2014] is currently too complicated and cumbersome to implement in a production renderer. Models in actual production use that achieve reciprocity, such as the coating scheme of Kulla and Estevez [#Kulla2017], do so by introducing drastic approximations with inaccuracy likely similar to the non-reciprocal approach described here.
437 |
438 | Therefore, for the time being we do not consider the incorporation of reciprocity in our model to be a strict necessity.
439 |
440 |
441 | Layering model
442 | --------------------------------------------------------------------------------
443 |
444 | Our layering model ensures energy conservation by construction, and attempts also to ensure energy preservation where possible. However, as a relatively simple model which is simply a linear combination of closures with weights adjusted according to an approximate `reflectance(...)` function, it is not a physically accurate simulation of the light transport in the layers that we describe.
445 |
446 | A number of more accurate treatments of the full light transport in layered media have appeared recently [#Jakob2014] [#Belcour2018] [#Zeltner2018]. These models incorporate the effect of the various modes of reflection and transmission through the whole stack of layers, which generates a final BSDF (or in general BSSRDF) which is not a simple linear combination of the per-layer BSDFs.
447 |
448 | In future, we would like to investigate transitioning to a more accurate model such as this. However, currently it seems all the available models are more expensive to compute and much more complex to implement.
449 |
450 | We attempt at least in our model to incorporate some of the most important effects which arise due to the inter-layer interaction by hand. For example, we allow the roughness of the coating to affect the roughness of (some of) the underlying layers.
451 |
452 |
453 | Surface orientation
454 | --------------------------------------------------------------------------------
455 |
456 | In transmissive situations, light may be incident from above or below the surface normal. The transmission layer is sensitive to this and ensures that light correctly refracts through the interface. However, the other layers are oriented w.r.t. the *facing* normal, so the scattering behavior is the same when objects are hit from outside and from inside. This again is a non-physical approximation, which is useful in practice as it simplifies the logic without introducing obvious visual artifacts.
457 |
458 |
459 | User-friendliness vs. flexibility
460 | --------------------------------------------------------------------------------
461 |
462 | Our model currently has a fixed number of layers, which includes only two specular layers, while some other popular models (for example, Pixar's PxrSurface [#Hery2017]) allow for a much more configurable number of layers. In a production context, this freedom to tweak the model to a fine degree can be useful in some situations.
463 |
464 | However, as mentioned earlier, our general philosophy here is that it is preferable to provide a relatively minimal set of user-friendly parameters with intuitive meanings, with a combination scheme which ensures that any given set of parameters is within the domain of physical plausibility. In those edge cases where the model cannot produce the desired result, a custom shader graph can be authored.
465 |
466 |
467 | Conclusion
468 | ================================================================================
469 |
470 | In this document we have described a proposal for a standard, generic surface shader for use in a wide variety of production rendering contexts. This model is based on the current implementation of the Standard Surface shader in the Arnold renderer. We described in detail the ten closures which comprise the model, and how they are combined to generate the final shader.
471 |
472 | We hope this proposal serves as a useful basis for a more widely adopted standard surface shader implementation.
473 |
474 |
475 | Acknowledgements
476 | ================================================================================
477 |
478 | The authors would like to thank Mike Farnsworth, Lee Griggs, Arvid Schneider, Milos Hasan, Michael Nickelsky, Henrik Edstrom, Karl Schmidt, Niklas Harrysson, Marcel Reinhard, and Davide Pesare for their useful input and feedback.
479 |
480 |
481 | Bibliography
482 | ================================================================================
483 |
484 | [#Andersson2016]: Zap Andersson. 2016. Physical Material (v1.01). Autodesk white paper.
485 |
486 | [#Belcour2017]: Laurent Belcour and Pascal Barla. 2017. A Practical Extension to Microfacet Theory for the Modeling of Varying Iridescence. *ACM Transactions on Graphics*, 36, 4.
487 |
488 | [#Belcour2018]: Laurent Belcour. 2018. Efficient Rendering of Layered Materials using an Atomic Decomposition with Statistical Operators. *ACM Transactions on Graphics*, 37, 4.
489 |
490 | [#Burley2012]: Brent Burley. 2016. Physically-based Shading at Disney. In *ACM SIGGRAPH 2012 Courses: Practical Physically Based Shading in Film and Game Production*.
491 |
492 | [#McDermott2018]: Wes McDermott. 2018. The PBR Guide. Allegorithmic. https://www.allegorithmic.com/pbr-guide.
493 |
494 | [#Estevez2017]: Alejandro Conty Estevez and Christopher Kulla. 2017. Production Friendly Microfacet Sheen BRDF. Sony Pictures Imageworks technical report.
495 |
496 | [#Georgiev2019]: Iliyan Georgiev, Jamie Portsmouth, Zap Andersson, Adrien Herubel, Alan King, Shinji Ogaki, Frederic Servant. 2019. Autodesk Standard Surface: reference implementations. https://github.com/Autodesk/standard-surface/blob/master/reference/.
497 |
498 | [#Gritz2010]: Larry Gritz, Clifford Stein, Chris Kulla, and Alejandro Conty. 2010. Open Shading Language. In *ACM SIGGRAPH 2010 Talks*.
499 |
500 | [#Gulbrandsen2014]: Ole Gulbrandsen. 2014. Artist Friendly Metallic Fresnel. *Journal of Computer Graphics Techniques*, 3, 4.
501 |
502 | [#Hery2017]: Christophe Hery, Ryusuke Villemin, Junyi Ling. 2017. Pixar's Foundation for Materials. Pixar technical report.
503 |
504 | [#Jakob2014]: Wenzel Jakob, Eugene d'Eon, Otto Jakob, and Steve Marschner. 2014. A Comprehensive Framework for Rendering Layered Materials. *ACM Transactions on Graphics*, 33, 4.
505 |
506 | [#Langlands2014]: Anders Langlands. 2014. Physically Based Shader Design in Arnold. In *ACM SIGGRAPH 2014 Talks*.
507 |
508 | [#Kulla2017]: Christopher Kulla and Alejandro Conty Estevez. 2017. Revisiting Physically Based Shading at Imageworks. In *ACM SIGGRAPH 2017 Courses: Physically Based Shading in Theory and Practice*.
509 |
510 | [#Zeltner2018]: Tizian Zeltner and Wenzel Jakob. 2018. The Layer Laboratory: A Calculus for Additive and Subtractive Composition of Anisotropic Surface Reflectance. *ACM Transactions on Graphics*, 37, 4.
511 |
512 |
513 | [^bsdf1]: For convenience, it is useful to allow our list of closures to not be strictly only BSDFs but also include an emission distribution function (EDF) and a bidirectional subsurface scattering distribution function (BSSRDF). The renderer is understood to recognize these and deal with them appropriately.
514 |
515 | [^bsdf2]: Or indeed EDF, or BSSRDF.
516 |
517 |
518 |
519 |
524 |
525 |
526 |
--------------------------------------------------------------------------------
/reference/standard_surface.mtlx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
8 |
10 |
12 |
13 |
14 |
15 |
17 |
19 |
21 |
23 |
25 |
27 |
29 |
31 |
33 |
35 |
37 |
39 |
41 |
43 |
45 |
47 |
49 |
51 |
53 |
55 |
57 |
59 |
61 |
63 |
65 |
67 |
69 |
71 |
73 |
75 |
77 |
79 |
81 |
83 |
85 |
87 |
89 |
91 |
93 |
95 |
97 |
99 |
100 |
101 |
102 |
106 |
107 |
108 |
109 |
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 |
--------------------------------------------------------------------------------
/reference/standard_surface.osl:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2019 Autodesk
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 | */
10 |
11 | // List of shader closures
12 | // TODO: Missing closures. Align names with what appears in paper
13 | closure color emission() [[ int builtin = 1 ]];
14 | closure color oren_nayar(normal N, float sigma) [[ int builtin = 1 ]];
15 | closure color sheen(normal N, float roughness) [[ int builtin = 1 ]];
16 | closure color translucent(normal N, float sigma) [[ int builtin = 1 ]];
17 | closure color microfacet(string distribution, normal N, vector U, float xalpha,
18 | float yalpha, float eta, int refract) [[ int builtin = 1 ]];
19 | closure color transparent() [[ int builtin = 1 ]];
20 | closure color bssrdf(vector mfp, color albedo, float g) [[ int builtin = 1 ]];
21 | closure color metal(string distribution, normal N, vector U,
22 | color n, color k, float xalpha, float yalpha) [[ int builtin = 1 ]];
23 |
24 | // List of shader parameters
25 | struct StandardSurfaceParameters
26 | {
27 | float base;
28 | color base_color;
29 | float diffuse_roughness;
30 | float specular;
31 | color specular_color;
32 | float specular_IOR;
33 | float metalness;
34 | float transmission;
35 | color transmission_color;
36 | float subsurface;
37 | color subsurface_color;
38 | color subsurface_radius;
39 | float subsurface_scale;
40 | float subsurface_anisotropy;
41 | float sheen;
42 | color sheen_color;
43 | float sheen_roughness;
44 | int thin_walled;
45 | vector input_normal;
46 | float coat;
47 | color coat_color;
48 | float coat_roughness;
49 | float coat_IOR;
50 | normal coat_normal;
51 | float coat_gamma;
52 | float emission;
53 | color emission_color;
54 | vector U;
55 | float rx;
56 | float ry;
57 | };
58 |
59 | float sqr(float x) { return x*x; }
60 |
61 | // approximates the reflectance of a specular BSDF
62 | // by computing the dielectric fresnel
63 | // at the surface normal
64 | float reflectance(normal n, float IOR)
65 | {
66 | float Kr, Kt;
67 | fresnel(I, n, 1 / IOR, Kr, Kt);
68 | return Kr;
69 | }
70 |
71 | // converts two colors to complex IOR
72 | void ArtisticToConductorFresnel(color reflectivity, color edgetint, output color n, output color k)
73 | {
74 | color r = clamp(reflectivity, color(0), color(0.99));
75 | color g = edgetint;
76 |
77 | color r_sqrt = sqrt(r);
78 | color n_min = (1 - r) / (1 + r);
79 | color n_max = (1 + r_sqrt) / (1 - r_sqrt);
80 |
81 | n = mix(n_max, n_min, g);
82 |
83 | color k2 = ((n + 1) * (n + 1) * r - (n - 1) * (n - 1)) / (1 - r);
84 | k2 = max(k2, 0);
85 | k = sqrt(k2);
86 | }
87 |
88 | closure color diffuse_layer(StandardSurfaceParameters p)
89 | {
90 | // TODO: use correct sheen reflectance
91 | return p.sheen * p.sheen_color * sheen(N, p.sheen_roughness) +
92 | (1 - p.sheen * reflectance(p.input_normal, p.specular_IOR)) *
93 | pow(p.base * p.base_color, p.coat_gamma) * oren_nayar(p.input_normal, p.diffuse_roughness);
94 | }
95 |
96 | closure color subsurface_layer(StandardSurfaceParameters p)
97 | {
98 | if (p.thin_walled)
99 | return pow(p.subsurface_color, p.coat_gamma) * translucent(p.input_normal,
100 | p.diffuse_roughness);
101 | else
102 | return bssrdf(vector(p.subsurface_scale * p.subsurface_radius),
103 | pow(p.subsurface_color, p.coat_gamma), p.subsurface_anisotropy);
104 | }
105 |
106 | closure color base_layer(StandardSurfaceParameters p)
107 | {
108 | return (1 - p.subsurface) * diffuse_layer(p) + p.subsurface * subsurface_layer(p);
109 | }
110 |
111 | closure color spec_trans_layer(StandardSurfaceParameters p)
112 | {
113 | float transmission_IOR = (p.thin_walled) ? 1 : max(p.specular_IOR, 1.e-04);
114 | // TODO: handle dispersion
115 | // TODO: handle absorption and interior closures
116 | // TODO: handle specular transmission thin film
117 | return p.transmission * p.transmission_color *
118 | microfacet("ggx", p.input_normal, p.U, p.rx, p.ry, transmission_IOR, 1) +
119 | (1 - p.transmission) * base_layer(p);
120 | }
121 |
122 | closure color spec_refl_layer(StandardSurfaceParameters p)
123 | {
124 | // TODO: handle handle specular reflection thin film
125 | // TODO: use correct microfacet reflectance
126 | return p.specular * p.specular_color *
127 | microfacet("ggx", p.input_normal, p.U, p.rx, p.ry, p.specular_IOR, 0) +
128 | (1 - p.specular * p.specular_color * reflectance(p.input_normal, p.specular_IOR)) *
129 | spec_trans_layer(p);
130 | }
131 |
132 | closure color metal_layer(StandardSurfaceParameters p)
133 | {
134 | color n, k;
135 | ArtisticToConductorFresnel(p.base_color, p.specular_color, n, k);
136 | return p.metalness * metal("ggx", p.input_normal, p.U, n, k, p.rx, p.ry) +
137 | (1 - p.metalness) * spec_refl_layer(p);
138 | }
139 |
140 | closure color emission_layer(StandardSurfaceParameters p)
141 | {
142 | return p.emission * p.emission_color * emission() + metal_layer(p);
143 | }
144 |
145 | closure color coat_layer(StandardSurfaceParameters p)
146 | {
147 | // TODO: use correct microfacet reflectance
148 | return
149 | p.coat *
150 | microfacet("ggx", p.coat_normal, p.U, p.coat_roughness, p.coat_roughness, p.coat_IOR, 0) +
151 | emission_layer(p) *
152 | mix(color(1), clamp(1 - reflectance(p.coat_normal, p.coat_IOR), 0, 1) * p.coat_color, p.coat);
153 | }
154 |
155 | shader standard_surface(
156 | float base = .8,
157 | color base_color = color(1),
158 | float diffuse_roughness = 0,
159 | float specular = 1,
160 | color specular_color = color(1),
161 | float specular_roughness = .1,
162 | float specular_IOR = 1.52,
163 | float specular_anisotropy = 0,
164 | float specular_rotation = 0,
165 | float metalness = 0,
166 | float transmission = 0,
167 | color transmission_color = color(1),
168 | float transmission_depth = 0,
169 | float transmission_scatter = 0,
170 | float transmission_scatter_anisotropy = 0,
171 | float transmission_dispersion = 0,
172 | float subsurface = 0,
173 | color subsurface_color = color(1),
174 | color subsurface_radius = color(1),
175 | float subsurface_scale = 1,
176 | float subsurface_anisotropy = 0,
177 | float sheen = 0,
178 | color sheen_color = color(1),
179 | float sheen_roughness = 0.3,
180 | int thin_walled = 0 [[ string widget = "boolean"]],
181 | normal input_normal = N,
182 | vector tangent = dPdu,
183 | float coat = 0,
184 | color coat_color = color(1),
185 | float coat_roughness = .1,
186 | float coat_IOR = 1.5,
187 | normal coat_normal = N,
188 | float coat_affect_color = 0,
189 | float coat_affect_roughness = 0,
190 | float thin_film_thickness = 0,
191 | float thin_film_IOR = 1.5,
192 | float emission_w = 0,
193 | color emission_color = color(1),
194 | color opacity = color(1),
195 | output closure color standard_surface_closures = 0)
196 | {
197 | StandardSurfaceParameters params;
198 | params.base = base;
199 | params.base_color = base_color;
200 | params.diffuse_roughness = diffuse_roughness;
201 | params.specular = specular;
202 | params.specular_color = specular_color;
203 | params.specular_IOR = specular_IOR;
204 | params.metalness = clamp(metalness, 0.0, 1.0);
205 | params.transmission = clamp(transmission, 0.0, 1.0);
206 | params.transmission_color = transmission_color;
207 | params.subsurface = clamp(subsurface, 0, 1);
208 | params.subsurface_color = subsurface_color;
209 | params.subsurface_radius = subsurface_radius;
210 | params.subsurface_scale = subsurface_scale;
211 | params.subsurface_anisotropy = subsurface_anisotropy;
212 | params.sheen = sheen;
213 | params.sheen_color = sheen_color;
214 | params.sheen_roughness = sheen_roughness;
215 | params.thin_walled = thin_walled;
216 | params.input_normal = input_normal;
217 | params.coat = clamp(coat, 0.0, 1.0);
218 | params.coat_color = coat_color;
219 | params.coat_roughness = sqr(coat_roughness);
220 | params.coat_IOR = coat_IOR;
221 | params.coat_normal = coat_normal;
222 | params.coat_gamma = clamp(coat, 0.0, 1.0) * coat_affect_color + 1;
223 | params.emission = emission_w;
224 | params.emission_color = emission_color;
225 |
226 | // specular roughness and anisotropy
227 | float specular_roughness_sqr = mix(sqr(specular_roughness), 1, params.coat *
228 | coat_affect_roughness * params.coat_roughness);
229 | params.U = normalize(tangent);
230 | if (specular_anisotropy != 0)
231 | {
232 | float aspect = sqrt(1 - clamp(specular_anisotropy, 0, 0.98));
233 | params.rx = min(specular_roughness_sqr / aspect, 1);
234 | params.ry = specular_roughness_sqr * aspect;
235 | float rot_angle = 2 * specular_rotation;
236 | if (rot_angle != 0.0)
237 | {
238 | vector V = normalize(cross(input_normal, params.U));
239 | float cos_rot_angle = cos(rot_angle * M_PI);
240 | float sin_rot_angle = sin(rot_angle * M_PI);
241 | params.U = cos_rot_angle * params.U - sin_rot_angle * V;
242 | }
243 | }
244 | else
245 | {
246 | params.rx = params.ry = specular_roughness_sqr;
247 | }
248 |
249 | standard_surface_closures += (color(1) - opacity) * transparent() + opacity * coat_layer(params);
250 | }
--------------------------------------------------------------------------------
/style/fonts/Artifakt/Artifakt Element Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/Artifakt/Artifakt Element Bold.woff2
--------------------------------------------------------------------------------
/style/fonts/Artifakt/Artifakt Element Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/Artifakt/Artifakt Element Medium.woff2
--------------------------------------------------------------------------------
/style/fonts/Artifakt/Artifakt Element Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/Artifakt/Artifakt Element Regular.woff2
--------------------------------------------------------------------------------
/style/fonts/Artifakt/Artifakt Legend Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/Artifakt/Artifakt Legend Bold.woff2
--------------------------------------------------------------------------------
/style/fonts/PTSerif/PTSerif-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/PTSerif/PTSerif-Bold.woff2
--------------------------------------------------------------------------------
/style/fonts/PTSerif/PTSerif-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/PTSerif/PTSerif-Italic.woff2
--------------------------------------------------------------------------------
/style/fonts/PTSerif/PTSerif-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/PTSerif/PTSerif-Regular.woff2
--------------------------------------------------------------------------------
/style/fonts/RobotoMono/RobotoMono-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/RobotoMono/RobotoMono-Bold.woff2
--------------------------------------------------------------------------------
/style/fonts/RobotoMono/RobotoMono-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Autodesk/standard-surface/34b1d5bd3a234c54354808d8308eb88409f5960c/style/fonts/RobotoMono/RobotoMono-Regular.woff2
--------------------------------------------------------------------------------
/style/style.css:
--------------------------------------------------------------------------------
1 | /******************************************************************************/
2 | /* Fonts
3 | /******************************************************************************/
4 |
5 | @font-face {
6 | font-family: 'Artifakt Legend';
7 | font-style: normal;
8 | font-weight: 700;
9 | src: url('fonts/Artifakt/Artifakt Legend Bold.woff2') format('woff2');
10 | }
11 |
12 | @font-face {
13 | font-family: 'Artifakt Element';
14 | font-style: normal;
15 | font-weight: 400;
16 | src: url('fonts/Artifakt/Artifakt Element Regular.woff2') format('woff2');
17 | }
18 |
19 | @font-face {
20 | font-family: 'Artifakt Element';
21 | font-style: normal;
22 | font-weight: 500;
23 | src: url('fonts/Artifakt/Artifakt Element Medium.woff2') format('woff2');
24 | }
25 |
26 | @font-face {
27 | font-family: 'Artifakt Element';
28 | font-style: normal;
29 | font-weight: 700;
30 | src: url('fonts/Artifakt/Artifakt Element Bold.woff2') format('woff2');
31 | }
32 |
33 | @font-face {
34 | font-family: 'Roboto Mono';
35 | font-style: normal;
36 | font-weight: 400;
37 | src: local('Roboto Mono'), local('RobotoMono-Regular'), url('fonts/RobotoMono/RobotoMono-Regular.woff2') format('woff2');
38 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; /* Latin */
39 | }
40 |
41 | @font-face {
42 | font-family: 'Roboto Mono';
43 | font-style: normal;
44 | font-weight: 700;
45 | src: local('Roboto Mono Bold'), local('RobotoMono-Bold'), url('fonts/RobotoMono/RobotoMono-Bold.woff2') format('woff2');
46 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; /* Latin */
47 | }
48 |
49 | @font-face {
50 | font-family: 'PT Serif';
51 | font-style: italic;
52 | font-weight: 400;
53 | src: local('PT Serif Italic'), local('PTSerif-Italic'), url('fonts/PTSerif/PTSerif-Italic.woff2') format('woff2');
54 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; /* Latin */
55 | }
56 |
57 | @font-face {
58 | font-family: 'PT Serif';
59 | font-style: normal;
60 | font-weight: 400;
61 | src: local('PT Serif'), local('PTSerif-Regular'), url('fonts/PTSerif/PTSerif-Regular.woff2') format('woff2');
62 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; /* Latin */
63 | }
64 |
65 | @font-face {
66 | font-family: 'PT Serif';
67 | font-style: normal;
68 | font-weight: 700;
69 | src: local('PT Serif Bold'), local('PTSerif-Bold'), url('fonts/PTSerif/PTSerif-Bold.woff2') format('woff2');
70 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; /* Latin */
71 | }
72 |
73 | /******************************************************************************/
74 | /* Document body
75 | /******************************************************************************/
76 |
77 | body
78 | {
79 | max-width: 800px;
80 | font-family: 'PT Serif', serif;
81 | padding: 70px 10px 0px 10px;
82 | min-width: 260px;
83 | font-size: 16px;
84 | line-height: 21px;
85 | color: black;
86 | }
87 |
88 | @media print
89 | {
90 | body
91 | {
92 | max-width: 100%;
93 | padding: 0 5%;
94 | }
95 | }
96 |
97 | /******************************************************************************/
98 | /* Table of contents
99 | /******************************************************************************/
100 |
101 | /* For screens wide enough, put on the right side */
102 | @media screen and (min-width: 1400px)
103 | {
104 | .md .longTOC, .md .mediumTOC, .md .shortTOC
105 | {
106 | max-width: 300px;
107 | right: 0em;
108 | display: block;
109 | position: fixed;
110 | top: 0;
111 | bottom: 0;
112 | overflow-y: scroll;
113 | margin-top: 0;
114 | margin-bottom: 0;
115 | padding: 1em 1em 0 0;
116 | font-size: 85%;
117 | line-height: 120%;
118 | border: 0;
119 | opacity: 0.66;
120 | font-family: 'Artifakt Element', sans-serif;
121 | }
122 |
123 | .md .longTOC a, .md .mediumTOC a, .md .shortTOC a
124 | {
125 | font-family: 'Artifakt Element', sans-serif;
126 | }
127 |
128 | .md .longTOC:hover, .md .mediumTOC:hover, .md .shortTOC:hover
129 | {
130 | opacity: 1;
131 | }
132 | }
133 |
134 | /* For narrow screens, make inline */
135 | @media screen and (max-width: 1399px)
136 | {
137 | .md .longTOC, .md .mediumTOC, .md .shortTOC
138 | {
139 | display: block;
140 | margin: 20px 0 40px 3px;
141 | padding: 0;
142 | padding-top: 13px;
143 | float: initial;
144 | font-size: 98%;
145 | line-height: 120%;
146 | border: 0;
147 | font-family: 'Artifakt Element', sans-serif;
148 | border-top: 1px solid rgba(0,0,0,.1);
149 | border-bottom: 1px solid rgba(0,0,0,.1);
150 | }
151 |
152 | .md .longTOC a, .md .mediumTOC a, .md .shortTOC a
153 | {
154 | font-family: 'Artifakt Element', sans-serif;
155 | }
156 | }
157 |
158 | /* For print, hide */
159 | @media print
160 | {
161 | .md .longTOC, .md .mediumTOC, .md .shortTOC
162 | {
163 | display: none;
164 | }
165 | }
166 |
167 | .md div.title
168 | {
169 | font-family: 'Artifakt Legend', sans-serif;
170 | font-weight: 700;
171 | border: 0;
172 | }
173 |
174 | contents, .md .tocHeader,
175 | .md h1, .md h2, .md h3, .md h4, .md h5, .md h6,
176 | .md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4, .md .nonumberh5, .md .nonumberh6
177 | {
178 | font-family: 'Artifakt Element', sans-serif;
179 | font-weight: 500;
180 | border: 0;
181 | }
182 |
183 | .md .tocHeader
184 | {
185 | margin: 0;
186 | padding: 0;
187 | border: none;
188 | font-size: inherit;
189 | }
190 |
191 | .md .longTOC p, .md .mediumTOC p, .md .shortTOC p
192 | {
193 | overflow: hidden;
194 | text-overflow: ellipsis;
195 | }
196 |
197 | .md .longTOC center, .md .mediumTOC center, .md .shortTOC center, .md .tocHeader
198 | {
199 | text-align: left;
200 | }
201 |
202 | .md .longTOC b, .md .mediumTOC b, .md .shortTOC b
203 | {
204 | font-weight: 500;
205 | font-size: 120%;
206 | }
207 |
208 | .md .longTOC a.level1, .md .mediumTOC a.level1, .md .shortTOC a.level1
209 | {
210 | display: inline-block;
211 | color: rgba(0,0,0,.95);
212 | font-weight: 500;
213 | margin-top: 7px;
214 | margin-bottom: 4px;
215 | }
216 |
217 | .md .longTOC a.level2, .md .mediumTOC a.level2, .md .shortTOC a.level2
218 | {
219 | color: rgba(0,0,0,.9);
220 | font-weight: 400;
221 | line-height: 130%;
222 | }
223 |
224 |
225 | /******************************************************************************/
226 | /* Titles and headings
227 | /******************************************************************************/
228 |
229 | /* Title style */
230 | .md div.title
231 | {
232 | color: rgba(0,0,0,.7);
233 | margin: 0.4em 0 20px 0;
234 | padding: 0;
235 | font-size: 230%;
236 | font-weight: 700;
237 | text-align: center;
238 | }
239 |
240 | /* Subtitle style */
241 | .md div.subtitle
242 | {
243 | text-align: center;
244 | font-size: 95%;
245 | }
246 |
247 | /* Blue sections */
248 | .md h1, .md .nonumberh1
249 | {
250 | font-size: 150%;
251 | color: #029be5;
252 | }
253 |
254 | /* Grey sub-sections */
255 | .md h2, .md .nonumberh2, .md h3, .md .nonumberh3
256 | {
257 | font-size: 130%;
258 | color: rgba(0,0,0,.7);
259 | }
260 |
261 | .md h3, .md .nonumberh3
262 | {
263 | font-size: 115%;
264 | margin-bottom: 0;
265 | color: rgba(0,0,0,.75);
266 | }
267 |
268 | /******************************************************************************/
269 | /* Tables
270 | /******************************************************************************/
271 |
272 | .md table.table
273 | {
274 | font-size: 90%;
275 | width: 100%;
276 | border: 1px solid rgb(230, 230, 230);
277 | }
278 |
279 | .md table.table td
280 | {
281 | border: none;
282 | padding: 7px 7px 7px 7px;
283 | }
284 |
285 | /* Header row */
286 | .md table.table th
287 | {
288 | border: none;
289 | background-color: rgb(230, 230, 230);
290 | color: black;
291 | font-weight: 700;
292 | font-family: 'Artifakt Element', sans-serif;
293 | padding: 7px 7px 7px 7px;
294 | }
295 |
296 | /* Even table rows: 1, 3, ... */
297 | .md table.table tr:nth-child(odd)
298 | {
299 | background-color: rgb(247,247,247);
300 | }
301 |
302 | /* Odd table rows: 2, 4, ... */
303 | .md table.table tr:nth-child(even)
304 | {
305 | background-color: rgb(253, 253, 253);
306 | }
307 |
308 | .md table.table tr:hover
309 | {
310 | background-color: #f9f5d7;
311 | }
312 |
313 |
314 | /******************************************************************************/
315 | /* Links
316 | /******************************************************************************/
317 |
318 | .md a
319 | {
320 | font-family: 'PT Serif';
321 | }
322 |
323 | .md a:link, .md a:visited
324 | {
325 | color: #0085c7;
326 | }
327 |
328 | /* For print, make links black */
329 | @media print
330 | {
331 | .md a:link, .md a:visited
332 | {
333 | color: black;
334 | }
335 | }
336 |
337 | /******************************************************************************/
338 | /* Misc
339 | /******************************************************************************/
340 |
341 | /* Code */
342 | .md code
343 | {
344 | padding: 0;
345 | border: none;
346 | font-family: 'Roboto Mono', monospace;
347 | font-size: 92%;
348 | }
349 | .md pre.listing
350 | {
351 | background-color: transparent;
352 | font-size: 93%;
353 | background-color: rgb(250,250,250);
354 | border: 1px solid rgba(0,0,0,.05);
355 | padding: 6px 10px;
356 | text-align: left;
357 | }
358 |
359 | /* Bibliography */
360 | .md .bib
361 | {
362 | font-size: 90%;
363 | padding-left: 20px;
364 | text-indent: -20px;
365 | }
366 | .md .bib b
367 | {
368 | font-weight: inherit;
369 | font-style: italic;
370 | }
371 |
372 | hr.pagebreak
373 | {
374 | visibility: hidden;
375 | }
376 |
377 | .afterTitles
378 | {
379 | height: 50px !important;
380 | }
381 |
382 | /* Center short image captions */
383 | .md div.table
384 | {
385 | margin: 0 0 30px 0;
386 | }
387 |
388 | .md div.tablecaption
389 | {
390 | text-align: justify;
391 | }
392 |
393 | /* Center short image captions */
394 | .md div.imagecaption
395 | {
396 | display: inline-block;
397 | margin: 7px 0 0 0;
398 | }
399 |
400 | .md img.markdeep
401 | {
402 | margin-top: 25px;
403 | }
404 |
405 | .md .subtitle img.markdeep
406 | {
407 | margin-top: 7px;
408 | }
409 |
410 | .md .imagecaption b
411 | {
412 | font-weight: 700;
413 | color: rgba(0,0,0,.85);
414 | }
415 |
416 | /* Hack to place a caption below a table of images */
417 | .shifted-caption
418 | {
419 | margin-top: -30px;
420 | text-align: center;
421 | }
422 | .shifted-caption .image
423 | {
424 | float: initial !important;
425 | margin: 0 !important;
426 | }
427 | .shifted-caption img
428 | {
429 | display: none;
430 | }
431 |
432 | .markdeepFooter
433 | {
434 | opacity: 0.4;
435 | }
436 |
437 | .md code .long
438 | {
439 | font-size: 88%;
440 | }
441 |
442 | /* For print, hide Markdeep footer */
443 | @media print
444 | {
445 | .markdeepFooter
446 | {
447 | display: none;
448 | }
449 | }
--------------------------------------------------------------------------------