Skip to content

Commit 5e4e257

Browse files
authored
Merge pull request #556 from KhronosGroup/refactor/BRDF
Refactor/brdf
2 parents 72357e9 + c22a47a commit 5e4e257

File tree

7 files changed

+188
-327
lines changed

7 files changed

+188
-327
lines changed

source/GltfState/gltf_state.js

+19-33
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,8 @@ GltfState.DebugOutput = {
149149
EMISSIVE: "Emissive",
150150
},
151151

152-
/** output metallic roughness */
152+
/** metallic roughness */
153153
mr: {
154-
/** output the combined metallic roughness */
155-
METALLIC_ROUGHNESS: "Metallic Roughness",
156154
/** output the base color value */
157155
BASECOLOR: "Base Color",
158156
/** output the metallic value from pbr metallic roughness */
@@ -161,69 +159,57 @@ GltfState.DebugOutput = {
161159
ROUGHNESS: "Roughness",
162160
},
163161

164-
/** output clearcoat lighting */
162+
/** KHR_materials_clearcoat */
165163
clearcoat: {
166-
/** output the combined clear coat */
167-
CLEARCOAT: "ClearCoat",
168-
/** output the clear coat factor */
169-
CLEARCOAT_FACTOR: "ClearCoat Factor",
164+
/** output the clear coat strength */
165+
CLEARCOAT_FACTOR: "ClearCoat Strength",
170166
/** output the clear coat roughness */
171167
CLEARCOAT_ROUGHNESS: "ClearCoat Roughness",
172168
/** output the clear coat normal */
173169
CLEARCOAT_NORMAL: "ClearCoat Normal",
174170
},
175171

176-
/** output sheen lighting */
172+
/** KHR_materials_sheen */
177173
sheen: {
178-
/** output the combined sheen */
179-
SHEEN: "Sheen",
180174
/** output the sheen color*/
181175
SHEEN_COLOR: "Sheen Color",
182176
/** output the sheen roughness*/
183177
SHEEN_ROUGHNESS: "Sheen Roughness",
184178
},
185179

186-
/** output specular lighting */
180+
/** KHR_materials_specular */
187181
specular: {
188-
/** output the combined specular */
189-
SPECULAR: "Specular",
190-
/** output the specular factor*/
191-
SPECULAR_FACTOR: "Specular Factor",
182+
/** output the specular strength*/
183+
SPECULAR_FACTOR: "Specular Strength",
192184
/** output the specular color*/
193185
SPECULAR_COLOR: "Specular Color",
194186
},
195187

196-
/** output tranmission lighting */
188+
/** KHR_materials_transmission */
197189
transmission: {
198-
/** output the combined transmission/volume */
199-
TRANSMISSION_VOLUME: "Transmission/Volume",
200-
/** output the transmission factor*/
201-
TRANSMISSION_FACTOR: "Transmission Factor",
190+
/** output the transmission strength*/
191+
TRANSMISSION_FACTOR: "Transmission Strength",
202192
/** output the volume thickness*/
203193
VOLUME_THICKNESS: "Volume Thickness",
204194
},
205195

206-
/** output diffuse tranmission lighting */
196+
/** KHR_materials_diffuse_tranmission */
207197
diffuseTransmission: {
208-
/** output the combined diffuse tranmission */
209-
DIFFUSE_TRANSMISSION: "Diffuse Transmission",
210-
/** output the diffuse tranmission factor */
211-
DIFFUSE_TRANSMISSION_FACTOR: "Diffuse Transmission Factor",
198+
/** output the diffuse tranmission strength */
199+
DIFFUSE_TRANSMISSION_FACTOR: "Diffuse Transmission Strength",
212200
/** output the diffuse tranmission color factor */
213-
DIFFUSE_TRANSMISSION_COLOR_FACTOR: "Diffuse Transmission Color Factor",
201+
DIFFUSE_TRANSMISSION_COLOR_FACTOR: "Diffuse Transmission Color",
214202
},
215203

216-
/** output iridescence */
204+
/** KHR_materials_iridescence */
217205
iridescence: {
218-
/** output the combined iridescence */
219-
IRIDESCENCE: "Iridescence",
220-
/** output the iridescence factor*/
221-
IRIDESCENCE_FACTOR: "Iridescence Factor",
206+
/** output the iridescence strength*/
207+
IRIDESCENCE_FACTOR: "Iridescence Strength",
222208
/** output the iridescence thickness*/
223209
IRIDESCENCE_THICKNESS: "Iridescence Thickness",
224210
},
225211

226-
/** output anisotropy */
212+
/** KHR_materials_anisotropy */
227213
anisotropy: {
228214
/** output the anisotropic strength*/
229215
ANISOTROPIC_STRENGTH: "Anisotropic Strength",

source/Renderer/shaders/brdf.glsl

+7-41
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
// The following equation models the Fresnel reflectance term of the spec equation (aka F())
1010
// Implementation of fresnel from [4], Equation 15
11-
vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH)
11+
vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH)
1212
{
1313
return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
1414
}
@@ -149,54 +149,22 @@ float D_Charlie(float sheenRoughness, float NdotH)
149149

