Skip to content

Commit 3cddebc

Browse files
author
Mike Bond
committed
Add coat_darkening to OpenPBR
1 parent 52448cd commit 3cddebc

18 files changed

+180
-11
lines changed

packages/dev/core/src/Materials/PBR/openPbrMaterial.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,28 @@ export class OpenPBRMaterial extends OpenPBRMaterialBase {
613613
// eslint-disable-next-line @typescript-eslint/no-unused-vars
614614
private _coatIor: Property<number> = new Property<number>("coat_ior", 1.5, "vCoatIor", 1, 0);
615615

616+
/**
617+
* Defines the amount that interreflections within the coat allow the underlying surface
618+
* to be darkened. A value of 1.0 means that the physically correct amount of darkening
619+
* is applied, while a value of 0.0 means that no darkening is applied.
620+
* See OpenPBR's specs for coat_darkening
621+
*/
622+
public coatDarkening: number;
623+
@addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "coatDarkening")
624+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
625+
private _coatDarkening: Property<number> = new Property<number>("coat_darkening", 0.0, "vCoatDarkening", 1, 0);
626+
627+
/**
628+
* Defines the amount that interreflections within the coat allow the underlying surface
629+
* to be darkened. A value of 1.0 means that the physically correct amount of darkening
630+
* is applied, while a value of 0.0 means that no darkening is applied.
631+
* See OpenPBR's specs for coat_darkening
632+
*/
633+
public coatDarkeningTexture: Nullable<BaseTexture>;
634+
@addAccessorsForMaterialProperty("_markAllSubMeshesAsTexturesDirty", "coatDarkeningTexture")
635+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
636+
private _coatDarkeningTexture: Sampler = new Sampler("coat_darkening", "coatDarkening", "COAT_DARKENING");
637+
616638
/**
617639
* Specifies whether the coat roughness is taken from the
618640
* same texture as the coat_weight.

packages/dev/core/src/Shaders/ShadersInclude/openpbrCoatLayerData.fx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ coat_weight = vCoatWeight;
3535
coat_roughness = vCoatRoughness;
3636
// coat_roughness_anisotropy = vCoatRoughnessAnisotropy;
3737
coat_ior = vCoatIor;
38-
// coat_darkening = vCoatDarkening;
38+
coat_darkening = vCoatDarkening;
3939

4040
// Apply texture values to coat layer properties
4141
#ifdef COAT_WEIGHT

packages/dev/core/src/Shaders/ShadersInclude/openpbrDirectLighting.fx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,35 @@
8282
}
8383
#endif
8484

85+
vec3 coatAbsorption = vec3(1.0);
86+
if (coat_weight > 0.0) {
87+
// __________ Coat Darkening _____________
88+
float cosTheta_view = max(preInfoCoat{X}.NdotV, 0.001);
89+
float cosTheta_light = max(preInfoCoat{X}.NdotL, 0.001);
90+
91+
// Fresnel reflectance for view direction
92+
float fresnel_view = coatReflectance.F0 + (1.0 - coatReflectance.F0) * pow(1.0 - cosTheta_view, 5.0);
93+
94+
// Fresnel reflectance for light direction
95+
float fresnel_light = coatReflectance.F0 + (1.0 - coatReflectance.F0) * pow(1.0 - cosTheta_light, 5.0);
96+
97+
// Average reflectance for the round trip (light in, view out)
98+
float averageReflectance = (fresnel_view + fresnel_light) * 0.5;
99+
100+
// Calculate transmission through multiple internal reflections
101+
// This uses the geometric series for infinite reflections:
102+
// T = (1-R) / (1 + R + R² + R³ + ...) = (1-R) / (1/(1-R)) = (1-R)²
103+
float effectiveReflectance = averageReflectance * coat_weight;
104+
float transmission = (1.0 - effectiveReflectance) / (1.0 + effectiveReflectance);
105+
coatAbsorption = coat_color * mix(1.0, transmission, coat_darkening);
106+
}
107+
85108
slab_diffuse *= base_color.rgb;
86109
vec3 material_opaque_base = mix(slab_diffuse, slab_subsurface, subsurface_weight);
87110
vec3 material_dielectric_base = mix(material_opaque_base, slab_translucent, transmission_weight);
88111
vec3 material_dielectric_gloss = layer(material_dielectric_base, slab_glossy, specularFresnel, vec3(1.0), specular_color);
89112
vec3 material_base_substrate = mix(material_dielectric_gloss, slab_metal, base_metalness);
90-
vec3 material_coated_base = layer(material_base_substrate, slab_coat, coatFresnel, coat_color, vec3(1.0));
113+
vec3 material_coated_base = layer(material_base_substrate, slab_coat, coatFresnel, coatAbsorption, vec3(1.0));
91114
material_surface_direct += mix(material_coated_base, slab_fuzz, fuzz_weight);
92115
}
93116
#endif

packages/dev/core/src/Shaders/ShadersInclude/openpbrEnvironmentLighting.fx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,28 @@
104104
slab_metal_ibl = baseSpecularEnvironmentLight * conductorIblFresnel * vLightingIntensity.z;
105105

106106
// _____________________________ Coat Layer IBL _____________________________
107+
// We will use this absorption value to darken the underlying layers. It includes both the
108+
// abosorption of the coat layer and the darkening due to internal reflections.
109+
vec3 coatAbsorption = vec3(1.0);
107110
if (coat_weight > 0.0) {
108111
slab_coat_ibl = coatEnvironmentLight * vLightingIntensity.z;
112+
113+
// __________ Coat Darkening _____________
114+
// Hemisphere-averaged Fresnel (empirical approximation)
115+
float hemisphere_avg_fresnel = coatReflectance.F0 + 0.5 * (1.0 - coatReflectance.F0);
116+
float averageReflectance = (coatIblFresnel + hemisphere_avg_fresnel) * 0.5;
117+
118+
// Account for roughness - rougher surfaces have more diffuse internal reflections
119+
// This reduces the darkening effect as roughness increases
120+
float roughnessFactor = 1.0 - coat_roughness * 0.5;
121+
averageReflectance *= roughnessFactor;
122+
123+
// Calculate transmission through multiple internal reflections
124+
// This uses the geometric series for infinite reflections:
125+
// T = (1-R) / (1 + R + R² + R³ + ...) = (1-R) / (1/(1-R)) = (1-R)²
126+
float effectiveReflectance = averageReflectance * coat_weight;
127+
float transmission = (1.0 - effectiveReflectance) / (1.0 + effectiveReflectance);
128+
coatAbsorption = coat_color * mix(1.0, transmission, coat_darkening);
109129
}
110130

111131
// TEMP
@@ -121,7 +141,7 @@
121141
vec3 material_dielectric_base_ibl = mix(material_opaque_base_ibl, slab_translucent_base_ibl, transmission_weight);
122142
vec3 material_dielectric_gloss_ibl = layer(material_dielectric_base_ibl, slab_glossy_ibl, dielectricIblFresnel, vec3(1.0), specular_color);
123143
vec3 material_base_substrate_ibl = mix(material_dielectric_gloss_ibl, slab_metal_ibl, base_metalness);
124-
vec3 material_coated_base_ibl = layer(material_base_substrate_ibl, slab_coat_ibl, coatIblFresnel, coat_color, vec3(1.0));
144+
vec3 material_coated_base_ibl = layer(material_base_substrate_ibl, slab_coat_ibl, coatIblFresnel, coatAbsorption, vec3(1.0));
125145
material_surface_ibl = mix(material_coated_base_ibl, slab_fuzz_ibl, fuzz_weight);
126146

127147
#endif

packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentDeclaration.fx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ uniform float vCoatWeight;
99
uniform vec3 vCoatColor;
1010
uniform float vCoatRoughness;
1111
uniform float vCoatIor;
12+
uniform float vCoatDarkening;
1213
uniform vec3 vEmissionColor;
1314

1415
// CUSTOM CONTROLS
@@ -57,6 +58,10 @@ uniform vec2 vBaseMetalRoughInfos;
5758
uniform vec2 vCoatWeightInfos;
5859
#endif
5960

61+
#ifdef COAT_DARKENING
62+
uniform vec2 vCoatDarkeningInfos;
63+
#endif
64+
6065
// Refraction Reflection
6166
#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(SS_REFRACTION) || defined(PREPASS)
6267
uniform mat4 view;

packages/dev/core/src/Shaders/ShadersInclude/openpbrFragmentSamplersDeclaration.fx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include<samplerFragmentDeclaration>(_DEFINENAME_,COAT_WEIGHT,_VARYINGNAME_,CoatWeight,_SAMPLERNAME_,coatWeight)
88
#include<samplerFragmentDeclaration>(_DEFINENAME_,COAT_COLOR,_VARYINGNAME_,CoatColor,_SAMPLERNAME_,coatColor)
99
#include<samplerFragmentDeclaration>(_DEFINENAME_,COAT_ROUGHNESS,_VARYINGNAME_,CoatRoughness,_SAMPLERNAME_,coatRoughness)
10+
// #include<samplerFragmentDeclaration>(_DEFINENAME_,COAT_ROUGHNESS_ANISOTROPY,_VARYINGNAME_,CoatRoughnessAnisotropy,_SAMPLERNAME_,coatRoughnessAnisotropy)
11+
#include <samplerFragmentDeclaration>(_DEFINENAME_,COAT_DARKENING,_VARYINGNAME_,CoatDarkening,_SAMPLERNAME_,coatDarkening)
1012
#include<samplerFragmentDeclaration>(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_SAMPLERNAME_,geometryOpacity)
1113
#include<samplerFragmentDeclaration>(_DEFINENAME_,EMISSION_COLOR,_VARYINGNAME_,EmissionColor,_SAMPLERNAME_,emissionColor)
1214

packages/dev/core/src/Shaders/ShadersInclude/openpbrUboDeclaration.fx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ uniform Material {
6969
vec3 vCoatColor;
7070
float vCoatRoughness;
7171
float vCoatIor;
72+
float vCoatDarkening;
7273
vec3 vEmissionColor;
7374

7475
vec2 vBaseWeightInfos;
@@ -89,6 +90,8 @@ uniform Material {
8990
mat4 coatColorMatrix;
9091
vec2 vCoatRoughnessInfos;
9192
mat4 coatRoughnessMatrix;
93+
vec2 vCoatDarkeningInfos;
94+
mat4 coatDarkeningMatrix;
9295
vec2 vGeometryNormalInfos;
9396
mat4 geometryNormalMatrix;
9497
vec2 vGeometryCoatNormalInfos;

packages/dev/core/src/Shaders/ShadersInclude/openpbrVertexDeclaration.fx

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,6 @@ uniform mat4 baseDiffuseRoughnessMatrix;
2121
uniform vec2 vBaseDiffuseRoughnessInfos;
2222
#endif
2323

24-
#ifdef GEOMETRY_OPACITY
25-
uniform mat4 geometryOpacityMatrix;
26-
uniform vec2 vGeometryOpacityInfos;
27-
#endif
28-
2924
#ifdef AMBIENT_OCCLUSION
3025
uniform vec2 vAmbientOcclusionInfos;
3126
uniform mat4 ambientOcclusionMatrix;
@@ -56,6 +51,36 @@ uniform vec2 vSpecularColorInfos;
5651
uniform mat4 specularColorMatrix;
5752
#endif
5853

54+
#ifdef COAT_WEIGHT
55+
uniform vec2 vCoatWeightInfos;
56+
uniform mat4 coatWeightMatrix;
57+
#endif
58+
59+
#ifdef COAT_COLOR
60+
uniform vec2 vCoatColorInfos;
61+
uniform mat4 coatColorMatrix;
62+
#endif
63+
64+
#ifdef COAT_ROUGHNESS
65+
uniform vec2 vCoatRoughnessInfos;
66+
uniform mat4 coatRoughnessMatrix;
67+
#endif
68+
69+
#ifdef COAT_ROUGHNESS_ANISOTROPY
70+
uniform vec2 vCoatRoughnessAnisotropyInfos;
71+
uniform mat4 coatRoughnessAnisotropyMatrix;
72+
#endif
73+
74+
#ifdef COAT_IOR
75+
uniform vec2 vCoatIorInfos;
76+
uniform mat4 coatIorMatrix;
77+
#endif
78+
79+
#ifdef COAT_DARKENING
80+
uniform vec2 vCoatDarkeningInfos;
81+
uniform mat4 coatDarkeningMatrix;
82+
#endif
83+
5984
#ifdef GEOMETRY_NORMAL
6085
uniform vec2 vGeometryNormalInfos;
6186
uniform mat4 geometryNormalMatrix;
@@ -66,6 +91,11 @@ uniform vec2 vGeometryCoatNormalInfos;
6691
uniform mat4 geometryCoatNormalMatrix;
6792
#endif
6893

94+
#ifdef GEOMETRY_OPACITY
95+
uniform mat4 geometryOpacityMatrix;
96+
uniform vec2 vGeometryOpacityInfos;
97+
#endif
98+
6999
#ifdef POINTSIZE
70100
uniform float pointSize;
71101
#endif

packages/dev/core/src/Shaders/openpbr.vertex.fx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ attribute vec4 color;
4242
#include<samplerVertexDeclaration>(_DEFINENAME_,COAT_WEIGHT,_VARYINGNAME_,CoatWeight)
4343
#include<samplerVertexDeclaration>(_DEFINENAME_,COAT_COLOR,_VARYINGNAME_,CoatColor)
4444
#include<samplerVertexDeclaration>(_DEFINENAME_,COAT_ROUGHNESS,_VARYINGNAME_,CoatRoughness)
45+
// #include<samplerVertexDeclaration>(_DEFINENAME_,COAT_ROUGHNESS_ANISOTROPY,_VARYINGNAME_,CoatRoughnessAnisotropy)
46+
#include<samplerVertexDeclaration>(_DEFINENAME_,COAT_DARKENING,_VARYINGNAME_,CoatDarkening)
4547
#include<samplerVertexDeclaration>(_DEFINENAME_,GEOMETRY_NORMAL,_VARYINGNAME_,GeometryNormal)
4648
#include<samplerVertexDeclaration>(_DEFINENAME_,GEOMETRY_COAT_NORMAL,_VARYINGNAME_,GeometryCoatNormal)
4749
#include<samplerVertexDeclaration>(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity)
@@ -224,6 +226,8 @@ void main(void) {
224226
#include<samplerVertexImplementation>(_DEFINENAME_,COAT_WEIGHT,_VARYINGNAME_,CoatWeight,_MATRIXNAME_,coatWeight,_INFONAME_,CoatWeightInfos.x)
225227
#include<samplerVertexImplementation>(_DEFINENAME_,COAT_COLOR,_VARYINGNAME_,CoatColor,_MATRIXNAME_,coatColor,_INFONAME_,CoatColorInfos.x)
226228
#include<samplerVertexImplementation>(_DEFINENAME_,COAT_ROUGHNESS,_VARYINGNAME_,CoatRoughness,_MATRIXNAME_,coatRoughness,_INFONAME_,CoatRoughnessInfos.x)
229+
// #include<samplerVertexImplementation>(_DEFINENAME_,COAT_ROUGHNESS_ANISOTROPY,_VARYINGNAME_,CoatRoughnessAnisotropy,_MATRIXNAME_,coatRoughnessAnisotropy,_INFONAME_,CoatRoughnessAnisotropyInfos.x)
230+
#include<samplerVertexImplementation>(_DEFINENAME_,COAT_DARKENING,_VARYINGNAME_,CoatDarkening,_MATRIXNAME_,coatDarkening,_INFONAME_,CoatDarkeningInfos.x)
227231
#include<samplerVertexImplementation>(_DEFINENAME_,GEOMETRY_NORMAL,_VARYINGNAME_,GeometryNormal,_MATRIXNAME_,geometryNormal,_INFONAME_,GeometryNormalInfos.x)
228232
#include<samplerVertexImplementation>(_DEFINENAME_,GEOMETRY_COAT_NORMAL,_VARYINGNAME_,GeometryCoatNormal,_MATRIXNAME_,geometryCoatNormal,_INFONAME_,GeometryCoatNormalInfos.x)
229233
#include<samplerVertexImplementation>(_DEFINENAME_,GEOMETRY_OPACITY,_VARYINGNAME_,GeometryOpacity,_MATRIXNAME_,geometryOpacity,_INFONAME_,GeometryOpacityInfos.x)

packages/dev/core/src/ShadersWGSL/ShadersInclude/openpbrCoatLayerData.fx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ coat_weight = uniforms.vCoatWeight;
3535
coat_roughness = uniforms.vCoatRoughness;
3636
// coat_roughness_anisotropy = uniforms.vCoatRoughnessAnisotropy;
3737
coat_ior = uniforms.vCoatIor;
38-
// coat_darkening = uniforms.vCoatDarkening;
38+
coat_darkening = uniforms.vCoatDarkening;
3939

4040
// Apply texture values to coat layer properties
4141
#ifdef COAT_WEIGHT

0 commit comments

Comments
 (0)