pex-gl / pex-renderer

Physically based renderer (PBR) and scene graph for PEX.
https://pex-gl.github.io/pex-renderer/examples/index.html
MIT License
234 stars 16 forks source link

Add energy compensation #198

Open dmnsgn opened 5 years ago

vorg commented 5 years ago

To be precise i mean multiscatter ggx preventing loosing energy from IBL for metallic materials

This is tested using Furnace Test with pure white environment map. As you can see rough material on the right is darker than glossy on the left.

Screenshot 2019-04-25 at 16 47 41

vorg commented 5 years ago

Examples here https://doc.babylonjs.com/how_to/physically_based_rendering_master#energy-conservation

vorg commented 4 years ago

Original (?) source of discussion https://eheitzresearch.wordpress.com/240-2/

multiplescatteringsmith_res1

Excellent explanation of math https://patapom.com/blog/BRDF/MSBRDFEnergyCompensation/

Screenshot 2019-08-06 at 14 05 57

ThreeJS PR https://github.com/mrdoob/three.js/pull/15644

51778960-5d6d6600-20b9-11e9-9311-ca8b060dc8fe

Filament implementation https://google.github.io/filament/Filament.md.html#materialsystem/improvingthebrdfs/energylossinspecularreflectance

Screenshot 2019-08-06 at 14 22 39

vorg commented 10 months ago

There is some work done here https://github.com/pex-gl/pex-renderer/issues/331

dmnsgn commented 1 month ago

A Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting

// GLSL code for dielectrics
// Common code for single and multiple scattering
// Roughness dependent fresnel
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0; vec3 kS = F0 + Fr * pow(1.0-ndv, 5.0);
vec2 f_ab = textureLod(uEnvBRDF, vec2(ndv, roughness), 0).xy;
vec3 FssEss = kS * f_ab.x + f_ab.y;
float lodLevel = roughness * numEnvLevels;
vec3 reflDir = reflect(-eye, normal);
// Prefiltered radiance
vec3 radiance = getRadiance(reflDir, lodLevel);
// Cosine-weighted irradiance
vec3 irradiance = getIrradiance(normal);
// Multiple scattering
float Ess = f_ab.x + f_ab.y;
float Ems = 1-Ess;
vec3 Favg = F0 + (1-F0)/21;
vec3 Fms = FssEss*Favg/(1-(1-Ess)*Favg);
// Dielectrics
vec3 Edss = 1 - (FssEss + Fms * Ems); vec3 kD = albedo * Edss;
// Composition
return FssEss * radiance + (Fms*Ems+kD) * irradiance;
vorg commented 1 month ago

Hasn't that been implemented already? Or is it only in some experiment?

dmnsgn commented 1 month ago

Hasn't that been implemented already? Or is it only in some experiment?

We are not doing multi-scattering in IBL no, as far as I am aware, and we're not computing the energyCompensation factor.

It has improved over the past years but still not energy conserving for metals (metallic: 1 and increasing roughness):

image