150150

151151
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB
152-
vec3 BRDF_lambertian(vec3 f0, vec3 f90, vec3 diffuseColor, float specularWeight, float VdotH)
152+
vec3 BRDF_lambertian(vec3 diffuseColor)
153153
{
154154
// see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
155-
return (1.0 - specularWeight * F_Schlick(f0, f90, VdotH)) * (diffuseColor / M_PI);
155+
return (diffuseColor / M_PI);
156156
}
157157

158-
159-
#ifdef MATERIAL_IRIDESCENCE
160-
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB
161-
vec3 BRDF_lambertianIridescence(vec3 f0, vec3 f90, vec3 iridescenceFresnel, float iridescenceFactor, vec3 diffuseColor, float specularWeight, float VdotH)
162-
{
163-
// Use the maximum component of the iridescence Fresnel color
164-
// Maximum is used instead of the RGB value to not get inverse colors for the diffuse BRDF
165-
vec3 iridescenceFresnelMax = vec3(max(max(iridescenceFresnel.r, iridescenceFresnel.g), iridescenceFresnel.b));
166-
167-
vec3 schlickFresnel = F_Schlick(f0, f90, VdotH);
168-
169-
// Blend default specular Fresnel with iridescence Fresnel
170-
vec3 F = mix(schlickFresnel, iridescenceFresnelMax, iridescenceFactor);
171-
172-
// see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
173-
return (1.0 - specularWeight * F) * (diffuseColor / M_PI);
174-
}
175-
#endif
176-
177-
178158
// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB
179-
vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, float specularWeight, float VdotH, float NdotL, float NdotV, float NdotH)
159+
vec3 BRDF_specularGGX(float alphaRoughness, float NdotL, float NdotV, float NdotH)
180160
{
181-
vec3 F = F_Schlick(f0, f90, VdotH);
182161
float Vis = V_GGX(NdotL, NdotV, alphaRoughness);
183162
float D = D_GGX(NdotH, alphaRoughness);
184163

185-
return specularWeight * F * Vis * D;
164+
return vec3(Vis * D);
186165
}
187166

188167

189-
#ifdef MATERIAL_IRIDESCENCE
190-
vec3 BRDF_specularGGXIridescence(vec3 f0, vec3 f90, vec3 iridescenceFresnel, float alphaRoughness, float iridescenceFactor, float specularWeight, float VdotH, float NdotL, float NdotV, float NdotH)
191-
{
192-
vec3 F = mix(F_Schlick(f0, f90, VdotH), iridescenceFresnel, iridescenceFactor);
193-
float Vis = V_GGX(NdotL, NdotV, alphaRoughness);
194-
float D = D_GGX(NdotH, alphaRoughness);
195-
196-
return specularWeight * F * Vis * D;
197-
}
198-
#endif
199-
200168
#ifdef MATERIAL_ANISOTROPY
201169
// GGX Distribution Anisotropic (Same as Babylon.js)
202170
// https://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf Addenda
@@ -218,7 +186,7 @@ float V_GGX_anisotropic(float NdotL, float NdotV, float BdotV, float TdotV, floa
218186
return clamp(v, 0.0, 1.0);
219187
}
220188

