Skip to content

Commit 5366c30

Browse files
MiiBondvirtualzavieMike BondPopov72
authored
Diffuse Roughness support (#16253)
This PR replaces #16183 This PR implements the base_diffuse_roughness parameter from the [OpenPBR specification](https://academysoftwarefoundation.github.io/OpenPBR/#model/basesubstrate). The diffuse roughness is implemented for analytic lights, realtime-filtered IBL, prefiltered IBL and spherical harmonics. I've added a flag to a material to choose between Lambert, Burley and the new Energy Conserving Oren-Nayar (EON) model used by OpenPBR. The default is OpenPBR's EON model. The previous behaviour was to use Burley diffuse for analytical lights and Lambert for IBL. Also, previously, specular roughness was applied to diffuse roughness for analytical lights while IBL didn't use it at all (because it was simply Lambertian). So, the new default slightly changes existing projects that used analytical lights but I question how noticeable that will be. **Analytical Light:** https://playground.babylonjs.com/?snapshot=refs/pull/16253/merge#MXACV7#3 ![roughnessCompare](https://github.com/user-attachments/assets/df0f6782-f1c9-42b3-8c82-d2e4ebc59f85) **Realtime IBL:** https://playground.babylonjs.com/?snapshot=refs/pull/16253/merge#MXACV7#5 <img width="881" alt="image" src="https://github.com/user-attachments/assets/4d33b49c-a8d5-4903-85ca-78eb368c015e" /> The diffuse roughness models are heavily dependent on the light direction and view direction and are therefore difficult to handle with a prefiltered IBL. I came up with two methods for approximating roughness with prefiltered IBL's. The first, if we prefiltered using CDF, we generate a dominant light direction to use in the BRDF calculations. It works reasonably well. **Prefiltered IBL with CDF:** https://playground.babylonjs.com/?snapshot=refs/pull/16253/merge#MXACV7#9 <img width="883" alt="image" src="https://github.com/user-attachments/assets/b4c8383b-30be-4505-a09c-3bc5d6ee4cc3" /> The second approach, if you don't use CDF, is by approximating roughness by bending the surface normal towards the camera to add some of the retro-reflective behaviour that you get with EON. Because of this, you'll notice that Burley and EON are identical and the shadow terminator appears to move as diffuse roughness increases. In practice, however, this example uses an extreme IBL with a bright sunlight. With other IBL's, the effect tends to be more convincing. **Prefiltered IBL without CDF** https://playground.babylonjs.com/?snapshot=refs/pull/16253/merge#MXACV7#10 <img width="878" alt="image" src="https://github.com/user-attachments/assets/ffaa366c-6e9f-449a-8cbf-6364354e314f" /> The default IBL lighting in Sandbox uses spherical harmonics so we need to approximate diffuse roughness with this as well. I'm using the same bent normal technique as with prefiltered IBL without CDF. **Spherical Harmonics IBL** https://playground.babylonjs.com/?snapshot=refs/pull/16253/merge#MXACV7#11 ![image](https://github.com/user-attachments/assets/13543a47-62aa-4d26-a438-1a6031803027) --------- Co-authored-by: Julien Guertault <[email protected]> Co-authored-by: Mike Bond <[email protected]> Co-authored-by: Popov72 <[email protected]>
1 parent 8d54280 commit 5366c30

File tree

64 files changed

+1029
-91
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1029
-91
lines changed

packages/dev/core/src/Engines/constants.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,21 @@ export class Constants {
469469
*/
470470
public static readonly MATERIAL_CounterClockWiseSideOrientation = 1;
471471

472+
/**
473+
* Energy-conserving Oren Nayar diffuse model type.
474+
*/
475+
public static readonly MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR = 0;
476+
477+
/**
478+
* Burley diffuse model type.
479+
*/
480+
public static readonly MATERIAL_DIFFUSE_MODEL_BURLEY = 1;
481+
482+
/**
483+
* Lambertian diffuse model type.
484+
*/
485+
public static readonly MATERIAL_DIFFUSE_MODEL_LAMBERT = 2;
486+
472487
/**
473488
* Nothing
474489
* @see https://doc.babylonjs.com/features/featuresDeepDive/events/actions#triggers

packages/dev/core/src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
9797
private _metallicReflectanceColor: Color3 = Color3.White();
9898
private _metallicF0Factor = 1;
9999
private _vMetallicReflectanceFactorsName: string;
100+
private _baseDiffuseRoughnessName: string;
100101

101102
/**
102103
* Create a new ReflectionBlock
@@ -271,6 +272,19 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
271272
})
272273
public realTimeFilteringQuality = Constants.TEXTURE_FILTERING_QUALITY_LOW;
273274

275+
/**
276+
* Base Diffuse Model
277+
*/
278+
@editableInPropertyPage("Diffuse Model", PropertyTypeForEdition.List, "RENDERING", {
279+
notifiers: { update: true },
280+
options: [
281+
{ label: "Lambert", value: Constants.MATERIAL_DIFFUSE_MODEL_LAMBERT },
282+
{ label: "Burley", value: Constants.MATERIAL_DIFFUSE_MODEL_BURLEY },
283+
{ label: "Oren-Nayar", value: Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR },
284+
],
285+
})
286+
public baseDiffuseModel = Constants.MATERIAL_DIFFUSE_MODEL_E_OREN_NAYAR;
287+
274288
/**
275289
* Defines if the material uses energy conservation.
276290
*/
@@ -762,6 +776,8 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
762776
defines.setValue("NUM_SAMPLES", "" + this.realTimeFilteringQuality, true);
763777
}
764778

779+
defines.setValue("BASE_DIFFUSE_MODEL", this.baseDiffuseModel, true);
780+
765781
// Advanced
766782
defines.setValue("BRDF_V_HEIGHT_CORRELATED", true);
767783
defines.setValue("MS_BRDF_ENERGY_CONSERVATION", this.useEnergyConservation, true);
@@ -1014,13 +1030,21 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
10141030
this._vMetallicReflectanceFactorsName = state._getFreeVariableName("vMetallicReflectanceFactors");
10151031
state._emitUniformFromString(this._vMetallicReflectanceFactorsName, NodeMaterialBlockConnectionPointTypes.Vector4);
10161032

1033+
this._baseDiffuseRoughnessName = state._getFreeVariableName("baseDiffuseRoughness");
1034+
state._emitUniformFromString(this._baseDiffuseRoughnessName, NodeMaterialBlockConnectionPointTypes.Float);
1035+
10171036
code += `${state._declareLocalVar("baseColor", NodeMaterialBlockConnectionPointTypes.Vector3)} = surfaceAlbedo;
10181037
${isWebGPU ? "let" : `vec4${state.fSuffix}`} vReflectivityColor = vec4${state.fSuffix}(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, ${this.indexOfRefraction.associatedVariableName || "1.5"}, 1.0);
10191038
reflectivityOut = reflectivityBlock(
10201039
vReflectivityColor
10211040
#ifdef METALLICWORKFLOW
10221041
, surfaceAlbedo
10231042
, ${(isWebGPU ? "uniforms." : "") + this._vMetallicReflectanceFactorsName}
1043+
#endif
1044+
, ${(isWebGPU ? "uniforms." : "") + this._baseDiffuseRoughnessName}
1045+
#ifdef BASE_DIFFUSE_ROUGHNESS
1046+
, 0.
1047+
, vec2${state.fSuffix}(0., 0.)
10241048
#endif
10251049
#ifdef REFLECTIVITY
10261050
, vec3${state.fSuffix}(0., 0., ${aoIntensity})
@@ -1036,6 +1060,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
10361060
10371061
${state._declareLocalVar("microSurface", NodeMaterialBlockConnectionPointTypes.Float)} = reflectivityOut.microSurface;
10381062
${state._declareLocalVar("roughness", NodeMaterialBlockConnectionPointTypes.Float)} = reflectivityOut.roughness;
1063+
${state._declareLocalVar("diffuseRoughness", NodeMaterialBlockConnectionPointTypes.Float)} = reflectivityOut.diffuseRoughness;
10391064
10401065
#ifdef METALLICWORKFLOW
10411066
surfaceAlbedo = reflectivityOut.surfaceAlbedo;

packages/dev/core/src/Materials/Node/Blocks/PBR/reflectionBlock.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
438438
#ifdef USEIRRADIANCEMAP
439439
, irradianceSampler // ** not handled **
440440
${isWebGPU ? `, irradianceSamplerSampler` : ""}
441+
#ifdef USE_IRRADIANCE_DOMINANT_DIRECTION
442+
, vReflectionDominantDirection
443+
#endif
441444
#endif
442445
#ifndef LODBASEDMICROSFURACE
443446
#ifdef ${this._define3DName}
@@ -459,6 +462,9 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
459462
${isWebGPU ? `, icdfSamplerSampler` : ""}
460463
#endif
461464
#endif
465+
, viewDirectionW
466+
, diffuseRoughness
467+
, surfaceAlbedo
462468
);
463469
#endif\n`;
464470

0 commit comments

Comments
 (0)