Skip to content
Permalink
Browse files

Fix Sheen BRDF

  • Loading branch information...
sebavan committed Mar 7, 2019
1 parent 717c034 commit 59ff97060856cfdec0ce687a5cec04b9bfb84062
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -90,7 +90,7 @@
if (typeof createEngine !== "undefined") {
engine = createEngine();
} else {
engine = new BABYLON.Engine(canvas, true, { stencil: true, disableWebGL2Support: false, preserveDrawingBuffer: true });
engine = new BABYLON.Engine(canvas, true, { premultipliedAlpha: false, stencil: true, disableWebGL2Support: false, preserveDrawingBuffer: true });
}
BABYLONDEVTOOLS.Loader.debugShortcut(engine);
@@ -16,16 +16,28 @@ export interface IMaterialBRDFDefines {
*/
export class PBRBRDFConfiguration {

/**
* Default value used for the energy conservation.
* This should only be changed to adapt to the type of texture in scene.environmentBRDFTexture.
*/
public static DEFAULT_USE_ENERGY_CONSERVATION = true;

/**
* Default value used for the Smith Visibility Height Correlated mode.
* This should only be changed to adapt to the type of texture in scene.environmentBRDFTexture.
*/
public static DEFAULT_USE_SMITH_VISIBILITY_HEIGHT_CORRELATED = true;

@serialize()
private _useEnergyConservation = true;
private _useEnergyConservation = PBRBRDFConfiguration.DEFAULT_USE_ENERGY_CONSERVATION;
/**
* Defines if the material uses energy conservation.
*/
@expandToProperty("_markAllSubMeshesAsMiscDirty")
public useEnergyConservation = true;
public useEnergyConservation = PBRBRDFConfiguration.DEFAULT_USE_ENERGY_CONSERVATION;

@serialize()
private _useSmithVisibilityHeightCorrelated = true;
private _useSmithVisibilityHeightCorrelated = PBRBRDFConfiguration.DEFAULT_USE_SMITH_VISIBILITY_HEIGHT_CORRELATED;
/**
* LEGACY Mode set to false
* Defines if the material uses height smith correlated visibility term.
@@ -35,7 +47,7 @@ export class PBRBRDFConfiguration {
* Not relying on height correlated will also disable energy conservation.
*/
@expandToProperty("_markAllSubMeshesAsMiscDirty")
public useSmithVisibilityHeightCorrelated = true;
public useSmithVisibilityHeightCorrelated = PBRBRDFConfiguration.DEFAULT_USE_SMITH_VISIBILITY_HEIGHT_CORRELATED;

/** @hidden */
private _internalMarkAllSubMeshesAsMiscDirty: () => void;
@@ -96,6 +96,7 @@ class PBRMaterialDefines extends MaterialDefines
public METALLNESSSTOREINMETALMAPBLUE = false;
public AOSTOREINMETALMAPRED = false;
public ENVIRONMENTBRDF = false;
public ENVIRONMENTBRDF_RGBD = false;

public NORMAL = false;
public TANGENT = false;
@@ -1448,8 +1449,11 @@ export abstract class PBRBaseMaterial extends PushMaterial {

if (this._environmentBRDFTexture && MaterialFlags.ReflectionTextureEnabled) {
defines.ENVIRONMENTBRDF = true;
// Not actual true RGBD, only the B chanel is encoded as RGBD for sheen.
defines.ENVIRONMENTBRDF_RGBD = this._environmentBRDFTexture.isRGBD;
} else {
defines.ENVIRONMENTBRDF = false;
defines.ENVIRONMENTBRDF_RGBD = false;
}

if (this._shouldUseAlphaFromAlbedoTexture()) {
@@ -2123,7 +2127,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
this._reflectionTexture.dispose();
}

if (this._environmentBRDFTexture && this.getScene()._environmentBRDFTexture !== this._environmentBRDFTexture) {
if (this._environmentBRDFTexture && this.getScene().environmentBRDFTexture !== this._environmentBRDFTexture) {
this._environmentBRDFTexture.dispose();
}

@@ -418,6 +418,7 @@ export class InternalTexture implements IInternalTextureTracker {
/** @hidden */
public _swapAndDie(target: InternalTexture): void {
target._webGLTexture = this._webGLTexture;
target._isRGBD = this._isRGBD;

if (this._framebuffer) {
target._framebuffer = this._framebuffer;

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -9,23 +9,27 @@
#ifdef MS_BRDF_ENERGY_CONSERVATION
// http://www.jcgt.org/published/0008/01/03/
// http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf
vec3 getEnergyConservationFactor(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
vec3 getEnergyConservationFactor(const vec3 specularEnvironmentR0, const vec3 environmentBrdf) {
return 1.0 + specularEnvironmentR0 * (1.0 / environmentBrdf.y - 1.0);
}
#endif

#ifdef ENVIRONMENTBRDF
vec2 getBRDFLookup(float NdotV, float perceptualRoughness, sampler2D brdfSampler) {
vec3 getBRDFLookup(float NdotV, float perceptualRoughness, sampler2D brdfSampler) {
// Indexed on cos(theta) and roughness
vec2 UV = vec2(NdotV, perceptualRoughness);

// We can find the scale and offset to apply to the specular value.
vec2 brdfLookup = texture2D(brdfSampler, UV).xy;
vec4 brdfLookup = texture2D(brdfSampler, UV);

return brdfLookup;
#ifdef ENVIRONMENTBRDF_RGBD
brdfLookup.rgb = fromRGBD(brdfLookup.rgba);
#endif

return brdfLookup.rgb;
}

vec3 getReflectanceFromBRDFLookup(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
vec3 getReflectanceFromBRDFLookup(const vec3 specularEnvironmentR0, const vec3 environmentBrdf) {
#ifdef BRDF_V_HEIGHT_CORRELATED
vec3 reflectance = mix(environmentBrdf.xxx, environmentBrdf.yyy, specularEnvironmentR0);
#else
@@ -46,36 +50,12 @@

#if defined(SHEEN) && defined(REFLECTION)
/**
* Special thanks to @romainguy for all the support :-)
* Analytical approximation of the pre-filtered DFG terms for the cloth shading
* model. This approximation is based on the Estevez & Kulla distribution term
* ("Charlie" sheen) and the Neubelt visibility term. See brdf.fs for more
* details.
*/
vec2 getCharlieSheenAnalyticalBRDFLookup_RomainGuy(float NoV, float roughness) {
const vec3 c0 = vec3(0.95, 1250.0, 0.0095);
const vec4 c1 = vec4(0.04, 0.2, 0.3, 0.2);

float a = 1.0 - NoV;
float b = 1.0 - roughness;

float n = pow(c1.x + a, 64.0);
float e = b - c0.x;
float g = exp2(-(e * e) * c0.y);
float f = b + c1.y;
float a2 = a * a;
float a3 = a2 * a;
float c = n * g + c1.z * (a + c1.w) * roughness + f * f * a3 * a3 * a2;
float r = min(c, 18.0);

return vec2(r, r * c0.z);
}

vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, float NdotV, float sheenAlphaG) {
vec2 environmentSheenBrdf = getCharlieSheenAnalyticalBRDFLookup_RomainGuy(NdotV, sheenAlphaG);
vec3 reflectance = reflectance0 * environmentSheenBrdf.x + environmentSheenBrdf.y;

return reflectance;
* The sheen BRDF not containing F can be easily stored in the blue channel of the BRDF texture.
* The blue channel contains DCharlie * VAshikhmin * NdotL as a lokkup table
*/
vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, const vec3 environmentBrdf) {
vec3 sheenEnvironmentReflectance = reflectance0 * environmentBrdf.b;
return sheenEnvironmentReflectance;
}
#endif

@@ -123,12 +123,13 @@ vec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler, m
float roughness = max(info.roughness, geometricRoughnessFactor);
float alphaG = convertRoughnessToAverageSlope(roughness);

// No Fresnel with sheen
// No Fresnel Effect with sheen
// vec3 fresnel = fresnelSchlickGGX(info.VdotH, reflectance0, reflectance90);
vec3 fresnel = reflectance0;
float distribution = normalDistributionFunction_CharlieSheen(NdotH, alphaG);
float visibility = visibility_Ashikhmin(info.NdotL, info.NdotV);

float sheenTerm = distribution * visibility;
vec3 sheenTerm = fresnel * distribution * visibility;
return sheenTerm * info.attenuation * info.NdotL * lightColor;
}
#endif
@@ -516,9 +516,12 @@ void main(void) {
sheenColor.rgb *= toLinearSpace(sheenMapData.rgb);
#endif
float sheenRoughness = roughness;

// Sheen Lobe Layering.
sheenIntensity *= (1. - reflectance);

// Remap F0 and sheen.
sheenColor *= sheenIntensity;
specularEnvironmentR0 *= (1.0-sheenIntensity);
#endif

// Sheen Reflection
@@ -731,7 +734,7 @@ void main(void) {
// _____________________________ IBL BRDF + Energy Cons _________________________________
#if defined(ENVIRONMENTBRDF)
// BRDF Lookup
vec2 environmentBrdf = getBRDFLookup(NdotV, roughness, environmentBrdfSampler);
vec3 environmentBrdf = getBRDFLookup(NdotV, roughness, environmentBrdfSampler);

#ifdef MS_BRDF_ENERGY_CONSERVATION
vec3 energyConservationFactor = getEnergyConservationFactor(specularEnvironmentR0, environmentBrdf);
@@ -796,7 +799,7 @@ void main(void) {

// _____________________________ Sheen Environment Oclusion __________________________
#if defined(SHEEN) && defined(REFLECTION)
vec3 sheenEnvironmentReflectance = getSheenReflectanceFromBRDFLookup(sheenColor, NdotV, sheenAlphaG);
vec3 sheenEnvironmentReflectance = getSheenReflectanceFromBRDFLookup(sheenColor, environmentBrdf);

#ifdef RADIANCEOCCLUSION
sheenEnvironmentReflectance *= seo;
@@ -815,7 +818,7 @@ void main(void) {
#ifdef CLEARCOAT
#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
// BRDF Lookup
vec2 environmentClearCoatBrdf = getBRDFLookup(clearCoatNdotV, clearCoatRoughness, environmentBrdfSampler);
vec3 environmentClearCoatBrdf = getBRDFLookup(clearCoatNdotV, clearCoatRoughness, environmentBrdfSampler);
vec3 clearCoatEnvironmentReflectance = getReflectanceFromBRDFLookup(vec3(vClearCoatRefractionParams.x), environmentClearCoatBrdf);

#ifdef RADIANCEOCCLUSION
@@ -985,11 +988,11 @@ void main(void) {
finalSheen = max(finalSheen, 0.0);

vec3 finalSheenScaled = finalSheen * vLightingIntensity.x * vLightingIntensity.w;
#if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
// #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
// The sheen does not use the same BRDF so not energy conservation is possible
// Should be less a problem as it is usually not metallic
// finalSheenScaled *= energyConservationFactor;
#endif
// #endif

#ifdef REFLECTION
vec3 finalSheenRadiance = environmentSheenRadiance.rgb;
@@ -188,8 +188,15 @@ export class Scene extends AbstractScene implements IAnimatable {
*/
public ambientColor = new Color3(0, 0, 0);

/** @hidden */
public _environmentBRDFTexture: BaseTexture;
/**
* This is use to store the default BRDF lookup for PBR materials in your scene.
* It should only be one of the following (if not the default embedded one):
* * For uncorrelated BRDF (pbr.brdf.useEnergyConservation = false and pbr.brdf.useSmithVisibilityHeightCorrelated = false) : https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
* * For correlated BRDF (pbr.brdf.useEnergyConservation = false and pbr.brdf.useSmithVisibilityHeightCorrelated = true) : https://assets.babylonjs.com/environments/correlatedBRDF.dds
* * For correlated multi scattering BRDF (pbr.brdf.useEnergyConservation = true and pbr.brdf.useSmithVisibilityHeightCorrelated = true) : https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
* The material properties need to be setup according to the type of texture in use.
*/
public environmentBRDFTexture: BaseTexture;

/** @hidden */
protected _environmentTexture: Nullable<BaseTexture>;
@@ -121,7 +121,7 @@ describe('Babylon Scene Loader', function() {
expect(meshCount, "meshCount").to.equal(scene.meshes.length);
expect(materialCount, "materialCount").to.equal(scene.materials.length);

const filteredTextures = scene.textures.filter((texture) => texture !== scene._environmentBRDFTexture);
const filteredTextures = scene.textures.filter((texture) => texture !== scene.environmentBRDFTexture);
expect(textureCount, "textureCount").to.equal(filteredTextures.length);
}));

0 comments on commit 59ff970

Please sign in to comment.
You can’t perform that action at this time.