221-
vec3 BRDF_specularGGXAnisotropy(vec3 f0, vec3 f90, float alphaRoughness, float anisotropy, vec3 n, vec3 v, vec3 l, vec3 h, vec3 t, vec3 b)
189+
vec3 BRDF_specularGGXAnisotropy(float alphaRoughness, float anisotropy, vec3 n, vec3 v, vec3 l, vec3 h, vec3 t, vec3 b)
222190
{
223191
// Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy.
224192
float at = mix(alphaRoughness, 1.0, anisotropy * anisotropy);
@@ -227,13 +195,11 @@ vec3 BRDF_specularGGXAnisotropy(vec3 f0, vec3 f90, float alphaRoughness, float a
227195
float NdotL = clamp(dot(n, l), 0.0, 1.0);
228196
float NdotH = clamp(dot(n, h), 0.001, 1.0);
229197
float NdotV = dot(n, v);
230-
float VdotH = clamp(dot(v, h), 0.0, 1.0);
231198

232199
float V = V_GGX_anisotropic(NdotL, NdotV, dot(b, v), dot(t, v), dot(t, l), dot(b, l), at, ab);
233200
float D = D_GGX_anisotropic(NdotH, dot(t, h), dot(b, h), anisotropy, at, ab);
234201

235-
vec3 F = F_Schlick(f0, f90, VdotH);
236-
return F * V * D;
202+
return vec3(V * D);
237203
}
238204
#endif
239205

source/Renderer/shaders/functions.glsl

+7
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,10 @@ float applyIorToRoughness(float roughness, float ior)
8484
// an IOR of 1.5 results in the default amount of microfacet refraction.
8585
return roughness * clamp(ior * 2.0 - 2.0, 0.0, 1.0);
8686
}
87+
88+
vec3 rgb_mix(vec3 base, vec3 layer, vec3 rgb_alpha)
89+
{
90+
float rgb_alpha_max = max(rgb_alpha.r, max(rgb_alpha.g, rgb_alpha.b));
91+
return (1.0 - rgb_alpha_max) * base + rgb_alpha * layer;
92+
}
93+

source/Renderer/shaders/ibl.glsl

+14-97
Original file line numberDiff line numberDiff line change
@@ -17,51 +17,36 @@ vec4 getSheenSample(vec3 reflection, float lod)
1717
return textureLod(u_CharlieEnvSampler, u_EnvRotation * reflection, lod) * u_EnvIntensity;
1818
}
1919

20-
21-
vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight)
20+
vec3 getIBLGGXFresnel(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight)
2221
{
22+
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
23+
// Roughness dependent fresnel, from Fdez-Aguera
2324
float NdotV = clampedDot(n, v);
24-
float lod = roughness * float(u_MipCount - 1);
25-
vec3 reflection = normalize(reflect(-v, n));
26-
2725
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
2826
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
29-
vec4 specularSample = getSpecularSample(reflection, lod);
30-
31-
vec3 specularLight = specularSample.rgb;
32-
33-
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
34-
// Roughness dependent fresnel, from Fdez-Aguera
3527
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
3628
vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0);
37-
vec3 FssEss = k_S * f_ab.x + f_ab.y;
29+
vec3 FssEss = specularWeight * (k_S * f_ab.x + f_ab.y);
3830

39-
return specularWeight * specularLight * FssEss;
40-
}
31+
// Multiple scattering, from Fdez-Aguera
32+
float Ems = (1.0 - (f_ab.x + f_ab.y));
33+
vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0);
34+
vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
4135

36+
return FssEss + FmsEms;
37+
}
4238

43-
#ifdef MATERIAL_IRIDESCENCE
44-
vec3 getIBLRadianceGGXIridescence(vec3 n, vec3 v, float roughness, vec3 F0, vec3 iridescenceFresnel, float iridescenceFactor, float specularWeight)
39+
vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness)
4540
{
4641
float NdotV = clampedDot(n, v);
4742
float lod = roughness * float(u_MipCount - 1);
4843
vec3 reflection = normalize(reflect(-v, n));
49-
50-
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
51-
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
5244
vec4 specularSample = getSpecularSample(reflection, lod);
5345

5446
vec3 specularLight = specularSample.rgb;
5547

56-
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
57-
// Roughness dependent fresnel, from Fdez-Aguera
58-
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
59-
vec3 k_S = mix(F0 + Fr * pow(1.0 - NdotV, 5.0), iridescenceFresnel, iridescenceFactor);
60-
vec3 FssEss = k_S * f_ab.x + f_ab.y;
61-
62-
return specularWeight * specularLight * FssEss;
48+
return specularLight;
6349
}
64-
#endif
6550

