Skip to content

Commit

Permalink
Separate extension into normative and non-normative parts.
Browse files Browse the repository at this point in the history
  • Loading branch information
proog128 committed Mar 18, 2020
1 parent abd0e4e commit 0cbbc72
Showing 1 changed file with 46 additions and 12 deletions.
58 changes: 46 additions & 12 deletions extensions/2.0/Khronos/KHR_materials_clearcoat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,63 @@ All implementations should use the same calculations for the BRDF inputs. Implem
|**clearcoatRoughnessFactor** | `number` | The clearcoat layer roughness. | No, default: `0.0` |
|**clearcoatRoughnessTexture** | [`textureInfo`](/specification/2.0/README.md#reference-textureInfo) | The clearcoat layer roughness texture. | No |
|**clearcoatNormalTexture** | [`normalTextureInfo`](/specification/2.0/README.md#reference-normaltextureinfo) | The clearcoat normal map texture. | No |

The clearcoat formula `f_clearcoat` is computed using the specular term from the glTF 2.0 Metallic-Roughness material, defined in [Appendix B](/specification/2.0/README.md#appendix-b-brdf-implementation). Use specular F0 equal `0.04`, base color black `0.0, 0.0, 0.0`, metallic value `0.0`, and the clearcoat roughness value defined in this extension as follows:

```
clearcoatRoughness = clearcoatRoughnessFactor * clearcoatRoughnessTexture.g
```
The clearcoat layer is applied on top of the metallic-roughness material including emission and all extensions as follows, resulting in the coated material.

The following abstract code describes how the base and clearcoat layers should be blended together:

```
clearcoatBlendFactor = clearcoatTexture.r * clearcoatFactor
clearcoatFresnel = fresnel(0.04, NdotV)
color = (f_emissive + f_diffuse + f_specular) * (1.0 - clearcoatBlendFactor * clearcoatFresnel) +
f_clearcoat * clearcoatBlendFactor
coated_material = fresnel_coat(
layer = clearcoat_brdf,
base = material,
ior = 1.5,
weight = clearcoatTexture.r * clearcoatFactor,
normal = clearcoatNormalTexture)
material = mix(dielectric_brdf, metal_brdf, metallic) # from glTF 2.0 Metallic-Roughness material (core)
clearcoat_brdf = specular_brdf((clearcoatRoughnessFactor * clearcoatRoughnessTexture.g)^2)
```

The `fresnel_coat` operator adds a BRDF as a layer on top of another BSDF according to `weight` and a Fresnel term. The layer is weighted with `weight*fresnel(ior)`. The base is weighted with `1-(weight*fresnel(ior)`. `normal` is a float3 vector that affects the top layer, but not the base. The index of refraction is set to a fixed value of 1.5, corresponding to a F0 value of 0.04. The clearcoat effect is modeled via a microfacet-based BRDF. Similar to the specular component of the base material, the roughness `clearcoatRoughness` is squared to make it perceptually linear.

If `clearcoatFactor` (in the extension) is zero, the whole clearcoat layer is disabled.

The values for clearcoat layer intensity and clearcoat roughness can be defined using factors, textures, or both. If the `clearcoatTexture` or `clearcoatRoughnessTexture` is not given, respective texture components are assumed to have a value of 1.0. All clearcoat textures contain RGB components in linear space. If both factors and textures are present, the factor value acts as a linear multiplier for the corresponding texture values.

If `clearcoatNormalTexture` is not given, no normal mapping is applied to the clear coat layer, even if normal mapping is applied to the base material. Otherwise, `clearcoatNormalTexture` may be a reference to the same normal map used by the base material, or any other compatible normal map.

## Implementation

**This section is non-normative.**

The reflection at the coating layer is modeled as a microfacet BRDF with GGX distribution and Smith height-correlated masking-shadowing term ([Heitz 2014: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs](http://jcgt.org/published/0003/02/03/paper.pdf)).

```
1 alpha^2
D = -- --------------------------------
pi (HdotN^2 * (alpha^2-1) + 1)^2
2 * NdotV * NdotL
G = ----------------------------------------------------------------------------------------------
NdotL * sqrt(NdotV^2 * (1-alpha^2) + alpha^2) + NdotV * sqrt(NdotL^2 * (1-alpha^2) + alpha^2))
G * D
microfacet_brdf = --------------------
4 * NdotL * NdotV
clearcoat_brdf = microfacet_brdf(alpha)
```

Light that is not reflected by the clearcoat BRDF is transmitted through the coating layer to the underlying material. The ratio of reflection to transmission is given by the Fresnel term. For an index of refraction of 1.5 Schlick's approximation is accurate and a lot easier to compute than the full Fresnel equations. Using the half vector `H = normalize(V+L)` the mixing is given as follows:

```
fresnel(cosTheta) = 0.04 + 0.96 * (1 - cosTheta)^5
clearcoat_brdf * clearcoat * fresnel(HdotV) + material * (1 - clearcoat * max(fresnel(VdotN), fresnel(LdotN)))
```

Note that this simple model ignores effects like internal reflection, absorption, and thin-film interference.

In some rendering algorithms it may be hard to use `LdotN` in the base layer weight. In this case, the term may be omitted, violating the reciprocity principle.

## Schema

- [glTF.KHR_materials_clearcoat.schema.json](schema/glTF.KHR_materials_clearcoat.schema.json)
Expand Down

0 comments on commit 0cbbc72

Please sign in to comment.