From 880a9a8de6be02eb726609b93f0981693d188f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Mon, 27 May 2024 16:26:38 +0200 Subject: [PATCH 01/18] Add helper comments --- source/Renderer/shaders/brdf.glsl | 10 +++++----- source/Renderer/shaders/material_info.glsl | 2 ++ source/Renderer/shaders/pbr.frag | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/source/Renderer/shaders/brdf.glsl b/source/Renderer/shaders/brdf.glsl index dcb55ce5..558f3ae0 100644 --- a/source/Renderer/shaders/brdf.glsl +++ b/source/Renderer/shaders/brdf.glsl @@ -8,9 +8,9 @@ // The following equation models the Fresnel reflectance term of the spec equation (aka F()) // Implementation of fresnel from [4], Equation 15 -vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH) +vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH) { - return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); + return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); // dialectric_fresnel } float F_Schlick(float f0, float f90, float VdotH) @@ -152,7 +152,7 @@ float D_Charlie(float sheenRoughness, float NdotH) vec3 BRDF_lambertian(vec3 f0, vec3 f90, vec3 diffuseColor, float specularWeight, float VdotH) { // see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ - return (1.0 - specularWeight * F_Schlick(f0, f90, VdotH)) * (diffuseColor / M_PI); + return (1.0 - specularWeight * F_Schlick(f0, f90, VdotH)) * (diffuseColor / M_PI); // 1.0 - specularWeight * => mix dielectric_fresnel * diffuse_bdrf } @@ -182,7 +182,7 @@ vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, float specularWei float Vis = V_GGX(NdotL, NdotV, alphaRoughness); float D = D_GGX(NdotH, alphaRoughness); - return specularWeight * F * Vis * D; + return specularWeight * F * Vis * D; // Vis * D => specular_brdf } @@ -193,7 +193,7 @@ vec3 BRDF_specularGGXIridescence(vec3 f0, vec3 f90, vec3 iridescenceFresnel, flo float Vis = V_GGX(NdotL, NdotV, alphaRoughness); float D = D_GGX(NdotH, alphaRoughness); - return specularWeight * F * Vis * D; + return specularWeight * F * Vis * D; // Vis * D => specular_brdf } #endif diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index d0f761a0..aefe9c85 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -69,6 +69,8 @@ struct MaterialInfo float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) vec3 c_diff; + float fresnel_w; + vec3 f90; // reflectance color at grazing angle float metallic; diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index f229a428..643a22d7 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -58,6 +58,7 @@ void main() materialInfo.ior = 1.5; materialInfo.f0 = vec3(0.04); materialInfo.specularWeight = 1.0; + materialInfo.fresnel_w = pow(1 - abs(VdotH), 5); // If the MR debug output is selected, we have to enforce evaluation of the non-iridescence BRDF functions. #if DEBUG == DEBUG_METALLIC_ROUGHNESS From b69adea2d18f9021c79dc4b87c719b320daf7803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Tue, 25 Jun 2024 17:48:48 +0200 Subject: [PATCH 02/18] WIP Refactor shader --- source/Renderer/shaders/brdf.glsl | 48 +---- source/Renderer/shaders/functions.glsl | 7 + source/Renderer/shaders/ibl.glsl | 119 +++-------- source/Renderer/shaders/material_info.glsl | 6 +- source/Renderer/shaders/pbr.frag | 218 ++++++++++++--------- source/Renderer/shaders/punctual.glsl | 2 +- 6 files changed, 164 insertions(+), 236 deletions(-) diff --git a/source/Renderer/shaders/brdf.glsl b/source/Renderer/shaders/brdf.glsl index 558f3ae0..8718ceea 100644 --- a/source/Renderer/shaders/brdf.glsl +++ b/source/Renderer/shaders/brdf.glsl @@ -10,7 +10,7 @@ // Implementation of fresnel from [4], Equation 15 vec3 F_Schlick(vec3 f0, vec3 f90, float VdotH) { - return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); // dialectric_fresnel + return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); } float F_Schlick(float f0, float f90, float VdotH) @@ -149,54 +149,22 @@ float D_Charlie(float sheenRoughness, float NdotH) //https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB -vec3 BRDF_lambertian(vec3 f0, vec3 f90, vec3 diffuseColor, float specularWeight, float VdotH) +vec3 BRDF_lambertian(vec3 diffuseColor) { // see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ - return (1.0 - specularWeight * F_Schlick(f0, f90, VdotH)) * (diffuseColor / M_PI); // 1.0 - specularWeight * => mix dielectric_fresnel * diffuse_bdrf + return (diffuseColor / M_PI); // 1.0 - specularWeight * => mix dielectric_fresnel * diffuse_bdrf } - -#ifdef MATERIAL_IRIDESCENCE -//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB -vec3 BRDF_lambertianIridescence(vec3 f0, vec3 f90, vec3 iridescenceFresnel, float iridescenceFactor, vec3 diffuseColor, float specularWeight, float VdotH) -{ - // Use the maximum component of the iridescence Fresnel color - // Maximum is used instead of the RGB value to not get inverse colors for the diffuse BRDF - vec3 iridescenceFresnelMax = vec3(max(max(iridescenceFresnel.r, iridescenceFresnel.g), iridescenceFresnel.b)); - - vec3 schlickFresnel = F_Schlick(f0, f90, VdotH); - - // Blend default specular Fresnel with iridescence Fresnel - vec3 F = mix(schlickFresnel, iridescenceFresnelMax, iridescenceFactor); - - // see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ - return (1.0 - specularWeight * F) * (diffuseColor / M_PI); -} -#endif - - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB -vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, float specularWeight, float VdotH, float NdotL, float NdotV, float NdotH) +vec3 BRDF_specularGGX(float alphaRoughness, float NdotL, float NdotV, float NdotH) { - vec3 F = F_Schlick(f0, f90, VdotH); float Vis = V_GGX(NdotL, NdotV, alphaRoughness); float D = D_GGX(NdotH, alphaRoughness); - return specularWeight * F * Vis * D; // Vis * D => specular_brdf + return vec3(Vis * D); } -#ifdef MATERIAL_IRIDESCENCE -vec3 BRDF_specularGGXIridescence(vec3 f0, vec3 f90, vec3 iridescenceFresnel, float alphaRoughness, float iridescenceFactor, float specularWeight, float VdotH, float NdotL, float NdotV, float NdotH) -{ - vec3 F = mix(F_Schlick(f0, f90, VdotH), iridescenceFresnel, iridescenceFactor); - float Vis = V_GGX(NdotL, NdotV, alphaRoughness); - float D = D_GGX(NdotH, alphaRoughness); - - return specularWeight * F * Vis * D; // Vis * D => specular_brdf -} -#endif - #ifdef MATERIAL_ANISOTROPY // GGX Distribution Anisotropic (Same as Babylon.js) // 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 return clamp(v, 0.0, 1.0); } -vec3 BRDF_specularGGXAnisotropy(vec3 f0, vec3 f90, float alphaRoughness, float anisotropy, vec3 n, vec3 v, vec3 l, vec3 h, vec3 t, vec3 b) +vec3 BRDF_specularGGXAnisotropy(float alphaRoughness, float anisotropy, vec3 n, vec3 v, vec3 l, vec3 h, vec3 t, vec3 b) { // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. float at = mix(alphaRoughness, 1.0, anisotropy * anisotropy); @@ -227,13 +195,11 @@ vec3 BRDF_specularGGXAnisotropy(vec3 f0, vec3 f90, float alphaRoughness, float a float NdotL = clamp(dot(n, l), 0.0, 1.0); float NdotH = clamp(dot(n, h), 0.001, 1.0); float NdotV = dot(n, v); - float VdotH = clamp(dot(v, h), 0.0, 1.0); float V = V_GGX_anisotropic(NdotL, NdotV, dot(b, v), dot(t, v), dot(t, l), dot(b, l), at, ab); float D = D_GGX_anisotropic(NdotH, dot(t, h), dot(b, h), anisotropy, at, ab); - vec3 F = F_Schlick(f0, f90, VdotH); - return F * V * D; + return vec3(V * D); } #endif diff --git a/source/Renderer/shaders/functions.glsl b/source/Renderer/shaders/functions.glsl index 1c7db9f0..b9179a0f 100644 --- a/source/Renderer/shaders/functions.glsl +++ b/source/Renderer/shaders/functions.glsl @@ -84,3 +84,10 @@ float applyIorToRoughness(float roughness, float ior) // an IOR of 1.5 results in the default amount of microfacet refraction. return roughness * clamp(ior * 2.0 - 2.0, 0.0, 1.0); } + +vec3 rgb_mix(vec3 base, vec3 layer, vec3 rgb_alpha) +{ + float rgb_alpha_max = max(rgb_alpha.r, max(rgb_alpha.g, rgb_alpha.b)); + return (1.0 - rgb_alpha_max) * base + rgb_alpha * layer; +} + diff --git a/source/Renderer/shaders/ibl.glsl b/source/Renderer/shaders/ibl.glsl index a2d2ff77..0e01b819 100644 --- a/source/Renderer/shaders/ibl.glsl +++ b/source/Renderer/shaders/ibl.glsl @@ -17,51 +17,48 @@ vec4 getSheenSample(vec3 reflection, float lod) return textureLod(u_CharlieEnvSampler, u_EnvRotation * reflection, lod) * u_EnvIntensity; } - -vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight) +vec3 getIBLGGXFresnel(vec3 n, vec3 v, vec3 F0, float roughness, float specularWeight) { + // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results + // Roughness dependent fresnel, from Fdez-Aguera float NdotV = clampedDot(n, v); - float lod = roughness * float(u_MipCount - 1); - vec3 reflection = normalize(reflect(-v, n)); - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; - vec4 specularSample = getSpecularSample(reflection, lod); - - vec3 specularLight = specularSample.rgb; + vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; + vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); + vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; + return FssEss; +} - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera +vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, float specularWeight) +{ + float NdotV = clampedDot(n, v); + vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); + vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = k_S * f_ab.x + f_ab.y; + vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low) - return specularWeight * specularLight * FssEss; + // Multiple scattering, from Fdez-Aguera + float Ems = (1.0 - (f_ab.x + f_ab.y)); + vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0); + vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); + 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) + return (FmsEms + k_D); } -#ifdef MATERIAL_IRIDESCENCE -vec3 getIBLRadianceGGXIridescence(vec3 n, vec3 v, float roughness, vec3 F0, vec3 iridescenceFresnel, float iridescenceFactor, float specularWeight) +vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness) { float NdotV = clampedDot(n, v); float lod = roughness * float(u_MipCount - 1); vec3 reflection = normalize(reflect(-v, n)); - - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; vec4 specularSample = getSpecularSample(reflection, lod); vec3 specularLight = specularSample.rgb; - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera - vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; - vec3 k_S = mix(F0 + Fr * pow(1.0 - NdotV, 5.0), iridescenceFresnel, iridescenceFactor); - vec3 FssEss = k_S * f_ab.x + f_ab.y; - - return specularWeight * specularLight * FssEss; + return specularLight; } -#endif #ifdef MATERIAL_TRANSMISSION @@ -130,68 +127,8 @@ vec3 getIBLVolumeRefraction(vec3 n, vec3 v, float perceptualRoughness, vec3 base #endif -// specularWeight is introduced with KHR_materials_specular -vec3 getIBLRadianceLambertian(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, float specularWeight) -{ - float NdotV = clampedDot(n, v); - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; - - vec3 irradiance = getDiffuseLight(n); - - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera - - vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; - vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low) - - // Multiple scattering, from Fdez-Aguera - float Ems = (1.0 - (f_ab.x + f_ab.y)); - vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0); - vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); - 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) - - return (FmsEms + k_D) * irradiance; -} - - -#ifdef MATERIAL_IRIDESCENCE -// specularWeight is introduced with KHR_materials_specular -vec3 getIBLRadianceLambertianIridescence(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, vec3 iridescenceF0, float iridescenceFactor, float specularWeight) -{ - float NdotV = clampedDot(n, v); - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; - - vec3 irradiance = getDiffuseLight(n); - - // Use the maximum component of the iridescence Fresnel color - // Maximum is used instead of the RGB value to not get inverse colors for the diffuse BRDF - vec3 iridescenceF0Max = vec3(max(max(iridescenceF0.r, iridescenceF0.g), iridescenceF0.b)); - - // Blend between base F0 and iridescence F0 - vec3 mixedF0 = mix(F0, iridescenceF0Max, iridescenceFactor); - - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera - - vec3 Fr = max(vec3(1.0 - roughness), mixedF0) - mixedF0; - vec3 k_S = mixedF0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low) - - // Multiple scattering, from Fdez-Aguera - float Ems = (1.0 - (f_ab.x + f_ab.y)); - vec3 F_avg = specularWeight * (mixedF0 + (1.0 - mixedF0) / 21.0); - vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); - 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) - - return (FmsEms + k_D) * irradiance; -} -#endif - #ifdef MATERIAL_ANISOTROPY -vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy, vec3 anisotropyDirection, vec3 F0, float specularWeight) +vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy, vec3 anisotropyDirection) { float NdotV = clampedDot(n, v); @@ -205,19 +142,11 @@ vec3 getIBLRadianceAnisotropy(vec3 n, vec3 v, float roughness, float anisotropy, float lod = roughness * float(u_MipCount - 1); vec3 reflection = normalize(reflect(-v, bentNormal)); - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; vec4 specularSample = getSpecularSample(reflection, lod); vec3 specularLight = specularSample.rgb; - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera - vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; - vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = k_S * f_ab.x + f_ab.y; - - return specularWeight * specularLight * FssEss; + return specularLight; } #endif diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index aefe9c85..a4dca937 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -65,6 +65,7 @@ struct MaterialInfo float ior; float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) vec3 f0; // full reflectance color (n incidence angle) + vec3 f0_dielectric; float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) vec3 c_diff; @@ -72,6 +73,7 @@ struct MaterialInfo float fresnel_w; vec3 f90; // reflectance color at grazing angle + vec3 f90_dielectric; float metallic; vec3 baseColor; @@ -282,9 +284,9 @@ MaterialInfo getSpecularInfo(MaterialInfo info) specularTexture.rgb = texture(u_SpecularColorSampler, getSpecularColorUV()).rgb; #endif - vec3 dielectricSpecularF0 = min(info.f0 * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); - info.f0 = mix(dielectricSpecularF0, info.baseColor.rgb, info.metallic); + info.f0_dielectric = min(info.f0 * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); info.specularWeight = u_KHR_materials_specular_specularFactor * specularTexture.a; + info.f90_dielectric = info.specularWeight; info.c_diff = mix(info.baseColor.rgb, vec3(0), info.metallic); return info; } diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 643a22d7..d7948e0c 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -40,6 +40,7 @@ void main() #if ALPHAMODE == ALPHAMODE_OPAQUE baseColor.a = 1.0; #endif + vec3 color = vec3(0); vec3 v = normalize(u_Camera - v_Position); NormalInfo normalInfo = getNormalInfo(v); @@ -57,8 +58,12 @@ void main() // The default index of refraction of 1.5 yields a dielectric normal incidence reflectance of 0.04. materialInfo.ior = 1.5; materialInfo.f0 = vec3(0.04); + materialInfo.f0_dielectric = materialInfo.f0; materialInfo.specularWeight = 1.0; - materialInfo.fresnel_w = pow(1 - abs(VdotH), 5); + + // Anything less than 2% is physically impossible and is instead considered to be shadowing. Compare to "Real-Time-Rendering" 4th editon on page 325. + materialInfo.f90 = vec3(1.0); + materialInfo.f90_dielectric = materialInfo.f90; // If the MR debug output is selected, we have to enforce evaluation of the non-iridescence BRDF functions. #if DEBUG == DEBUG_METALLIC_ROUGHNESS @@ -115,17 +120,23 @@ void main() // Compute reflectance. float reflectance = max(max(materialInfo.f0.r, materialInfo.f0.g), materialInfo.f0.b); - // Anything less than 2% is physically impossible and is instead considered to be shadowing. Compare to "Real-Time-Rendering" 4th editon on page 325. - materialInfo.f90 = vec3(1.0); - // LIGHTING - vec3 f_specular = vec3(0.0); + vec3 f_specular_dielectric = vec3(0.0); + vec3 f_specular_metal = vec3(0.0); vec3 f_diffuse = vec3(0.0); + vec3 f_dielectric_brdf_ibl = vec3(0.0); + vec3 f_metal_brdf_ibl = vec3(0.0); + vec3 f_specular_fresnel_ibl = vec3(0.0); + vec3 f_diffuse_fresnel_ibl = vec3(0.0); + vec3 f_metal_fresnel_ibl = vec3(0.0); vec3 f_emissive = vec3(0.0); vec3 f_clearcoat = vec3(0.0); vec3 f_sheen = vec3(0.0); vec3 f_transmission = vec3(0.0); + float clearcoatFactor = 0.0; + vec3 clearcoatFresnel = vec3(0); + float albedoSheenScaling = 1.0; #ifdef MATERIAL_IRIDESCENCE @@ -137,48 +148,82 @@ void main() } #endif +#ifdef MATERIAL_CLEARCOAT + clearcoatFactor = materialInfo.clearcoatFactor; + clearcoatFresnel = F_Schlick(materialInfo.clearcoatF0, materialInfo.clearcoatF90, clampedDot(materialInfo.clearcoatNormal, v)); +#endif + // Calculate lighting contribution from image based lighting source (IBL) #ifdef USE_IBL -#ifdef MATERIAL_IRIDESCENCE - f_specular += getIBLRadianceGGXIridescence(n, v, materialInfo.perceptualRoughness, materialInfo.f0, iridescenceFresnel, materialInfo.iridescenceFactor, materialInfo.specularWeight); - f_diffuse += getIBLRadianceLambertianIridescence(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, iridescenceF0, materialInfo.iridescenceFactor, materialInfo.specularWeight); -#elif defined(MATERIAL_ANISOTROPY) - f_specular += getIBLRadianceAnisotropy(n, v, materialInfo.perceptualRoughness, materialInfo.anisotropyStrength, materialInfo.anisotropicB, materialInfo.f0, materialInfo.specularWeight); - f_diffuse += getIBLRadianceLambertian(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, materialInfo.specularWeight); + // Calculate fresnel mix for IBL + f_specular_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.f0_dielectric, materialInfo.perceptualRoughness, materialInfo.specularWeight); + f_diffuse_fresnel_ibl = getIBLLambertianFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, materialInfo.specularWeight); + f_metal_fresnel_ibl = getIBLGGXFresnel(n, v, baseColor.rgb, materialInfo.perceptualRoughness, 1.0); + f_diffuse = getDiffuseLight(n); + +#if defined(MATERIAL_TRANSMISSION) && defined(USE_IBL) + f_transmission = getIBLVolumeRefraction( + n, v, + materialInfo.perceptualRoughness, + materialInfo.c_diff, materialInfo.f0, materialInfo.f90, + v_Position, u_ModelMatrix, u_ViewMatrix, u_ProjectionMatrix, + materialInfo.ior, materialInfo.thickness, materialInfo.attenuationColor, materialInfo.attenuationDistance, materialInfo.dispersion); + f_diffuse = mix(f_diffuse, f_transmission, materialInfo.transmissionFactor); +#endif + +#ifdef MATERIAL_ANISOTROPY + f_specular_metal = getIBLRadianceAnisotropy(n, v, materialInfo.perceptualRoughness, materialInfo.anisotropyStrength, materialInfo.anisotropicB); + f_specular_dielectric = f_specular_metal; #else - f_specular += getIBLRadianceGGX(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); - f_diffuse += getIBLRadianceLambertian(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, materialInfo.specularWeight); + f_specular_metal = getIBLRadianceGGX(n, v, materialInfo.perceptualRoughness); + f_specular_dielectric = f_specular_metal; #endif + f_metal_brdf_ibl = f_metal_fresnel_ibl * f_specular_metal; + f_dielectric_brdf_ibl = f_diffuse_fresnel_ibl * f_diffuse + f_specular_fresnel_ibl * f_specular_dielectric; + +#ifdef MATERIAL_IRIDESCENCE + f_metal_brdf_ibl = mix(f_metal_brdf_ibl, f_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); + f_dielectric_brdf_ibl = mix(f_dielectric_brdf_ibl, rgb_mix(f_diffuse, f_specular_dielectric, iridescenceFresnel), materialInfo.iridescenceFactor); +#endif + + #ifdef MATERIAL_CLEARCOAT - f_clearcoat += getIBLRadianceGGX(materialInfo.clearcoatNormal, v, materialInfo.clearcoatRoughness, materialInfo.clearcoatF0, 1.0); + f_clearcoat = getIBLRadianceGGX(materialInfo.clearcoatNormal, v, materialInfo.clearcoatRoughness); #endif #ifdef MATERIAL_SHEEN - f_sheen += getIBLRadianceCharlie(n, v, materialInfo.sheenRoughnessFactor, materialInfo.sheenColorFactor); + f_sheen = getIBLRadianceCharlie(n, v, materialInfo.sheenRoughnessFactor, materialInfo.sheenColorFactor); albedoSheenScaling = 1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotV, materialInfo.sheenRoughnessFactor); #endif + + color = mix(f_dielectric_brdf_ibl, f_metal_brdf_ibl, materialInfo.metallic); + color = f_sheen + color * albedoSheenScaling; + color = color * (1.0 - clearcoatFactor * clearcoatFresnel) + f_clearcoat; + +#ifdef HAS_OCCLUSION_MAP + float ao = 1.0; + ao = texture(u_OcclusionSampler, getOcclusionUV()).r; + color = color * (1.0 + u_OcclusionStrength * (ao - 1.0)); #endif -#if defined(MATERIAL_TRANSMISSION) && defined(USE_IBL) - f_transmission += getIBLVolumeRefraction( - n, v, - materialInfo.perceptualRoughness, - materialInfo.c_diff, materialInfo.f0, materialInfo.f90, - v_Position, u_ModelMatrix, u_ViewMatrix, u_ProjectionMatrix, - materialInfo.ior, materialInfo.thickness, materialInfo.attenuationColor, materialInfo.attenuationDistance, materialInfo.dispersion); #endif - vec3 f_diffuse_ibl = f_diffuse; - vec3 f_specular_ibl = f_specular; + vec3 f_sheen_ibl = f_sheen; vec3 f_clearcoat_ibl = f_clearcoat; f_diffuse = vec3(0.0); - f_specular = vec3(0.0); + f_specular_dielectric = vec3(0.0); + f_specular_metal = vec3(0.0); + vec3 f_dielectric_brdf = vec3(0.0); + vec3 f_metal_brdf = vec3(0.0); f_sheen = vec3(0.0); f_clearcoat = vec3(0.0); -#ifdef USE_PUNCTUAL +#ifdef USE_PUNCTUAL2 + //vec3 dielectric_brdf = mix(diffuse, specular_dielectric, dielectric_fresnel); + //vec3 metal_brdf = metal_fresnel * specular_metal; + for (int i = 0; i < LIGHT_COUNT; ++i) { Light light = u_Lights[i]; @@ -201,39 +246,18 @@ void main() float NdotH = clampedDot(n, h); float LdotH = clampedDot(l, h); float VdotH = clampedDot(v, h); - if (NdotL > 0.0 || NdotV > 0.0) - { - // Calculation of analytical light - // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB - vec3 intensity = getLighIntensity(light, pointToLight); - vec3 l_diffuse = vec3(0.0); - vec3 l_specular = vec3(0.0); -#ifdef MATERIAL_IRIDESCENCE - l_diffuse += intensity * NdotL * BRDF_lambertianIridescence(materialInfo.f0, materialInfo.f90, iridescenceFresnel, materialInfo.iridescenceFactor, materialInfo.c_diff, materialInfo.specularWeight, VdotH); - l_specular += intensity * NdotL * BRDF_specularGGXIridescence(materialInfo.f0, materialInfo.f90, iridescenceFresnel, materialInfo.alphaRoughness, materialInfo.iridescenceFactor, materialInfo.specularWeight, VdotH, NdotL, NdotV, NdotH); -#elif defined(MATERIAL_ANISOTROPY) - l_diffuse += intensity * NdotL * BRDF_lambertian(materialInfo.f0, materialInfo.f90, materialInfo.c_diff, materialInfo.specularWeight, VdotH); - l_specular += intensity * NdotL * BRDF_specularGGXAnisotropy(materialInfo.f0, materialInfo.f90, materialInfo.alphaRoughness, materialInfo.anisotropyStrength, n, v, l, h, materialInfo.anisotropicT, materialInfo.anisotropicB); -#else - l_diffuse += intensity * NdotL * BRDF_lambertian(materialInfo.f0, materialInfo.f90, materialInfo.c_diff, materialInfo.specularWeight, VdotH); - l_specular += intensity * NdotL * BRDF_specularGGX(materialInfo.f0, materialInfo.f90, materialInfo.alphaRoughness, materialInfo.specularWeight, VdotH, NdotL, NdotV, NdotH); -#endif -#ifdef MATERIAL_SHEEN - f_sheen += intensity * getPunctualRadianceSheen(materialInfo.sheenColorFactor, materialInfo.sheenRoughnessFactor, NdotL, NdotV, NdotH); - float l_albedoSheenScaling = min(1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotV, materialInfo.sheenRoughnessFactor), - 1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotL, materialInfo.sheenRoughnessFactor)); - l_diffuse *= l_albedoSheenScaling; - l_specular *= l_albedoSheenScaling; -#endif - f_diffuse += l_diffuse; - f_specular += l_specular; - -#ifdef MATERIAL_CLEARCOAT - f_clearcoat += intensity * getPunctualRadianceClearCoat(materialInfo.clearcoatNormal, v, l, h, VdotH, - materialInfo.clearcoatF0, materialInfo.clearcoatF90, materialInfo.clearcoatRoughness); -#endif - } + vec3 dielectric_fresnel = F_Schlick(materialInfo.f0_dielectric * materialInfo.specularWeight, materialInfo.f90_dielectric, NdotV); + vec3 metal_fresnel = baseColor.rgb + (vec3(1.0) - baseColor.rgb) * pow(1 - abs(VdotH), 5); + + vec3 l_diffuse = BRDF_lambertian(baseColor.rgb); + vec3 l_specular_dielectric = vec3(0.0); + vec3 l_specular_metal = vec3(0.0); + vec3 l_dielectric_brdf = vec3(0.0); + vec3 l_metal_brdf = vec3(0.0); + vec3 l_clearcoat = vec3(0.0); + vec3 l_sheen = vec3(0.0); + float l_albedoSheenScaling = 1.0; // BTDF (Bidirectional Transmittance Distribution Function) #ifdef MATERIAL_TRANSMISSION @@ -249,9 +273,46 @@ void main() #ifdef MATERIAL_VOLUME transmittedLight = applyVolumeAttenuation(transmittedLight, length(transmissionRay), materialInfo.attenuationColor, materialInfo.attenuationDistance); #endif + l_diffuse = mix(l_diffuse, transmittedLight, materialInfo.transmissionFactor); +#endif + + if (NdotL > 0.0 || NdotV > 0.0) + { + // Calculation of analytical light + // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB + vec3 intensity = getLighIntensity(light, pointToLight); + +#ifdef MATERIAL_ANISOTROPY + l_specular_metal = intensity * NdotL * BRDF_specularGGXAnisotropy(materialInfo.alphaRoughness, materialInfo.anisotropyStrength, n, v, l, h, materialInfo.anisotropicT, materialInfo.anisotropicB); + l_specular_dielectric = l_specular_metal; +#else + l_specular_metal = intensity * NdotL * BRDF_specularGGX(materialInfo.alphaRoughness, NdotL, NdotV, NdotH); + l_specular_dielectric = l_specular_metal; +#endif + + l_metal_brdf = metal_fresnel * l_specular_metal; + l_dielectric_brdf = mix(l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? + +#ifdef MATERIAL_IRIDESCENCE + l_metal_brdf = mix(l_metal_brdf, l_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); + l_dielectric_brdf = mix(l_dielectric_brdf, rgb_mix(l_diffuse, l_specular_dielectric, iridescenceFresnel), materialInfo.iridescenceFactor); +#endif - f_transmission += transmittedLight; +#ifdef MATERIAL_CLEARCOAT + l_clearcoat = intensity * getPunctualRadianceClearCoat(materialInfo.clearcoatNormal, v, l, h, VdotH, + materialInfo.clearcoatF0, materialInfo.clearcoatF90, materialInfo.clearcoatRoughness); #endif + +#ifdef MATERIAL_SHEEN + l_sheen = intensity * getPunctualRadianceSheen(materialInfo.sheenColorFactor, materialInfo.sheenRoughnessFactor, NdotL, NdotV, NdotH); + l_albedoSheenScaling = min(1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotV, materialInfo.sheenRoughnessFactor), + 1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotL, materialInfo.sheenRoughnessFactor)); +#endif + } + vec3 l_color = mix(l_dielectric_brdf, l_metal_brdf, materialInfo.metallic); + l_color = l_sheen + l_color * l_albedoSheenScaling; + l_color = l_color * (1.0 - clearcoatFactor * clearcoatFresnel) + l_clearcoat; + color += l_color; } #endif @@ -263,48 +324,11 @@ void main() f_emissive *= texture(u_EmissiveSampler, getEmissiveUV()).rgb; #endif - // Layer blending - float clearcoatFactor = 0.0; - vec3 clearcoatFresnel = vec3(0); - vec3 diffuse; - vec3 specular; - vec3 sheen; - vec3 clearcoat; - - float ao = 1.0; - // Apply optional PBR terms for additional (optional) shading -#ifdef HAS_OCCLUSION_MAP - ao = texture(u_OcclusionSampler, getOcclusionUV()).r; - diffuse = f_diffuse + mix(f_diffuse_ibl, f_diffuse_ibl * ao, u_OcclusionStrength) * albedoSheenScaling; - // apply ambient occlusion to all lighting that is not punctual - specular = f_specular + mix(f_specular_ibl, f_specular_ibl * ao, u_OcclusionStrength) * albedoSheenScaling; - sheen = f_sheen + mix(f_sheen_ibl, f_sheen_ibl * ao, u_OcclusionStrength); - clearcoat = f_clearcoat + mix(f_clearcoat_ibl, f_clearcoat_ibl * ao, u_OcclusionStrength); -#else - diffuse = f_diffuse_ibl * albedoSheenScaling + f_diffuse; - specular = f_specular_ibl * albedoSheenScaling + f_specular; - sheen = f_sheen_ibl + f_sheen; - clearcoat = f_clearcoat_ibl + f_clearcoat; -#endif - -#ifdef MATERIAL_CLEARCOAT - clearcoatFactor = materialInfo.clearcoatFactor; - clearcoatFresnel = F_Schlick(materialInfo.clearcoatF0, materialInfo.clearcoatF90, clampedDot(materialInfo.clearcoatNormal, v)); - clearcoat *= clearcoatFactor; -#endif - -#ifdef MATERIAL_TRANSMISSION - diffuse = mix(diffuse, f_transmission, materialInfo.transmissionFactor); -#endif - - vec3 color = vec3(0); #ifdef MATERIAL_UNLIT color = baseColor.rgb; #else - color = f_emissive + diffuse + specular; - color = sheen + color; - color = color * (1.0 - clearcoatFactor * clearcoatFresnel) + clearcoat; + color = f_emissive + color; #endif #if DEBUG == DEBUG_NONE diff --git a/source/Renderer/shaders/punctual.glsl b/source/Renderer/shaders/punctual.glsl index 1e7af287..be6d91a2 100644 --- a/source/Renderer/shaders/punctual.glsl +++ b/source/Renderer/shaders/punctual.glsl @@ -98,7 +98,7 @@ vec3 getPunctualRadianceClearCoat(vec3 clearcoatNormal, vec3 v, vec3 l, vec3 h, float NdotL = clampedDot(clearcoatNormal, l); float NdotV = clampedDot(clearcoatNormal, v); float NdotH = clampedDot(clearcoatNormal, h); - return NdotL * BRDF_specularGGX(f0, f90, clearcoatRoughness * clearcoatRoughness, 1.0, VdotH, NdotL, NdotV, NdotH); + return NdotL * BRDF_specularGGX(clearcoatRoughness * clearcoatRoughness, NdotL, NdotV, NdotH); } From 1e974990a5f2d8f7ad9d569a094b0e771191ef8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Thu, 11 Jul 2024 16:14:43 +0200 Subject: [PATCH 03/18] Fix shader error --- source/Renderer/shaders/material_info.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index a4dca937..e5462696 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -286,7 +286,7 @@ MaterialInfo getSpecularInfo(MaterialInfo info) info.f0_dielectric = min(info.f0 * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); info.specularWeight = u_KHR_materials_specular_specularFactor * specularTexture.a; - info.f90_dielectric = info.specularWeight; + info.f90_dielectric = vec3(info.specularWeight); info.c_diff = mix(info.baseColor.rgb, vec3(0), info.metallic); return info; } From afed40287063dfd8951170258a942e1cffcf410e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Thu, 11 Jul 2024 17:35:40 +0200 Subject: [PATCH 04/18] Fix clearcoat --- source/Renderer/shaders/pbr.frag | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index d7948e0c..cc391cf9 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -130,7 +130,7 @@ void main() vec3 f_diffuse_fresnel_ibl = vec3(0.0); vec3 f_metal_fresnel_ibl = vec3(0.0); vec3 f_emissive = vec3(0.0); - vec3 f_clearcoat = vec3(0.0); + vec3 clearcoat_brdf = vec3(0.0); vec3 f_sheen = vec3(0.0); vec3 f_transmission = vec3(0.0); @@ -189,7 +189,7 @@ void main() #ifdef MATERIAL_CLEARCOAT - f_clearcoat = getIBLRadianceGGX(materialInfo.clearcoatNormal, v, materialInfo.clearcoatRoughness); + clearcoat_brdf = getIBLRadianceGGX(materialInfo.clearcoatNormal, v, materialInfo.clearcoatRoughness); #endif #ifdef MATERIAL_SHEEN @@ -199,7 +199,7 @@ void main() color = mix(f_dielectric_brdf_ibl, f_metal_brdf_ibl, materialInfo.metallic); color = f_sheen + color * albedoSheenScaling; - color = color * (1.0 - clearcoatFactor * clearcoatFresnel) + f_clearcoat; + color = mix(color, clearcoat_brdf, clearcoatFactor * clearcoatFresnel); #ifdef HAS_OCCLUSION_MAP float ao = 1.0; @@ -209,16 +209,11 @@ void main() #endif - - vec3 f_sheen_ibl = f_sheen; - vec3 f_clearcoat_ibl = f_clearcoat; f_diffuse = vec3(0.0); f_specular_dielectric = vec3(0.0); f_specular_metal = vec3(0.0); vec3 f_dielectric_brdf = vec3(0.0); vec3 f_metal_brdf = vec3(0.0); - f_sheen = vec3(0.0); - f_clearcoat = vec3(0.0); #ifdef USE_PUNCTUAL2 //vec3 dielectric_brdf = mix(diffuse, specular_dielectric, dielectric_fresnel); @@ -255,7 +250,7 @@ void main() vec3 l_specular_metal = vec3(0.0); vec3 l_dielectric_brdf = vec3(0.0); vec3 l_metal_brdf = vec3(0.0); - vec3 l_clearcoat = vec3(0.0); + vec3 l_clearcoat_brdf = vec3(0.0); vec3 l_sheen = vec3(0.0); float l_albedoSheenScaling = 1.0; @@ -299,7 +294,7 @@ void main() #endif #ifdef MATERIAL_CLEARCOAT - l_clearcoat = intensity * getPunctualRadianceClearCoat(materialInfo.clearcoatNormal, v, l, h, VdotH, + l_clearcoat_brdf = intensity * getPunctualRadianceClearCoat(materialInfo.clearcoatNormal, v, l, h, VdotH, materialInfo.clearcoatF0, materialInfo.clearcoatF90, materialInfo.clearcoatRoughness); #endif @@ -311,7 +306,7 @@ void main() } vec3 l_color = mix(l_dielectric_brdf, l_metal_brdf, materialInfo.metallic); l_color = l_sheen + l_color * l_albedoSheenScaling; - l_color = l_color * (1.0 - clearcoatFactor * clearcoatFresnel) + l_clearcoat; + color = mix(l_color, l_clearcoat_brdf, clearcoatFactor * clearcoatFresnel); color += l_color; } #endif @@ -328,7 +323,7 @@ void main() #ifdef MATERIAL_UNLIT color = baseColor.rgb; #else - color = f_emissive + color; + color = f_emissive * (1.0 - clearcoatFactor * clearcoatFresnel) + color; #endif #if DEBUG == DEBUG_NONE From 56abd6c637d98c85d60e4f15954b08d717daaf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Thu, 11 Jul 2024 17:51:47 +0200 Subject: [PATCH 05/18] Fix specularWeight in IBL --- source/Renderer/shaders/ibl.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Renderer/shaders/ibl.glsl b/source/Renderer/shaders/ibl.glsl index 0e01b819..ceab900a 100644 --- a/source/Renderer/shaders/ibl.glsl +++ b/source/Renderer/shaders/ibl.glsl @@ -26,7 +26,7 @@ vec3 getIBLGGXFresnel(vec3 n, vec3 v, vec3 F0, float roughness, float specularWe vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; + vec3 FssEss = specularWeight * (k_S * f_ab.x + f_ab.y); return FssEss; } @@ -37,7 +37,7 @@ vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = specularWeight * k_S * f_ab.x + f_ab.y; // <--- GGX / specular light contribution (scale it down if the specularWeight is low) + vec3 FssEss = specularWeight * (k_S * f_ab.x + f_ab.y); // <--- GGX / specular light contribution (scale it down if the specularWeight is low) // Multiple scattering, from Fdez-Aguera float Ems = (1.0 - (f_ab.x + f_ab.y)); From 781e518043043bb7bf06e7d65c59b6408aec7ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Thu, 11 Jul 2024 18:29:36 +0200 Subject: [PATCH 06/18] Fix specular glossiness --- source/Renderer/shaders/material_info.glsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index e5462696..0870e2d5 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -224,6 +224,8 @@ MaterialInfo getSpecularGlossinessInfo(MaterialInfo info) info.f0 *= sgSample.rgb; // specular #endif // ! HAS_SPECULAR_GLOSSINESS_MAP + info.f0_dielectric = info.f0; + info.perceptualRoughness = 1.0 - info.perceptualRoughness; // 1 - glossiness info.c_diff = info.baseColor.rgb * (1.0 - max(max(info.f0.r, info.f0.g), info.f0.b)); return info; From dce179ef6a12d292355f2c65c233fe780d303cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Fri, 12 Jul 2024 12:26:14 +0200 Subject: [PATCH 07/18] First fix for puctual lights --- source/Renderer/shaders/pbr.frag | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index cc391cf9..366967b5 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -215,7 +215,7 @@ void main() vec3 f_dielectric_brdf = vec3(0.0); vec3 f_metal_brdf = vec3(0.0); -#ifdef USE_PUNCTUAL2 +#ifdef USE_PUNCTUAL //vec3 dielectric_brdf = mix(diffuse, specular_dielectric, dielectric_fresnel); //vec3 metal_brdf = metal_fresnel * specular_metal; @@ -242,8 +242,8 @@ void main() float LdotH = clampedDot(l, h); float VdotH = clampedDot(v, h); - vec3 dielectric_fresnel = F_Schlick(materialInfo.f0_dielectric * materialInfo.specularWeight, materialInfo.f90_dielectric, NdotV); - vec3 metal_fresnel = baseColor.rgb + (vec3(1.0) - baseColor.rgb) * pow(1 - abs(VdotH), 5); + vec3 dielectric_fresnel = F_Schlick(materialInfo.f0_dielectric * materialInfo.specularWeight, materialInfo.f90_dielectric, abs(VdotH)); + vec3 metal_fresnel = F_Schlick(baseColor.rgb, vec3(1.0), abs(VdotH)); vec3 l_diffuse = BRDF_lambertian(baseColor.rgb); vec3 l_specular_dielectric = vec3(0.0); @@ -271,8 +271,6 @@ void main() l_diffuse = mix(l_diffuse, transmittedLight, materialInfo.transmissionFactor); #endif - if (NdotL > 0.0 || NdotV > 0.0) - { // Calculation of analytical light // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB vec3 intensity = getLighIntensity(light, pointToLight); @@ -286,7 +284,7 @@ void main() #endif l_metal_brdf = metal_fresnel * l_specular_metal; - l_dielectric_brdf = mix(l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? + l_dielectric_brdf = mix(intensity * l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? #ifdef MATERIAL_IRIDESCENCE l_metal_brdf = mix(l_metal_brdf, l_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); @@ -303,10 +301,9 @@ void main() l_albedoSheenScaling = min(1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotV, materialInfo.sheenRoughnessFactor), 1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotL, materialInfo.sheenRoughnessFactor)); #endif - } vec3 l_color = mix(l_dielectric_brdf, l_metal_brdf, materialInfo.metallic); l_color = l_sheen + l_color * l_albedoSheenScaling; - color = mix(l_color, l_clearcoat_brdf, clearcoatFactor * clearcoatFresnel); + l_color = mix(l_color, l_clearcoat_brdf, clearcoatFactor * clearcoatFresnel); color += l_color; } #endif From c7111498d1510f6e6151e1c44d5b392b531a03a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Fri, 12 Jul 2024 12:57:55 +0200 Subject: [PATCH 08/18] Multiply diffuse with ndotl --- source/Renderer/shaders/pbr.frag | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 366967b5..3bf59c4c 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -270,7 +270,8 @@ void main() #endif l_diffuse = mix(l_diffuse, transmittedLight, materialInfo.transmissionFactor); #endif - + if (NdotL > 0.0 || NdotV > 0.0) + { // Calculation of analytical light // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB vec3 intensity = getLighIntensity(light, pointToLight); @@ -282,9 +283,10 @@ void main() l_specular_metal = intensity * NdotL * BRDF_specularGGX(materialInfo.alphaRoughness, NdotL, NdotV, NdotH); l_specular_dielectric = l_specular_metal; #endif + l_diffuse = intensity * NdotL * l_diffuse; l_metal_brdf = metal_fresnel * l_specular_metal; - l_dielectric_brdf = mix(intensity * l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? + l_dielectric_brdf = mix(l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? #ifdef MATERIAL_IRIDESCENCE l_metal_brdf = mix(l_metal_brdf, l_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); @@ -301,6 +303,7 @@ void main() l_albedoSheenScaling = min(1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotV, materialInfo.sheenRoughnessFactor), 1.0 - max3(materialInfo.sheenColorFactor) * albedoSheenScalingLUT(NdotL, materialInfo.sheenRoughnessFactor)); #endif + } vec3 l_color = mix(l_dielectric_brdf, l_metal_brdf, materialInfo.metallic); l_color = l_sheen + l_color * l_albedoSheenScaling; l_color = mix(l_color, l_clearcoat_brdf, clearcoatFactor * clearcoatFresnel); From d0b428c8946052cb640c4cf772686eb6c3abf3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Fri, 12 Jul 2024 15:55:06 +0200 Subject: [PATCH 09/18] Remove dead comments --- source/Renderer/shaders/brdf.glsl | 2 +- source/Renderer/shaders/pbr.frag | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/source/Renderer/shaders/brdf.glsl b/source/Renderer/shaders/brdf.glsl index 8718ceea..da16c3d3 100644 --- a/source/Renderer/shaders/brdf.glsl +++ b/source/Renderer/shaders/brdf.glsl @@ -152,7 +152,7 @@ float D_Charlie(float sheenRoughness, float NdotH) vec3 BRDF_lambertian(vec3 diffuseColor) { // see https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ - return (diffuseColor / M_PI); // 1.0 - specularWeight * => mix dielectric_fresnel * diffuse_bdrf + return (diffuseColor / M_PI); } // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#acknowledgments AppendixB diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 3bf59c4c..1c344c15 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -216,9 +216,6 @@ void main() vec3 f_metal_brdf = vec3(0.0); #ifdef USE_PUNCTUAL - //vec3 dielectric_brdf = mix(diffuse, specular_dielectric, dielectric_fresnel); - //vec3 metal_brdf = metal_fresnel * specular_metal; - for (int i = 0; i < LIGHT_COUNT; ++i) { Light light = u_Lights[i]; From 5aa9b6abb683d80a55a2fad995d713c02e4e380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Tue, 16 Jul 2024 11:04:04 +0200 Subject: [PATCH 10/18] Remove mix for f0 --- source/Renderer/shaders/material_info.glsl | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index 0870e2d5..39cd3451 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -249,7 +249,6 @@ MaterialInfo getMetallicRoughnessInfo(MaterialInfo info) // Achromatic f0 based on IOR. info.c_diff = mix(info.baseColor.rgb, vec3(0), info.metallic); - info.f0 = mix(info.f0, info.baseColor.rgb, info.metallic); return info; } #endif From 4c68aea0c6eea95b724ab4d1100bd9aded8c4379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Tue, 16 Jul 2024 11:55:52 +0200 Subject: [PATCH 11/18] Do not use c_diff in transmission --- source/Renderer/shaders/pbr.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 1c344c15..0913d2eb 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -165,7 +165,7 @@ void main() f_transmission = getIBLVolumeRefraction( n, v, materialInfo.perceptualRoughness, - materialInfo.c_diff, materialInfo.f0, materialInfo.f90, + baseColor.rgb, materialInfo.f0, materialInfo.f90, v_Position, u_ModelMatrix, u_ViewMatrix, u_ProjectionMatrix, materialInfo.ior, materialInfo.thickness, materialInfo.attenuationColor, materialInfo.attenuationDistance, materialInfo.dispersion); f_diffuse = mix(f_diffuse, f_transmission, materialInfo.transmissionFactor); @@ -260,7 +260,7 @@ void main() l = normalize(pointToLight); vec3 intensity = getLighIntensity(light, pointToLight); - vec3 transmittedLight = intensity * getPunctualRadianceTransmission(n, v, l, materialInfo.alphaRoughness, materialInfo.f0, materialInfo.f90, materialInfo.c_diff, materialInfo.ior); + vec3 transmittedLight = intensity * getPunctualRadianceTransmission(n, v, l, materialInfo.alphaRoughness, materialInfo.f0, materialInfo.f90, baseColor.rgb, materialInfo.ior); #ifdef MATERIAL_VOLUME transmittedLight = applyVolumeAttenuation(transmittedLight, length(transmissionRay), materialInfo.attenuationColor, materialInfo.attenuationDistance); From e558bb17ef82a3d6f212189096dbd6ebc5b556c8 Mon Sep 17 00:00:00 2001 From: Mathias Kanzler Date: Thu, 18 Jul 2024 11:23:51 +0200 Subject: [PATCH 12/18] Move FmsEms to getIBLGGXFresnel as mentioned in change request and use basecolor instead of c_diff --- source/Renderer/shaders/ibl.glsl | 18 ++++++++++++++---- source/Renderer/shaders/pbr.frag | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/source/Renderer/shaders/ibl.glsl b/source/Renderer/shaders/ibl.glsl index ceab900a..012a8f5c 100644 --- a/source/Renderer/shaders/ibl.glsl +++ b/source/Renderer/shaders/ibl.glsl @@ -27,11 +27,19 @@ vec3 getIBLGGXFresnel(vec3 n, vec3 v, vec3 F0, float roughness, float specularWe vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); vec3 FssEss = specularWeight * (k_S * f_ab.x + f_ab.y); - return FssEss; + + // Multiple scattering, from Fdez-Aguera + float Ems = (1.0 - (f_ab.x + f_ab.y)); + vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0); + vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); + + return FssEss + FmsEms; } -vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 diffuseColor, vec3 F0, float specularWeight) +vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight) { + // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results + // Roughness dependent fresnel, from Fdez-Aguera float NdotV = clampedDot(n, v); vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; @@ -43,8 +51,10 @@ vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 diffuseColor, float Ems = (1.0 - (f_ab.x + f_ab.y)); vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0); vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); - 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) - return (FmsEms + k_D); + + + vec3 k_D = (1.0 - (FssEss + FmsEms)); // we use (1.0 - (FssEss + FmsEms)) instead of (1.0 - FssEss + FmsEms) as indicated by the formula in the blog post (might be a typo in the implementation) + return k_D; } diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 0913d2eb..c3e71a82 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -157,9 +157,9 @@ void main() #ifdef USE_IBL // Calculate fresnel mix for IBL f_specular_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.f0_dielectric, materialInfo.perceptualRoughness, materialInfo.specularWeight); - f_diffuse_fresnel_ibl = getIBLLambertianFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, materialInfo.specularWeight); + f_diffuse_fresnel_ibl = getIBLLambertianFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); f_metal_fresnel_ibl = getIBLGGXFresnel(n, v, baseColor.rgb, materialInfo.perceptualRoughness, 1.0); - f_diffuse = getDiffuseLight(n); + f_diffuse = getDiffuseLight(n) * baseColor.rgb ; #if defined(MATERIAL_TRANSMISSION) && defined(USE_IBL) f_transmission = getIBLVolumeRefraction( From 422f054976fa63571f05141293c4033e05d12bff Mon Sep 17 00:00:00 2001 From: Mathias Kanzler Date: Thu, 18 Jul 2024 12:26:06 +0200 Subject: [PATCH 13/18] Simplify code --- source/Renderer/shaders/ibl.glsl | 24 +----------------------- source/Renderer/shaders/pbr.frag | 18 ++++++++---------- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/source/Renderer/shaders/ibl.glsl b/source/Renderer/shaders/ibl.glsl index 012a8f5c..875fbed7 100644 --- a/source/Renderer/shaders/ibl.glsl +++ b/source/Renderer/shaders/ibl.glsl @@ -17,7 +17,7 @@ vec4 getSheenSample(vec3 reflection, float lod) return textureLod(u_CharlieEnvSampler, u_EnvRotation * reflection, lod) * u_EnvIntensity; } -vec3 getIBLGGXFresnel(vec3 n, vec3 v, vec3 F0, float roughness, float specularWeight) +vec3 getIBLGGXFresnel(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight) { // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results // Roughness dependent fresnel, from Fdez-Aguera @@ -36,28 +36,6 @@ vec3 getIBLGGXFresnel(vec3 n, vec3 v, vec3 F0, float roughness, float specularWe return FssEss + FmsEms; } -vec3 getIBLLambertianFresnel(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight) -{ - // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results - // Roughness dependent fresnel, from Fdez-Aguera - float NdotV = clampedDot(n, v); - vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(u_GGXLUT, brdfSamplePoint).rg; - vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; - vec3 k_S = F0 + Fr * pow(1.0 - NdotV, 5.0); - vec3 FssEss = specularWeight * (k_S * f_ab.x + f_ab.y); // <--- GGX / specular light contribution (scale it down if the specularWeight is low) - - // Multiple scattering, from Fdez-Aguera - float Ems = (1.0 - (f_ab.x + f_ab.y)); - vec3 F_avg = specularWeight * (F0 + (1.0 - F0) / 21.0); - vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems); - - - vec3 k_D = (1.0 - (FssEss + FmsEms)); // we use (1.0 - (FssEss + FmsEms)) instead of (1.0 - FssEss + FmsEms) as indicated by the formula in the blog post (might be a typo in the implementation) - return k_D; -} - - vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness) { float NdotV = clampedDot(n, v); diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index c3e71a82..7863e225 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -126,9 +126,6 @@ void main() vec3 f_diffuse = vec3(0.0); vec3 f_dielectric_brdf_ibl = vec3(0.0); vec3 f_metal_brdf_ibl = vec3(0.0); - vec3 f_specular_fresnel_ibl = vec3(0.0); - vec3 f_diffuse_fresnel_ibl = vec3(0.0); - vec3 f_metal_fresnel_ibl = vec3(0.0); vec3 f_emissive = vec3(0.0); vec3 clearcoat_brdf = vec3(0.0); vec3 f_sheen = vec3(0.0); @@ -155,11 +152,6 @@ void main() // Calculate lighting contribution from image based lighting source (IBL) #ifdef USE_IBL - // Calculate fresnel mix for IBL - f_specular_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.f0_dielectric, materialInfo.perceptualRoughness, materialInfo.specularWeight); - f_diffuse_fresnel_ibl = getIBLLambertianFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); - f_metal_fresnel_ibl = getIBLGGXFresnel(n, v, baseColor.rgb, materialInfo.perceptualRoughness, 1.0); - f_diffuse = getDiffuseLight(n) * baseColor.rgb ; #if defined(MATERIAL_TRANSMISSION) && defined(USE_IBL) f_transmission = getIBLVolumeRefraction( @@ -179,8 +171,14 @@ void main() f_specular_dielectric = f_specular_metal; #endif + // Calculate fresnel mix for IBL + + vec3 f_metal_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, baseColor.rgb, 1.0); f_metal_brdf_ibl = f_metal_fresnel_ibl * f_specular_metal; - f_dielectric_brdf_ibl = f_diffuse_fresnel_ibl * f_diffuse + f_specular_fresnel_ibl * f_specular_dielectric; + + vec3 f_dielectric_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); + f_diffuse = getDiffuseLight(n) * baseColor.rgb ; + f_dielectric_brdf_ibl = mix(f_diffuse, f_specular_dielectric, f_dielectric_fresnel_ibl); #ifdef MATERIAL_IRIDESCENCE f_metal_brdf_ibl = mix(f_metal_brdf_ibl, f_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); @@ -207,7 +205,7 @@ void main() color = color * (1.0 + u_OcclusionStrength * (ao - 1.0)); #endif -#endif +#endif //end USE_IBL f_diffuse = vec3(0.0); f_specular_dielectric = vec3(0.0); From e58869e858d916e1f0aaa4e1a104e0d7d75032a8 Mon Sep 17 00:00:00 2001 From: Mathias Kanzler Date: Thu, 18 Jul 2024 14:26:22 +0200 Subject: [PATCH 14/18] Remove c_diff --- source/Renderer/shaders/material_info.glsl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index 39cd3451..dccd8ef6 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -68,7 +68,6 @@ struct MaterialInfo vec3 f0_dielectric; float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) - vec3 c_diff; float fresnel_w; @@ -227,7 +226,6 @@ MaterialInfo getSpecularGlossinessInfo(MaterialInfo info) info.f0_dielectric = info.f0; info.perceptualRoughness = 1.0 - info.perceptualRoughness; // 1 - glossiness - info.c_diff = info.baseColor.rgb * (1.0 - max(max(info.f0.r, info.f0.g), info.f0.b)); return info; } #endif @@ -247,8 +245,6 @@ MaterialInfo getMetallicRoughnessInfo(MaterialInfo info) info.metallic *= mrSample.b; #endif - // Achromatic f0 based on IOR. - info.c_diff = mix(info.baseColor.rgb, vec3(0), info.metallic); return info; } #endif @@ -288,7 +284,6 @@ MaterialInfo getSpecularInfo(MaterialInfo info) info.f0_dielectric = min(info.f0 * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); info.specularWeight = u_KHR_materials_specular_specularFactor * specularTexture.a; info.f90_dielectric = vec3(info.specularWeight); - info.c_diff = mix(info.baseColor.rgb, vec3(0), info.metallic); return info; } #endif From 1292c8b7fbe52497a5f6ae216da46b83d85a35d3 Mon Sep 17 00:00:00 2001 From: Mathias Kanzler Date: Thu, 18 Jul 2024 14:32:47 +0200 Subject: [PATCH 15/18] Fix transmission --- source/Renderer/shaders/pbr.frag | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 7863e225..0f23bda9 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -153,6 +153,8 @@ void main() // Calculate lighting contribution from image based lighting source (IBL) #ifdef USE_IBL + f_diffuse = getDiffuseLight(n) * baseColor.rgb ; + #if defined(MATERIAL_TRANSMISSION) && defined(USE_IBL) f_transmission = getIBLVolumeRefraction( n, v, @@ -177,7 +179,6 @@ void main() f_metal_brdf_ibl = f_metal_fresnel_ibl * f_specular_metal; vec3 f_dielectric_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); - f_diffuse = getDiffuseLight(n) * baseColor.rgb ; f_dielectric_brdf_ibl = mix(f_diffuse, f_specular_dielectric, f_dielectric_fresnel_ibl); #ifdef MATERIAL_IRIDESCENCE From 6ac6e802a16799b6b95210d2e02a9f7d2e50cc82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Thu, 18 Jul 2024 17:45:36 +0200 Subject: [PATCH 16/18] Fix iridesence --- source/Renderer/shaders/material_info.glsl | 11 ++++------ source/Renderer/shaders/pbr.frag | 25 ++++++++++------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/source/Renderer/shaders/material_info.glsl b/source/Renderer/shaders/material_info.glsl index 2a7a1849..380c6689 100644 --- a/source/Renderer/shaders/material_info.glsl +++ b/source/Renderer/shaders/material_info.glsl @@ -68,7 +68,6 @@ struct MaterialInfo { float ior; float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) - vec3 f0; // full reflectance color (n incidence angle) vec3 f0_dielectric; float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) @@ -221,17 +220,15 @@ vec4 getBaseColor() #ifdef MATERIAL_SPECULARGLOSSINESS MaterialInfo getSpecularGlossinessInfo(MaterialInfo info) { - info.f0 = u_SpecularFactor; + info.f0_dielectric = u_SpecularFactor; info.perceptualRoughness = u_GlossinessFactor; #ifdef HAS_SPECULAR_GLOSSINESS_MAP vec4 sgSample = texture(u_SpecularGlossinessSampler, getSpecularGlossinessUV()); info.perceptualRoughness *= sgSample.a ; // glossiness to roughness - info.f0 *= sgSample.rgb; // specular + info.f0_dielectric *= sgSample.rgb; // specular #endif // ! HAS_SPECULAR_GLOSSINESS_MAP - info.f0_dielectric = info.f0; - info.perceptualRoughness = 1.0 - info.perceptualRoughness; // 1 - glossiness return info; } @@ -288,7 +285,7 @@ MaterialInfo getSpecularInfo(MaterialInfo info) specularTexture.rgb = texture(u_SpecularColorSampler, getSpecularColorUV()).rgb; #endif - info.f0_dielectric = min(info.f0 * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); + info.f0_dielectric = min(info.f0_dielectric * u_KHR_materials_specular_specularColorFactor * specularTexture.rgb, vec3(1.0)); info.specularWeight = u_KHR_materials_specular_specularFactor * specularTexture.a; info.f90_dielectric = vec3(info.specularWeight); return info; @@ -400,7 +397,7 @@ MaterialInfo getClearCoatInfo(MaterialInfo info, NormalInfo normalInfo) #ifdef MATERIAL_IOR MaterialInfo getIorInfo(MaterialInfo info) { - info.f0 = vec3(pow(( u_Ior - 1.0) / (u_Ior + 1.0), 2.0)); + info.f0_dielectric = vec3(pow(( u_Ior - 1.0) / (u_Ior + 1.0), 2.0)); info.ior = u_Ior; return info; } diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index 447e8ee2..e86c919f 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -57,8 +57,7 @@ void main() // The default index of refraction of 1.5 yields a dielectric normal incidence reflectance of 0.04. materialInfo.ior = 1.5; - materialInfo.f0 = vec3(0.04); - materialInfo.f0_dielectric = materialInfo.f0; + materialInfo.f0_dielectric = vec3(0.04); materialInfo.specularWeight = 1.0; // Anything less than 2% is physically impossible and is instead considered to be shadowing. Compare to "Real-Time-Rendering" 4th editon on page 325. @@ -121,8 +120,6 @@ void main() // convert to material roughness by squaring the perceptual roughness. materialInfo.alphaRoughness = materialInfo.perceptualRoughness * materialInfo.perceptualRoughness; - // Compute reflectance. - float reflectance = max(max(materialInfo.f0.r, materialInfo.f0.g), materialInfo.f0.b); // LIGHTING vec3 f_specular_dielectric = vec3(0.0); @@ -143,8 +140,8 @@ void main() float diffuseTransmissionThickness = 1.0; #ifdef MATERIAL_IRIDESCENCE - vec3 iridescenceFresnel = evalIridescence(1.0, materialInfo.iridescenceIor, NdotV, materialInfo.iridescenceThickness, materialInfo.f0); - vec3 iridescenceF0 = Schlick_to_F0(iridescenceFresnel, NdotV); + vec3 iridescenceFresnel_dielectric = evalIridescence(1.0, materialInfo.iridescenceIor, NdotV, materialInfo.iridescenceThickness, materialInfo.f0_dielectric); + vec3 iridescenceFresnel_metallic = evalIridescence(1.0, materialInfo.iridescenceIor, NdotV, materialInfo.iridescenceThickness, baseColor.rgb); if (materialInfo.iridescenceThickness == 0.0) { materialInfo.iridescenceFactor = 0.0; @@ -182,7 +179,7 @@ void main() f_specular_transmission = getIBLVolumeRefraction( n, v, materialInfo.perceptualRoughness, - baseColor.rgb, materialInfo.f0, materialInfo.f90, + baseColor.rgb, materialInfo.f0_dielectric, materialInfo.f90, v_Position, u_ModelMatrix, u_ViewMatrix, u_ProjectionMatrix, materialInfo.ior, materialInfo.thickness, materialInfo.attenuationColor, materialInfo.attenuationDistance, materialInfo.dispersion); f_diffuse = mix(f_diffuse, f_specular_transmission, materialInfo.transmissionFactor); @@ -201,12 +198,12 @@ void main() vec3 f_metal_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, baseColor.rgb, 1.0); f_metal_brdf_ibl = f_metal_fresnel_ibl * f_specular_metal; - vec3 f_dielectric_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0, materialInfo.specularWeight); + vec3 f_dielectric_fresnel_ibl = getIBLGGXFresnel(n, v, materialInfo.perceptualRoughness, materialInfo.f0_dielectric, materialInfo.specularWeight); f_dielectric_brdf_ibl = mix(f_diffuse, f_specular_dielectric, f_dielectric_fresnel_ibl); #ifdef MATERIAL_IRIDESCENCE - f_metal_brdf_ibl = mix(f_metal_brdf_ibl, f_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); - f_dielectric_brdf_ibl = mix(f_dielectric_brdf_ibl, rgb_mix(f_diffuse, f_specular_dielectric, iridescenceFresnel), materialInfo.iridescenceFactor); + f_metal_brdf_ibl = mix(f_metal_brdf_ibl, f_specular_metal * iridescenceFresnel_metallic, materialInfo.iridescenceFactor); + f_dielectric_brdf_ibl = mix(f_dielectric_brdf_ibl, rgb_mix(f_diffuse, f_specular_dielectric, iridescenceFresnel_dielectric), materialInfo.iridescenceFactor); #endif @@ -296,7 +293,7 @@ void main() pointToLight -= transmissionRay; l = normalize(pointToLight); - vec3 transmittedLight = lightIntensity * getPunctualRadianceTransmission(n, v, l, materialInfo.alphaRoughness, materialInfo.f0, materialInfo.f90, baseColor.rgb, materialInfo.ior); + vec3 transmittedLight = lightIntensity * getPunctualRadianceTransmission(n, v, l, materialInfo.alphaRoughness, materialInfo.f0_dielectric, materialInfo.f90, baseColor.rgb, materialInfo.ior); #ifdef MATERIAL_VOLUME transmittedLight = applyVolumeAttenuation(transmittedLight, length(transmissionRay), materialInfo.attenuationColor, materialInfo.attenuationDistance); @@ -320,8 +317,8 @@ void main() l_dielectric_brdf = mix(l_diffuse, l_specular_dielectric, dielectric_fresnel); // Do we need to handle vec3 fresnel here? #ifdef MATERIAL_IRIDESCENCE - l_metal_brdf = mix(l_metal_brdf, l_specular_metal * iridescenceFresnel, materialInfo.iridescenceFactor); - l_dielectric_brdf = mix(l_dielectric_brdf, rgb_mix(l_diffuse, l_specular_dielectric, iridescenceFresnel), materialInfo.iridescenceFactor); + l_metal_brdf = mix(l_metal_brdf, l_specular_metal * iridescenceFresnel_metallic, materialInfo.iridescenceFactor); + l_dielectric_brdf = mix(l_dielectric_brdf, rgb_mix(l_diffuse, l_specular_dielectric, iridescenceFresnel_dielectric), materialInfo.iridescenceFactor); #endif #ifdef MATERIAL_CLEARCOAT @@ -502,7 +499,7 @@ vec3 specularTexture = vec3(1.0); // Iridescence: #ifdef MATERIAL_IRIDESCENCE #if DEBUG == DEBUG_IRIDESCENCE - g_finalColor.rgb = iridescenceFresnel * materialInfo.iridescenceFactor; + g_finalColor.rgb = mix(iridescenceFresnel_dielectric, iridescenceFresnel_metallic, materialInfo.metallic) * materialInfo.iridescenceFactor; #endif #if DEBUG == DEBUG_IRIDESCENCE_FACTOR g_finalColor.rgb = vec3(materialInfo.iridescenceFactor); From cd8edf72f447deb7720e65c24119f74fcae6bb41 Mon Sep 17 00:00:00 2001 From: Mathias Kanzler Date: Tue, 23 Jul 2024 11:45:49 +0200 Subject: [PATCH 17/18] Remove unsupported debug channels and give debug views more descriptive names --- source/GltfState/gltf_state.js | 52 ++++++++++++-------------------- source/Renderer/shaders/pbr.frag | 21 ------------- 2 files changed, 19 insertions(+), 54 deletions(-) diff --git a/source/GltfState/gltf_state.js b/source/GltfState/gltf_state.js index ecea059c..ab1e6f4e 100644 --- a/source/GltfState/gltf_state.js +++ b/source/GltfState/gltf_state.js @@ -149,10 +149,8 @@ GltfState.DebugOutput = { EMISSIVE: "Emissive", }, - /** output metallic roughness */ + /** metallic roughness */ mr: { - /** output the combined metallic roughness */ - METALLIC_ROUGHNESS: "Metallic Roughness", /** output the base color value */ BASECOLOR: "Base Color", /** output the metallic value from pbr metallic roughness */ @@ -161,69 +159,57 @@ GltfState.DebugOutput = { ROUGHNESS: "Roughness", }, - /** output clearcoat lighting */ + /** KHR_materials_clearcoat */ clearcoat: { - /** output the combined clear coat */ - CLEARCOAT: "ClearCoat", - /** output the clear coat factor */ - CLEARCOAT_FACTOR: "ClearCoat Factor", + /** output the clear coat strength */ + CLEARCOAT_FACTOR: "ClearCoat Strength", /** output the clear coat roughness */ CLEARCOAT_ROUGHNESS: "ClearCoat Roughness", /** output the clear coat normal */ CLEARCOAT_NORMAL: "ClearCoat Normal", }, - /** output sheen lighting */ + /** KHR_materials_sheen */ sheen: { - /** output the combined sheen */ - SHEEN: "Sheen", /** output the sheen color*/ SHEEN_COLOR: "Sheen Color", /** output the sheen roughness*/ SHEEN_ROUGHNESS: "Sheen Roughness", }, - /** output specular lighting */ + /** KHR_materials_specular */ specular: { - /** output the combined specular */ - SPECULAR: "Specular", - /** output the specular factor*/ - SPECULAR_FACTOR: "Specular Factor", + /** output the specular strength*/ + SPECULAR_FACTOR: "Specular Strength", /** output the specular color*/ SPECULAR_COLOR: "Specular Color", }, - /** output tranmission lighting */ + /** KHR_materials_transmission */ transmission: { - /** output the combined transmission/volume */ - TRANSMISSION_VOLUME: "Transmission/Volume", - /** output the transmission factor*/ - TRANSMISSION_FACTOR: "Transmission Factor", + /** output the transmission strength*/ + TRANSMISSION_FACTOR: "Transmission Strength", /** output the volume thickness*/ VOLUME_THICKNESS: "Volume Thickness", }, - /** output diffuse tranmission lighting */ + /** KHR_materials_diffuse_tranmission */ diffuseTransmission: { - /** output the combined diffuse tranmission */ - DIFFUSE_TRANSMISSION: "Diffuse Transmission", - /** output the diffuse tranmission factor */ - DIFFUSE_TRANSMISSION_FACTOR: "Diffuse Transmission Factor", + /** output the diffuse tranmission strength */ + DIFFUSE_TRANSMISSION_FACTOR: "Diffuse Transmission Strength", /** output the diffuse tranmission color factor */ - DIFFUSE_TRANSMISSION_COLOR_FACTOR: "Diffuse Transmission Color Factor", + DIFFUSE_TRANSMISSION_COLOR_FACTOR: "Diffuse Transmission Color", }, - /** output iridescence */ + /** KHR_materials_iridescence */ iridescence: { - /** output the combined iridescence */ - IRIDESCENCE: "Iridescence", - /** output the iridescence factor*/ - IRIDESCENCE_FACTOR: "Iridescence Factor", + /** output the iridescence strength*/ + IRIDESCENCE_FACTOR: "Iridescence Strength", /** output the iridescence thickness*/ IRIDESCENCE_THICKNESS: "Iridescence Thickness", }, - /** output anisotropy */ + /** KHR_materials_anisotropy */ anisotropy: { /** output the anisotropic strength*/ ANISOTROPIC_STRENGTH: "Anisotropic Strength", diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index e86c919f..ae901f83 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -420,9 +420,6 @@ void main() // MR: #ifdef MATERIAL_METALLICROUGHNESS -#if DEBUG == DEBUG_METALLIC_ROUGHNESS - g_finalColor.rgb = linearTosRGB(diffuse + specular); -#endif #if DEBUG == DEBUG_METALLIC g_finalColor.rgb = vec3(materialInfo.metallic); #endif @@ -436,9 +433,6 @@ void main() // Clearcoat: #ifdef MATERIAL_CLEARCOAT -#if DEBUG == DEBUG_CLEARCOAT - g_finalColor.rgb = linearTosRGB(clearcoat); -#endif #if DEBUG == DEBUG_CLEARCOAT_FACTOR g_finalColor.rgb = vec3(materialInfo.clearcoatFactor); #endif @@ -452,9 +446,6 @@ void main() // Sheen: #ifdef MATERIAL_SHEEN -#if DEBUG == DEBUG_SHEEN - g_finalColor.rgb = linearTosRGB(sheen); -#endif #if DEBUG == DEBUG_SHEEN_COLOR g_finalColor.rgb = materialInfo.sheenColorFactor; #endif @@ -465,9 +456,6 @@ void main() // Specular: #ifdef MATERIAL_SPECULAR -#if DEBUG == DEBUG_SPECULAR - g_finalColor.rgb = linearTosRGB(specular); -#endif #if DEBUG == DEBUG_SPECULAR_FACTOR g_finalColor.rgb = vec3(materialInfo.specularWeight); #endif @@ -483,9 +471,6 @@ vec3 specularTexture = vec3(1.0); // Transmission, Volume: #ifdef MATERIAL_TRANSMISSION -#if DEBUG == DEBUG_TRANSMISSION_VOLUME - g_finalColor.rgb = linearTosRGB(f_specular_transmission * materialInfo.transmissionFactor); -#endif #if DEBUG == DEBUG_TRANSMISSION_FACTOR g_finalColor.rgb = vec3(materialInfo.transmissionFactor); #endif @@ -498,9 +483,6 @@ vec3 specularTexture = vec3(1.0); // Iridescence: #ifdef MATERIAL_IRIDESCENCE -#if DEBUG == DEBUG_IRIDESCENCE - g_finalColor.rgb = mix(iridescenceFresnel_dielectric, iridescenceFresnel_metallic, materialInfo.metallic) * materialInfo.iridescenceFactor; -#endif #if DEBUG == DEBUG_IRIDESCENCE_FACTOR g_finalColor.rgb = vec3(materialInfo.iridescenceFactor); #endif @@ -530,9 +512,6 @@ vec3 specularTexture = vec3(1.0); // Diffuse Transmission: #ifdef MATERIAL_DIFFUSE_TRANSMISSION -#if DEBUG == DEBUG_DIFFUSE_TRANSMISSION - g_finalColor.rgb = linearTosRGB(f_diffuse_transmission * vec3(materialInfo.diffuseTransmissionFactor)); -#endif #if DEBUG == DEBUG_DIFFUSE_TRANSMISSION_FACTOR g_finalColor.rgb = linearTosRGB(vec3(materialInfo.diffuseTransmissionFactor)); #endif From c22a47af7aac63cecb86c1ab4418d8ccbcdc9f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20H=C3=A4rtl?= Date: Tue, 23 Jul 2024 14:53:11 +0200 Subject: [PATCH 18/18] Remove unused variable --- source/Renderer/shaders/pbr.frag | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/Renderer/shaders/pbr.frag b/source/Renderer/shaders/pbr.frag index ae901f83..b285bf4b 100644 --- a/source/Renderer/shaders/pbr.frag +++ b/source/Renderer/shaders/pbr.frag @@ -170,8 +170,7 @@ void main() #ifdef MATERIAL_VOLUME diffuseTransmissionIBL = applyVolumeAttenuation(diffuseTransmissionIBL, diffuseTransmissionThickness, materialInfo.attenuationColor, materialInfo.attenuationDistance); #endif - f_diffuse_transmission += diffuseTransmissionIBL; - f_diffuse = mix(f_diffuse, f_diffuse_transmission, materialInfo.diffuseTransmissionFactor); + f_diffuse = mix(f_diffuse, diffuseTransmissionIBL, materialInfo.diffuseTransmissionFactor); #endif @@ -282,7 +281,6 @@ void main() diffuse_btdf = applyVolumeAttenuation(diffuse_btdf, diffuseTransmissionThickness, materialInfo.attenuationColor, materialInfo.attenuationDistance); #endif l_diffuse = mix(l_diffuse, diffuse_btdf, materialInfo.diffuseTransmissionFactor); - f_diffuse_transmission += diffuse_btdf; #endif // MATERIAL_DIFFUSE_TRANSMISSION // BTDF (Bidirectional Transmittance Distribution Function)