Skip to content

Commit b2bf2c3

Browse files
author
Mike Bond
committed
WIP replacing PBR props with OpenPBR props
1 parent 68a6cf5 commit b2bf2c3

24 files changed

+970
-1775
lines changed

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

Lines changed: 110 additions & 475 deletions
Large diffs are not rendered by default.

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

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,20 @@ uniform Material {
2727
vec2 vOpacityInfos;
2828
vec2 vEmissiveInfos;
2929
vec2 vLightmapInfos;
30-
vec3 vReflectivityInfos;
31-
vec2 vMicroSurfaceSamplerInfos;
3230
vec3 vBumpInfos;
3331

3432
mat4 ambientMatrix;
3533
mat4 opacityMatrix;
3634
mat4 emissiveMatrix;
3735
mat4 lightmapMatrix;
38-
mat4 reflectivityMatrix;
39-
mat4 microSurfaceSamplerMatrix;
4036
mat4 bumpMatrix;
4137
vec2 vTangentSpaceParams;
4238
vec4 vLightingIntensity;
4339
float pointSize;
44-
vec4 vReflectivityColor;
4540
vec3 vAmbientColor;
4641

4742
vec2 vDebugMode;
4843

49-
vec4 vMetallicReflectanceFactors;
50-
vec2 vMetallicReflectanceInfos;
51-
mat4 metallicReflectanceMatrix;
52-
vec2 vReflectanceInfos;
53-
mat4 reflectanceMatrix;
5444
vec4 cameraInfo;
5545

5646
vec2 vReflectionInfos;
@@ -84,15 +74,24 @@ uniform Material {
8474

8575
float baseWeight;
8676
vec4 vBaseColor;
87-
float baseDiffuseRoughness;
77+
float vBaseDiffuseRoughness;
78+
vec4 vReflectanceInfo;
79+
vec4 vSpecularColor;
8880
vec3 vEmissiveColor;
8981

90-
vec2 baseWeightInfos;
82+
vec2 vBaseWeightInfos;
9183
mat4 baseWeightMatrix;
92-
vec2 baseColorInfos;
84+
vec2 vBaseColorInfos;
9385
mat4 baseColorMatrix;
94-
vec2 baseDiffuseRoughnessInfos;
86+
vec2 vBaseDiffuseRoughnessInfos;
9587
mat4 baseDiffuseRoughnessMatrix;
88+
vec2 vBaseMetalRoughInfos;
89+
mat4 baseMetalRoughMatrix;
90+
vec2 vSpecularWeightInfos;
91+
mat4 specularWeightMatrix;
92+
vec2 vSpecularColorInfos;
93+
mat4 specularColorMatrix;
94+
9695
#define ADDITIONAL_UBO_DECLARATION
9796
};
9897

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
vec4 finalColor = vec4(
2+
#ifndef UNLIT
3+
#ifdef REFLECTION
4+
finalIrradiance +
5+
#endif
6+
#ifdef SPECULARTERM
7+
finalSpecularScaled +
8+
#endif
9+
#ifdef REFLECTION
10+
finalRadianceScaled +
11+
#endif
12+
#endif
13+
finalAmbient +
14+
finalDiffuse,
15+
alpha);
16+
17+
// _____________________________ LightMappping _____________________________________
18+
#ifdef LIGHTMAP
19+
#ifndef LIGHTMAPEXCLUDED
20+
#ifdef USELIGHTMAPASSHADOWMAP
21+
finalColor.rgb *= lightmapColor.rgb;
22+
#else
23+
finalColor.rgb += lightmapColor.rgb;
24+
#endif
25+
#endif
26+
#endif
27+
28+
// _____________________________ EmissiveLight _____________________________________
29+
finalColor.rgb += finalEmissive;
30+
31+
#define CUSTOM_FRAGMENT_BEFORE_FOG
32+
33+
// _____________________________ Finally ___________________________________________
34+
finalColor = max(finalColor, 0.0);
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
aggShadow = aggShadow / numLights;
2+
3+
// ______________________________________________________________________________
4+
// _____________________________ Energy Conservation ___________________________
5+
// Apply Energy Conservation.
6+
// _____________________________ IBL BRDF + Energy Cons ________________________________
7+
#if defined(ENVIRONMENTBRDF)
8+
#ifdef MS_BRDF_ENERGY_CONSERVATION
9+
vec3 baseSpecularEnergyConservationFactor = getEnergyConservationFactor(vec3(reflectanceF0), environmentBrdf);
10+
vec3 coloredEnergyConservationFactor = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf);
11+
#endif
12+
#endif
13+
14+
// _____________________________ Irradiance ______________________________________
15+
#ifdef REFLECTION
16+
vec3 finalIrradiance = reflectionOut.environmentIrradiance;
17+
18+
// Account for energy loss due to specular reflectance
19+
vec3 baseSpecularEnergy = vec3(baseSpecularEnvironmentReflectance);
20+
#if defined(ENVIRONMENTBRDF)
21+
#ifdef MS_BRDF_ENERGY_CONSERVATION
22+
baseSpecularEnergy *= baseSpecularEnergyConservationFactor;
23+
#endif
24+
#endif
25+
finalIrradiance *= clamp(vec3(1.0) - baseSpecularEnergy, 0.0, 1.0);
26+
finalIrradiance *= vLightingIntensity.z;
27+
finalIrradiance *= surfaceAlbedo.rgb;
28+
finalIrradiance *= aoOut.ambientOcclusionColor;
29+
#endif
30+
31+
// _____________________________ Specular ________________________________________
32+
#ifdef SPECULARTERM
33+
vec3 finalSpecular = specularBase;
34+
finalSpecular = max(finalSpecular, 0.0);
35+
36+
vec3 finalSpecularScaled = finalSpecular * vLightingIntensity.x * vLightingIntensity.w;
37+
38+
#if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
39+
finalSpecularScaled *= coloredEnergyConservationFactor;
40+
#endif
41+
#endif
42+
43+
// _____________________________ Radiance ________________________________________
44+
#ifdef REFLECTION
45+
vec3 finalRadiance = reflectionOut.environmentRadiance.rgb;
46+
finalRadiance *= colorSpecularEnvironmentReflectance;
47+
48+
vec3 finalRadianceScaled = finalRadiance * vLightingIntensity.z;
49+
50+
#if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
51+
finalRadianceScaled *= coloredEnergyConservationFactor;
52+
#endif
53+
#endif
54+
55+
// _____________________________ Highlights on Alpha _____________________________
56+
#ifdef ALPHABLEND
57+
float luminanceOverAlpha = 0.0;
58+
#if defined(REFLECTION) && defined(RADIANCEOVERALPHA)
59+
luminanceOverAlpha += getLuminance(finalRadianceScaled);
60+
#endif
61+
62+
#if defined(SPECULARTERM) && defined(SPECULAROVERALPHA)
63+
luminanceOverAlpha += getLuminance(finalSpecularScaled);
64+
#endif
65+
66+
#if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)
67+
alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha);
68+
#endif
69+
#endif
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
2+
// "Base" specular reflectance is the amount of light prevented from penetrating the diffuse surface by the specular lobe.
3+
// For dielectric materials, this is a greyscale value derived from the IOR and the maximum component of the specular colour.
4+
// For metallic materials, this is vec3(1.0). i.e. no light penetrates to the diffuse surface.
5+
vec3 baseSpecularEnvironmentReflectance = getReflectanceFromBRDFLookup(vec3(reflectanceF0), reflectivityOut.reflectanceF90, environmentBrdf);
6+
7+
#if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR)
8+
// For OpenPBR, we use a different specular lobe for metallic materials and then blend based on metalness. However,
9+
// to do this correctly, we really need reflectivityOut to contain separate F0 and F90 values for purely dielectric
10+
// and purely metal. Instead, the values are already a mix of dielectric and metallic values.
11+
// So, for intermediate metallic values, the result isn't 100% correct but it seems to work well enough in practice.
12+
// Because specular weight in OpenPBR removes the specular lobe entirely for metals, we do need the actual dielectric
13+
// F0 value to pickup the weight from the dielectric lobe.
14+
vec3 metalEnvironmentReflectance = reflectivityOut.specularWeight * getF82Specular(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, reflectivityOut.roughness);
15+
vec3 dielectricEnvironmentReflectance = getReflectanceFromBRDFLookup(reflectivityOut.dielectricColorF0, reflectivityOut.colorReflectanceF90, environmentBrdf);
16+
vec3 colorSpecularEnvironmentReflectance = mix(dielectricEnvironmentReflectance, metalEnvironmentReflectance, reflectivityOut.metallic);
17+
#else
18+
vec3 colorSpecularEnvironmentReflectance = getReflectanceFromBRDFLookup(reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, environmentBrdf);
19+
#endif
20+
21+
#ifdef RADIANCEOCCLUSION
22+
colorSpecularEnvironmentReflectance *= seo;
23+
#endif
24+
25+
#ifdef HORIZONOCCLUSION
26+
#ifdef BUMP
27+
#ifdef REFLECTIONMAP_3D
28+
colorSpecularEnvironmentReflectance *= eho;
29+
#endif
30+
#endif
31+
#endif
32+
#else
33+
// Jones implementation of a well balanced fast analytical solution.
34+
vec3 colorSpecularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, reflectivityOut.colorReflectanceF0, reflectivityOut.colorReflectanceF90, sqrt(microSurface));
35+
vec3 baseSpecularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, vec3(reflectanceF0), reflectivityOut.reflectanceF90, sqrt(microSurface));
36+
#endif
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
struct reflectivityOutParams
2+
{
3+
float roughness;
4+
float diffuseRoughness;
5+
float reflectanceF0;
6+
vec3 reflectanceF90;
7+
vec3 colorReflectanceF0;
8+
vec3 colorReflectanceF90;
9+
float metallic;
10+
float specularWeight;
11+
vec3 dielectricColorF0;
12+
#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED)
13+
vec3 ambientOcclusionColor;
14+
#endif
15+
#if DEBUGMODE > 0
16+
#ifdef METALLIC_ROUGHNESS
17+
vec4 surfaceMetallicColorMap;
18+
#endif
19+
vec3 metallicF0;
20+
#endif
21+
};
22+
23+
#define pbr_inline
24+
reflectivityOutParams reflectivityBlock(
25+
in vec4 reflectanceInfo
26+
, in vec3 surfaceAlbedo
27+
, in vec4 specularColor
28+
, in float baseDiffuseRoughness
29+
#ifdef BASE_DIFFUSE_ROUGHNESS
30+
, in float baseDiffuseRoughnessTexture
31+
, in vec2 baseDiffuseRoughnessInfos
32+
#endif
33+
#ifdef METALLIC_ROUGHNESS
34+
, in vec3 reflectivityInfos
35+
, in vec4 metallicRoughnessFromTexture
36+
#endif
37+
#if defined(METALLIC_ROUGHNESS) && defined(AOSTOREINMETALMAPRED)
38+
, in vec3 ambientOcclusionColorIn
39+
#endif
40+
#ifdef DETAIL
41+
, in vec4 detailColor
42+
, in vec4 vDetailInfos
43+
#endif
44+
)
45+
{
46+
reflectivityOutParams outParams;
47+
vec2 metallicRoughness = reflectanceInfo.rg;
48+
float ior = reflectanceInfo.b;
49+
#ifdef METALLIC_ROUGHNESS
50+
#if DEBUGMODE > 0
51+
outParams.surfaceMetallicColorMap = metallicRoughnessFromTexture;
52+
#endif
53+
54+
#ifdef AOSTOREINMETALMAPRED
55+
vec3 aoStoreInMetalMap = vec3(metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r, metallicRoughnessFromTexture.r);
56+
outParams.ambientOcclusionColor = mix(ambientOcclusionColorIn, aoStoreInMetalMap, reflectivityInfos.z);
57+
#endif
58+
59+
metallicRoughness.r *= metallicRoughnessFromTexture.b;
60+
metallicRoughness.g *= metallicRoughnessFromTexture.g;
61+
#endif
62+
63+
#ifdef DETAIL
64+
float detailRoughness = mix(0.5, detailColor.b, vDetailInfos.w);
65+
float loLerp = mix(0., metallicRoughness.g, detailRoughness * 2.);
66+
float hiLerp = mix(metallicRoughness.g, 1., (detailRoughness - 0.5) * 2.);
67+
metallicRoughness.g = mix(loLerp, hiLerp, step(detailRoughness, 0.5));
68+
#endif
69+
70+
#define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS
71+
72+
outParams.metallic = metallicRoughness.r;
73+
outParams.roughness = metallicRoughness.g;
74+
outParams.specularWeight = specularColor.a;
75+
const float outsideIOR = 1.0;
76+
float dielectricF0 = pow((ior - outsideIOR) / (ior + outsideIOR), 2.0) * outParams.specularWeight;
77+
78+
#if DEBUGMODE > 0
79+
outParams.metallicF0 = vec3(dielectricF0) * specularColor.rgb;
80+
#endif
81+
82+
// Compute non-coloured reflectance.
83+
// reflectanceF0 is the non-coloured reflectance used for blending between the diffuse and specular components.
84+
// It represents the total percentage of light reflected by the specular lobe at normal incidence.
85+
// In glTF's material model, the F0 value is multiplied by the maximum component of the specular colour.
86+
87+
#if DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_GLTF
88+
float maxF0 = max(specularColor.r, max(specularColor.g, specularColor.b));
89+
outParams.reflectanceF0 = mix(dielectricF0 * maxF0, 1.0, outParams.metallic);
90+
#else
91+
outParams.reflectanceF0 = mix(dielectricF0, 1.0, outParams.metallic);
92+
#endif
93+
94+
95+
// Scale the reflectanceF90 by the IOR for values less than 1.5.
96+
// This is an empirical hack to account for the fact that Schlick is tuned for IOR = 1.5
97+
// and an IOR of 1.0 should result in no visible glancing specular.
98+
float f90Scale = clamp(2.0 * (ior - 1.0), 0.0, 1.0);
99+
outParams.reflectanceF90 = vec3(mix(outParams.specularWeight * f90Scale, 1.0, outParams.metallic));
100+
101+
// Compute the coloured F0 reflectance.
102+
// The coloured reflectance is the percentage of light reflected by the specular lobe at normal incidence.
103+
// In glTF and OpenPBR, it is not the same thing as the percentage of light blocked from penetrating
104+
// down to the diffuse lobe. The non-coloured F0 will be used for this (see below).
105+
outParams.dielectricColorF0 = vec3(dielectricF0 * specularColor.rgb);
106+
vec3 metallicColorF0 = surfaceAlbedo.rgb;
107+
outParams.colorReflectanceF0 = mix(outParams.dielectricColorF0, metallicColorF0, outParams.metallic);
108+
109+
// Now, compute the coloured reflectance at glancing angles based on the specular model.
110+
#if (DIELECTRIC_SPECULAR_MODEL == DIELECTRIC_SPECULAR_MODEL_OPENPBR)
111+
// In OpenPBR, the F90 is coloured using the specular colour for dielectrics.
112+
vec3 dielectricColorF90 = specularColor.rgb * vec3(outParams.specularWeight) * vec3(f90Scale);
113+
#else
114+
// In glTF, the F90 is white for dielectrics.
115+
vec3 dielectricColorF90 = vec3(outParams.specularWeight * f90Scale);
116+
#endif
117+
#if (CONDUCTOR_SPECULAR_MODEL == CONDUCTOR_SPECULAR_MODEL_OPENPBR)
118+
// In OpenPBR, we use the "F82" model for conductors.
119+
// We'll use the F90 value to hold the F82 tint which will be used in the computation later.
120+
vec3 conductorColorF90 = specularColor.rgb;
121+
#else
122+
// In glTF, the F90 colour for metals is white.
123+
vec3 conductorColorF90 = vec3(1.0);
124+
#endif
125+
outParams.colorReflectanceF90 = mix(dielectricColorF90, conductorColorF90, outParams.metallic);
126+
127+
float diffuseRoughness = baseDiffuseRoughness;
128+
#ifdef BASE_DIFFUSE_ROUGHNESS
129+
diffuseRoughness *= baseDiffuseRoughnessTexture * baseDiffuseRoughnessInfos.y;
130+
#endif
131+
132+
outParams.diffuseRoughness = diffuseRoughness;
133+
134+
return outParams;
135+
}

0 commit comments

Comments
 (0)