6651

6752
#ifdef MATERIAL_TRANSMISSION
@@ -130,68 +115,8 @@ vec3 getIBLVolumeRefraction(vec3 n, vec3 v, float perceptualRoughness, vec3 base
130115
#endif
131116

132117

133-
// specularWeight is introduced with KHR_materials_specular
134-
vec3 getIBLRadianceLambertian(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, float specularWeight)
135-
{
136-
float NdotV = clampedDot(n, v);
137-
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
138-
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
139-
140-
vec3 irradiance = getDiffuseLight(n);
141-
142-
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
143-
// Roughness dependent fresnel, from Fdez-Aguera
144-
145-
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
146-
vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0);
147-
vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low)
148-
149-
// Multiple scattering, from Fdez-Aguera
150-
float Ems = (1.0 - (f_ab.x + f_ab.y));
151-
vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0);
152-
vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
153-
vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms); // we use +FmsEms as indicated by the formula in the blog post (might be a typo in the implementation)
154-
155-
return (FmsEms + k_D) * irradiance;
156-
}
157-
158-
159-
#ifdef MATERIAL_IRIDESCENCE
160-
// specularWeight is introduced with KHR_materials_specular
161-
vec3 getIBLRadianceLambertianIridescence(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, vec3 iridescenceF0, float iridescenceFactor, float specularWeight)
162-
{
163-
float NdotV = clampedDot(n, v);
164-
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
165-
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
166-
167-
vec3 irradiance = getDiffuseLight(n);
168-
169-
// Use the maximum component of the iridescence Fresnel color
170-
// Maximum is used instead of the RGB value to not get inverse colors for the diffuse BRDF
171-
vec3 iridescenceF0Max = vec3(max(max(iridescenceF0.r, iridescenceF0.g), iridescenceF0.b));
172-
173-
// Blend between base F0 and iridescence F0
174-
vec3 mixedF0 = mix(F0, iridescenceF0Max, iridescenceFactor);
175-
176-
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
177-
// Roughness dependent fresnel, from Fdez-Aguera
178-
179-
vec3 Fr = max(vec3(1.0 - roughness), mixedF0) - mixedF0;
180-
vec3 k_S = mixedF0 + Fr * pow(1.0 - NdotV, 5.0);
181-
vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low)
182-
183-
// Multiple scattering, from Fdez-Aguera
184-
float Ems = (1.0 - (f_ab.x + f_ab.y));
185-
vec3 F_avg = specularWeight * (mixedF0 + (1.0 - mixedF0) / 21.0);
186-
vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
187-
vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms); // we use +FmsEms as indicated by the formula in the blog post (might be a typo in the implementation)
188-
189-
return (FmsEms + k_D) * irradiance;
190-
}
191-
#endif
192-
193118
#ifdef MATERIAL_ANISOTROPY
194-
vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy, vec3 anisotropyDirection, vec3 F0, float specularWeight)
119+
vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy, vec3 anisotropyDirection)
195120
{
196121
float NdotV = clampedDot(n, v);
197122

@@ -205,19 +130,11 @@ vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy,
205130
float lod = roughness * float(u_MipCount - 1);
206131
vec3 reflection = normalize(reflect(-v, bentNormal));
207132

208-
vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0));
209-
vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg;
210133
vec4 specularSample = getSpecularSample(reflection, lod);
211134

212135
vec3 specularLight = specularSample.rgb;
213136

214-
// see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results
215-
// Roughness dependent fresnel, from Fdez-Aguera
216-
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
217-
vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0);
218-
vec3 FssEss = k_S * f_ab.x + f_ab.y;
219-
220-
return specularWeight * specularLight * FssEss;
137+
return specularLight;
221138
}
222139
#endif
223140

0 commit comments

Comments
 (0)