Skip to content

Commit 61399a0

Browse files
author
Mike Bond
committed
Refactoring OpenPBR analytic light shaders
1 parent 6a284da commit 61399a0

18 files changed

+228
-184
lines changed

packages/dev/core/src/Rendering/IBLShadows/iblShadowsPluginMaterial.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,22 +163,22 @@ export class IBLShadowsPluginMaterial extends MaterialPluginBase {
163163
`;
164164
} else if (this._material instanceof OpenPBRMaterial) {
165165
// eslint-disable-next-line @typescript-eslint/naming-convention
166-
frag["CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION"] = `
166+
frag["CUSTOM_FRAGMENT_BEFORE_IBLLAYERCOMPOSITION"] = `
167167
#ifdef RENDER_WITH_IBL_SHADOWS
168168
#ifndef UNLIT
169169
#ifdef REFLECTION
170170
#ifdef COLORED_IBL_SHADOWS
171171
var shadowValue: vec3f = computeIndirectShadow();
172-
slab_diffuse *= shadowValue;
173-
slab_glossy *= mix(vec3f(1.0), shadowValue, specularAlphaG);
172+
slab_diffuse_ibl *= shadowValue;
173+
slab_glossy_ibl *= mix(vec3f(1.0), shadowValue, specularAlphaG);
174174
#else
175175
var shadowValue: vec2f = computeIndirectShadow();
176-
slab_diffuse *= vec3f(shadowValue.x);
177-
slab_glossy *= vec3f(mix(pow(shadowValue.y, 4.0), shadowValue.x, specularAlphaG));
176+
slab_diffuse_ibl *= vec3f(shadowValue.x);
177+
slab_glossy_ibl *= vec3f(mix(pow(shadowValue.y, 4.0), shadowValue.x, specularAlphaG));
178178
#endif
179179
#endif
180180
#else
181-
slab_diffuse *= computeIndirectShadow().x;
181+
slab_diffuse_ibl *= computeIndirectShadow().x;
182182
#endif
183183
#endif
184184
`;
@@ -241,22 +241,22 @@ export class IBLShadowsPluginMaterial extends MaterialPluginBase {
241241
`;
242242
} else if (this._material instanceof OpenPBRMaterial) {
243243
// eslint-disable-next-line @typescript-eslint/naming-convention
244-
frag["CUSTOM_FRAGMENT_BEFORE_FINALCOLORCOMPOSITION"] = `
244+
frag["CUSTOM_FRAGMENT_BEFORE_IBLLAYERCOMPOSITION"] = `
245245
#ifdef RENDER_WITH_IBL_SHADOWS
246246
#ifndef UNLIT
247247
#ifdef REFLECTION
248248
#ifdef COLORED_IBL_SHADOWS
249249
vec3 shadowValue = computeIndirectShadow();
250-
slab_diffuse.rgb *= shadowValue.rgb;
251-
slab_glossy *= mix(vec3(1.0), shadowValue.rgb, specularAlphaG);
250+
slab_diffuse_ibl.rgb *= shadowValue.rgb;
251+
slab_glossy_ibl *= mix(vec3(1.0), shadowValue.rgb, specularAlphaG);
252252
#else
253253
vec2 shadowValue = computeIndirectShadow();
254-
slab_diffuse *= shadowValue.x;
255-
slab_glossy *= mix(pow(shadowValue.y, 4.0), shadowValue.x, specularAlphaG);
254+
slab_diffuse_ibl *= shadowValue.x;
255+
slab_glossy_ibl *= mix(pow(shadowValue.y, 4.0), shadowValue.x, specularAlphaG);
256256
#endif
257257
#endif
258258
#else
259-
slab_diffuse *= computeIndirectShadow().x;
259+
slab_diffuse_ibl *= computeIndirectShadow().x;
260260
#endif
261261
#endif
262262
`;
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
struct conductorReflectanceOutParams
2-
{
3-
vec3 F0;
4-
vec3 F90;
5-
};
61

72
#define pbr_inline
8-
conductorReflectanceOutParams conductorReflectance(in vec3 baseColor, in vec3 specularColor, in float specularWeight)
3+
ReflectanceParams conductorReflectance(in vec3 baseColor, in vec3 specularColor, in float specularWeight)
94
{
10-
conductorReflectanceOutParams outParams;
5+
ReflectanceParams outParams;
116

127
#if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR)
13-
outParams.F0 = baseColor * specularWeight;
14-
outParams.F90 = specularColor * specularWeight;
8+
outParams.coloredF0 = baseColor * specularWeight;
9+
outParams.coloredF90 = specularColor * specularWeight;
1510
#else
16-
outParams.F0 = baseColor;
17-
outParams.F90 = vec3(1.0);
11+
outParams.coloredF0 = baseColor;
12+
outParams.coloredF90 = vec3(1.0);
1813
#endif
14+
outParams.F0 = 1.0;
15+
outParams.F90 = 1.0;
1916
return outParams;
2017
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
struct dielectricReflectanceOutParams
1+
struct ReflectanceParams
22
{
33
float F0;
44
float F90;
@@ -7,11 +7,11 @@ struct dielectricReflectanceOutParams
77
};
88

99
#define pbr_inline
10-
dielectricReflectanceOutParams dielectricReflectance(
10+
ReflectanceParams dielectricReflectance(
1111
in float insideIOR, in float outsideIOR, in vec3 specularColor, in float specularWeight
1212
)
1313
{
14-
dielectricReflectanceOutParams outParams;
14+
ReflectanceParams outParams;
1515

1616
float dielectricF0 = pow((insideIOR - outsideIOR) / (insideIOR + outsideIOR), 2.0);
1717

@@ -30,7 +30,7 @@ dielectricReflectanceOutParams dielectricReflectance(
3030
// Scale the reflectanceF90 by the IOR for values less than 1.5.
3131
// This is an empirical hack to account for the fact that Schlick is tuned for IOR = 1.5
3232
// and an IOR of 1.0 should result in no visible glancing specular.
33-
float f90Scale = clamp(2.0 * (insideIOR - 1.0), 0.0, 1.0);
33+
float f90Scale = clamp(2.0 * abs(insideIOR - outsideIOR), 0.0, 1.0);
3434
outParams.F90 = f90Scale * specularWeight;
3535

3636
// Compute the coloured F0 reflectance.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#ifdef LIGHT{X}
2+
{
3+
vec3 slab_diffuse = vec3(0., 0., 0.);
4+
vec3 slab_subsurface = vec3(0., 0., 0.);
5+
vec3 slab_translucent = vec3(0., 0., 0.);
6+
vec3 slab_glossy = vec3(0., 0., 0.);
7+
float specularFresnel = 0.0;
8+
vec3 slab_metal = vec3(0., 0., 0.);
9+
vec3 slab_coat = vec3(0., 0., 0.);
10+
float coatFresnel = 0.0;
11+
vec3 slab_fuzz = vec3(0., 0., 0.);
12+
13+
// Diffuse Lobe
14+
#ifdef HEMILIGHT{X}
15+
slab_diffuse = computeHemisphericDiffuseLighting(preInfo{X}, lightColor{X}.rgb, light{X}.vLightGround);
16+
#elif defined(AREALIGHT{X})
17+
slab_diffuse = computeAreaDiffuseLighting(preInfo{X}, lightColor{X}.rgb);
18+
#else
19+
slab_diffuse = computeDiffuseLighting(preInfo{X}, lightColor{X}.rgb);
20+
#endif
21+
22+
#ifdef PROJECTEDLIGHTTEXTURE{X}
23+
slab_diffuse *= computeProjectionTextureDiffuseLighting(projectionLightTexture{X}, textureProjectionMatrix{X}, vPositionW);
24+
#endif
25+
26+
numLights += 1.0;
27+
28+
// Specular Lobe
29+
#if AREALIGHT{X}
30+
slab_glossy = computeAreaSpecularLighting(preInfo{X}, light{X}.vLightSpecular.rgb, baseConductorReflectance.F0, baseConductorReflectance.F90);
31+
#else
32+
{
33+
#ifdef ANISOTROPIC
34+
slab_glossy = computeAnisotropicSpecularLighting(preInfo{X}, viewDirectionW, normalW,
35+
anisotropicOut.anisotropicTangent, anisotropicOut.anisotropicBitangent, anisotropicOut.anisotropy,
36+
vec3(baseDielectricReflectance.F0), vec3(baseDielectricReflectance.F90), baseGeoInfo.AARoughnessFactors.x, lightColor{X}.rgb);
37+
#else
38+
slab_glossy = computeSpecularLighting(preInfo{X}, normalW, baseDielectricReflectance.coloredF0, baseDielectricReflectance.coloredF90, specular_roughness, lightColor{X}.rgb);
39+
#endif
40+
41+
float NdotH = dot(normalW, preInfo{X}.H);
42+
specularFresnel = fresnelSchlickGGX(NdotH, baseDielectricReflectance.F0, baseDielectricReflectance.F90);
43+
}
44+
#endif
45+
46+
// Metal Lobe
47+
#if AREALIGHT{X}
48+
slab_metal = computeAreaSpecularLighting(preInfo{X}, light{X}.vLightSpecular.rgb, baseConductorReflectance.F0, baseConductorReflectance.F90);
49+
#else
50+
{
51+
vec3 coloredFresnel;
52+
// For OpenPBR, we use the F82 specular model for metallic materials and mix with the
53+
// usual Schlick lobe.
54+
#if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR)
55+
coloredFresnel = specular_weight * getF82Specular(preInfo{X}.VdotH, baseConductorReflectance.coloredF0, baseConductorReflectance.coloredF90, specular_roughness);
56+
#else
57+
coloredFresnel = fresnelSchlickGGX(preInfo{X}.VdotH, baseConductorReflectance.coloredF0, baseConductorReflectance.coloredF90);
58+
#endif
59+
60+
#ifdef ANISOTROPIC
61+
slab_metal = computeAnisotropicSpecularLighting(preInfo{X}, viewDirectionW, normalW, anisotropicOut.anisotropicTangent, anisotropicOut.anisotropicBitangent, anisotropicOut.anisotropy, specularEnvironmentR0, specularEnvironmentR90, baseGeoInfo.AARoughnessFactors.x, lightColor{X}.rgb);
62+
#else
63+
slab_metal = computeSpecularLighting(preInfo{X}, normalW, vec3(baseConductorReflectance.coloredF0), coloredFresnel, specular_roughness, lightColor{X}.rgb);
64+
#endif
65+
}
66+
#endif
67+
68+
// Coat Lobe
69+
#if AREALIGHT{X}
70+
slab_coat = computeAreaSpecularLighting(preInfoCoat{X}, light{X}.vLightSpecular.rgb, coatReflectance.F0, coatReflectance.F90);
71+
#else
72+
{
73+
#ifdef ANISOTROPIC
74+
slab_coat = computeAnisotropicSpecularLighting(preInfoCoat{X}, viewDirectionW, coatNormalW,
75+
anisotropicOut.anisotropicTangent, anisotropicOut.anisotropicBitangent, anisotropicOut.anisotropy,
76+
vec3(coatReflectance.F0), vec3(coatReflectance.F90), baseGeoInfo.AARoughnessFactors.x, lightColor{X}.rgb);
77+
#else
78+
slab_coat = computeSpecularLighting(preInfoCoat{X}, coatNormalW, vec3(coatReflectance.F0), vec3(1.0), coat_roughness, lightColor{X}.rgb);
79+
#endif
80+
81+
float NdotH = dot(coatNormalW, preInfoCoat{X}.H);
82+
coatFresnel = fresnelSchlickGGX(NdotH, coatReflectance.F0, coatReflectance.F90);
83+
}
84+
#endif
85+
86+
slab_diffuse *= base_color.rgb;
87+
vec3 material_opaque_base = mix(slab_diffuse, slab_subsurface, subsurface_weight);
88+
vec3 material_dielectric_base = mix(material_opaque_base, slab_translucent, transmission_weight);
89+
vec3 material_dielectric_gloss = layer(material_dielectric_base, slab_glossy, specularFresnel, vec3(1.0), specular_color);
90+
vec3 material_base_substrate = mix(material_dielectric_gloss, slab_metal, base_metalness);
91+
vec3 material_coated_base = layer(material_base_substrate, slab_coat, coatFresnel, coat_color, vec3(1.0));
92+
material_surface_direct += mix(material_coated_base, slab_fuzz, fuzz_weight);
93+
}
94+
#endif

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

Lines changed: 0 additions & 25 deletions
This file was deleted.

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifdef LIGHT{X}
22
preLightingInfo preInfo{X};
3-
openpbrLightingInfo info{X};
3+
preLightingInfo preInfoCoat{X};
4+
// openpbrLightingInfo info{X};
5+
vec4 lightColor{X} = light{X}.vLightDiffuse;
46
float shadow{X} = 1.;
57
#if defined(SHADOWONLY) || defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
68
//No light calculation
@@ -11,17 +13,23 @@
1113
// Compute Pre Lighting infos
1214
#ifdef SPOTLIGHT{X}
1315
preInfo{X} = computePointAndSpotPreLightingInfo(light{X}.vLightData, viewDirectionW, normalW, vPositionW);
16+
preInfoCoat{X} = computePointAndSpotPreLightingInfo(light{X}.vLightData, viewDirectionW, coatNormalW, vPositionW);
1417
#elif defined(POINTLIGHT{X})
1518
preInfo{X} = computePointAndSpotPreLightingInfo(light{X}.vLightData, viewDirectionW, normalW, vPositionW);
19+
preInfoCoat{X} = computePointAndSpotPreLightingInfo(light{X}.vLightData, viewDirectionW, coatNormalW, vPositionW);
1620
#elif defined(HEMILIGHT{X})
1721
preInfo{X} = computeHemisphericPreLightingInfo(light{X}.vLightData, viewDirectionW, normalW);
22+
preInfoCoat{X} = computeHemisphericPreLightingInfo(light{X}.vLightData, viewDirectionW, coatNormalW);
1823
#elif defined(DIRLIGHT{X})
1924
preInfo{X} = computeDirectionalPreLightingInfo(light{X}.vLightData, viewDirectionW, normalW);
25+
preInfoCoat{X} = computeDirectionalPreLightingInfo(light{X}.vLightData, viewDirectionW, coatNormalW);
2026
#elif defined(AREALIGHT{X}) && defined(AREALIGHTSUPPORTED)
2127
preInfo{X} = computeAreaPreLightingInfo(areaLightsLTC1Sampler, areaLightsLTC2Sampler, viewDirectionW, normalW, vPositionW, light{X}.vLightData, light{X}.vLightWidth.xyz, light{X}.vLightHeight.xyz, specular_roughness);
28+
preInfoCoat{X} = computeAreaPreLightingInfo(areaLightsLTC1Sampler, areaLightsLTC2Sampler, viewDirectionW, coatNormalW, vPositionW, light{X}.vLightData, light{X}.vLightWidth.xyz, light{X}.vLightHeight.xyz, coat_roughness);
2229
#endif
2330

2431
preInfo{X}.NdotV = baseGeoInfo.NdotV;
32+
preInfoCoat{X}.NdotV = coatGeoInfo.NdotV;
2533

2634
// Compute Attenuation infos
2735
#ifdef SPOTLIGHT{X}
@@ -68,12 +76,16 @@
6876
preInfo{X}.attenuation = 1.0;
6977
#endif
7078

79+
preInfoCoat{X}.attenuation = preInfo{X}.attenuation;
80+
7181
// Simulates Light radius for diffuse and spec term
7282
// clear coat is using a dedicated roughness
7383
#if defined(HEMILIGHT{X}) || defined(AREALIGHT{X})
7484
preInfo{X}.roughness = specular_roughness;
85+
preInfoCoat{X}.roughness = coat_roughness;
7586
#else
7687
preInfo{X}.roughness = adjustRoughnessFromLightProperties(specular_roughness, light{X}.vLightSpecular.a, preInfo{X}.lightDistance);
88+
preInfoCoat{X}.roughness = adjustRoughnessFromLightProperties(coat_roughness, light{X}.vLightSpecular.a, preInfoCoat{X}.lightDistance);
7789
#endif
7890
preInfo{X}.diffuseRoughness = base_diffuse_roughness;
7991
preInfo{X}.surfaceAlbedo = base_color.rgb;

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

Lines changed: 0 additions & 41 deletions
This file was deleted.

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@
218218
}
219219

220220
#define pbr_inline
221-
vec3 conductorIblFresnel(in conductorReflectanceOutParams reflectance, in float NdotV, in float roughness, in vec3 environmentBrdf)
221+
vec3 conductorIblFresnel(in ReflectanceParams reflectance, in float NdotV, in float roughness, in vec3 environmentBrdf)
222222
{
223223
#if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR)
224224
// For OpenPBR, we use a different specular lobe for metallic materials and then blend based on metalness. However,
@@ -227,10 +227,10 @@
227227
// So, for intermediate metallic values, the result isn't 100% correct but it seems to work well enough in practice.
228228
// Because specular weight in OpenPBR removes the specular lobe entirely for metals, we do need the actual dielectric
229229
// F0 value to pickup the weight from the dielectric lobe.
230-
return getF82Specular(NdotV, reflectance.F0, reflectance.F90, roughness);
231-
230+
return getF82Specular(NdotV, reflectance.coloredF0, reflectance.coloredF90, roughness);
231+
232232
#else
233-
return getReflectanceFromBRDFLookup(reflectance.F0, reflectance.F90, environmentBrdf);
233+
return getReflectanceFromBRDFLookup(reflectance.coloredF0, reflectance.coloredF90, environmentBrdf);
234234
#endif
235235
}
236236
#endif

0 commit comments

Comments
 (0)