Skip to content

OpenPBRMaterial (including loading and exporting glTF) #16773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 45 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
2c7ad5e
Added PBR2 material and option to load using glTF
Jun 19, 2025
095b44c
Try mixins for reusing defines in materials
Jun 19, 2025
7330638
Move UV defines into a mixin
Jun 20, 2025
c85e222
Add mixin for imageProcessing support in materials
Jun 20, 2025
6f00910
Fix compile warnings
Jun 20, 2025
2bffe3a
Fix error with es6 build and imageProcessing mixin
Jun 23, 2025
735bee9
Separating reflection (IBL) defines and uniforms
Jun 24, 2025
3d81ea5
Remove pbrBaseMaterial as base class for PBR2
Jun 24, 2025
72b9b3c
Rename PBR2 to OpenPBR
Jun 24, 2025
189cd01
Minor changes
Jun 25, 2025
3478433
Fixes for OpenPBRMaterial.
Jun 26, 2025
12eef7f
Adding properties to OpenPBRMaterial
Jul 10, 2025
555e8df
fix build
sebavan Jul 10, 2025
af04f8e
WIP glTFLoader dynamic material load
MiiBond Jul 10, 2025
a32a8f4
Finish glTFLoader dynamic material load
Jul 11, 2025
fe839d1
Revert "Finish glTFLoader dynamic material load"
Jul 15, 2025
68a6cf5
Revert "WIP glTFLoader dynamic material load"
Jul 15, 2025
b2bf2c3
WIP replacing PBR props with OpenPBR props
Jul 17, 2025
e3bfa80
Change albedo to base color
Jul 17, 2025
48b9e4d
WIP glTFLoader dynamic material load
MiiBond Jul 10, 2025
b9382ac
Finish glTFLoader dynamic material load
Jul 11, 2025
fe5a1fd
Fix dynamic loading of materials in glTF loader
Jul 18, 2025
d4d6183
Add more OpenPBR properties
Jul 18, 2025
c3d174f
Add geometry_normal to OpenPBR material
Jul 21, 2025
cf8143a
Remove lightmap from OpenPBR
Jul 21, 2025
8448191
Starting to refactor glsl shaders for OpenPBR
Jul 30, 2025
2bdb407
Revert settings.json
Jul 30, 2025
6a284da
Added OpenPBR inspector data and WIP on coat noramls
Jul 31, 2025
61399a0
Refactoring OpenPBR analytic light shaders
Aug 1, 2025
c229e29
WebGPU OpenPBR base layer support for direct lighting
Aug 4, 2025
0814449
Fix AO compilation errors for OpenPBR
Aug 5, 2025
6f743f0
Update and rename openPbrUboDeclaration.fx to openpbrUboDeclaration.fx
MiiBond Aug 5, 2025
101fd4b
Update and rename openPbrUboDeclaration.fx to openpbrUboDeclaration.fx
MiiBond Aug 5, 2025
828529a
Fix default glTF PBR values
Aug 5, 2025
aece67e
Fixes for vis tests
Aug 5, 2025
a21bfe7
Fix specular extension loading
Aug 5, 2025
9bf4077
Fix for mixin constructor names
Aug 6, 2025
bff96da
Adding support to export GLB with OpenPBR
Aug 6, 2025
c1c5f18
Add vis test for OpenPBR normal mapping
Aug 6, 2025
52448cd
OpenPBRMaterial export to glTF for diffuse roughness
Aug 6, 2025
3cddebc
Add coat_darkening to OpenPBR
Aug 7, 2025
70652cc
Updates for coat darkening
Aug 8, 2025
7062638
Import and export support for EXT_materials_clearcoat_darkening
Aug 8, 2025
ef48a7c
Fix import in glTFExporter
Aug 18, 2025
0485759
Fix build errors
Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/dev/buildTools/src/addJSToCompiledFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ function ProcessSource(sourceCode: string, forceMJS: boolean) {
const extension = forceMJS ? ".mjs" : ".js";
return (
sourceCode
// replace imports from directories with index.js (mixins are generating them)
.replace(/import\("([./]+)"\)/g, `import("$1/index${extension}")`)
// replace imports and exports with js extensions
.replace(/((import|export).*["'](@babylonjs\/.*\/|\.{1,2}\/)((?!\.scss|\.svg|\.png|\.jpg).)*?)("|');/g, `$1${extension}$5;`)
.replace(/((import|export)\(["']((@babylonjs\/.*\/|\.{1,2}\/)((?!\.scss|\.svg|\.png|\.jpg).)*?))(["'])\)/g, `$1${extension}$6)`)
Expand Down
13 changes: 9 additions & 4 deletions packages/dev/buildTools/src/generateDeclaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ function GetModuleDeclaration(
line = line.startsWith(" ") ? " //" + line.substring(3) : "// " + line;
}

// replace type imports from directories with index (mixins are generating them)
line = line.replace(/import\("([./]+)"\)/g, `import("$1/index")`);

[
// Declaration
/declare module ['"](.*)['"]/,
Expand All @@ -85,15 +88,17 @@ function GetModuleDeclaration(
/ {4}module ['"](.*)['"]/,
/^module ['"](\..*)['"]/,
// Inlined Import
/import\(['"](.*)['"]/,
/import\(['"]([^'"]*)['"]/,
// Side Effect Import
/import ['"](.*)['"]/,
].forEach((regex) => {
const match = line.match(regex);
if (match) {
if (match[1][0] === ".") {
const newLocation = path.join(sourceDir, match[1]).replace(/\\/g, "/");
line = line.replace(match[1], newLocation);
// replaceAll only avaialable by modifying the typescript lib
// which we prefered to not change for now
line = (line as any).replaceAll(match[1], newLocation);
} else {
let found = false;
Object.keys(mapping).forEach((devPackageName) => {
Expand Down Expand Up @@ -319,8 +324,8 @@ function GetPackageDeclaration(
while (i < lines.length) {
let line = lines[i];

if (/import\("\.(.*)\)./g.test(line) && !/^declare type (.*) import/g.test(line)) {
line = line.replace(/import\((.*)\)./, "");
if (/import\("\.([^)]*)\)./g.test(line) && !/^declare type (.*) import/g.test(line)) {
line = line.replace(/import\(([^)]*)\)./g, "");
}

if (!line.includes("const enum") && !line.includes("=")) {
Expand Down
295 changes: 21 additions & 274 deletions packages/dev/core/src/Materials/Background/backgroundMaterial.ts

Large diffs are not rendered by default.

114 changes: 8 additions & 106 deletions packages/dev/core/src/Materials/Node/nodeMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import { NodeMaterialBuildState } from "./nodeMaterialBuildState";
import type { IEffectCreationOptions } from "../effect";
import { Effect } from "../effect";
import type { BaseTexture } from "../../Materials/Textures/baseTexture";
import type { Observer } from "../../Misc/observable";
import { Observable } from "../../Misc/observable";
import { NodeMaterialBlockTargets } from "./Enums/nodeMaterialBlockTargets";
import { NodeMaterialBuildStateSharedData } from "./nodeMaterialBuildStateSharedData";
import type { SubMesh } from "../../Meshes/subMesh";
import { MaterialDefines } from "../../Materials/materialDefines";
import type { NodeMaterialOptimizer } from "./Optimizers/nodeMaterialOptimizer";
import type { ImageProcessingConfiguration } from "../imageProcessingConfiguration";
import type { Nullable } from "../../types";
import { VertexBuffer } from "../../Buffers/buffer";
import { Tools } from "../../Misc/tools";
Expand Down Expand Up @@ -67,11 +65,13 @@ import type { NodeMaterialTeleportOutBlock } from "./Blocks/Teleport/teleportOut
import type { NodeMaterialTeleportInBlock } from "./Blocks/Teleport/teleportInBlock";
import { Logger } from "core/Misc/logger";
import { PrepareDefinesForCamera, PrepareDefinesForPrePass } from "../materialHelper.functions";
import type { IImageProcessingConfigurationDefines } from "../imageProcessingConfiguration.defines";
import { ImageProcessingDefinesMixin } from "../imageProcessingConfiguration.defines";
import { ShaderLanguage } from "../shaderLanguage";
import { AbstractEngine } from "../../Engines/abstractEngine";
import type { LoopBlock } from "./Blocks/loopBlock";
import { MaterialHelperGeometryRendering } from "../materialHelper.geometryrendering";
import { UVDefinesMixin } from "../uv.defines";
import { ImageProcessingMixin } from "../imageProcessing";

const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };

Expand All @@ -91,26 +91,16 @@ export interface INodeMaterialEditorOptions {
};
}

class NodeMaterialDefinesBase extends UVDefinesMixin(MaterialDefines) {}

/** @internal */
export class NodeMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
export class NodeMaterialDefines extends ImageProcessingDefinesMixin(NodeMaterialDefinesBase) {
/** Normal */
public NORMAL = false;
/** Tangent */
public TANGENT = false;
/** Vertex color */
public VERTEXCOLOR_NME = false;
/** Uv1 **/
public UV1 = false;
/** Uv2 **/
public UV2 = false;
/** Uv3 **/
public UV3 = false;
/** Uv4 **/
public UV4 = false;
/** Uv5 **/
public UV5 = false;
/** Uv6 **/
public UV6 = false;

/** Prepass **/
public PREPASS = false;
Expand Down Expand Up @@ -177,37 +167,6 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces
/** Using a texture to store morph target data */
public MORPHTARGETS_TEXTURE = false;

/** IMAGE PROCESSING */
public IMAGEPROCESSING = false;
/** Vignette */
public VIGNETTE = false;
/** Multiply blend mode for vignette */
public VIGNETTEBLENDMODEMULTIPLY = false;
/** Opaque blend mode for vignette */
public VIGNETTEBLENDMODEOPAQUE = false;
/** Tone mapping */
public TONEMAPPING = 0;
/** Contrast */
public CONTRAST = false;
/** Exposure */
public EXPOSURE = false;
/** Color curves */
public COLORCURVES = false;
/** Color grading */
public COLORGRADING = false;
/** 3D color grading */
public COLORGRADING3D = false;
/** Sampler green depth */
public SAMPLER3DGREENDEPTH = false;
/** Sampler for BGR map */
public SAMPLER3DBGRMAP = false;
/** Dithering */
public DITHER = false;
/** Using post process for image processing */
public IMAGEPROCESSINGPOSTPROCESS = false;
/** Skip color clamp */
public SKIPFINALCOLORCLAMP = false;

/** MISC. */
public BUMPDIRECTUV = 0;
/** Camera is orthographic */
Expand Down Expand Up @@ -272,10 +231,11 @@ export type NodeMaterialTextureBlocks =
| BiPlanarBlock
| PrePassTextureBlock;

class NodeMaterialBase extends ImageProcessingMixin(PushMaterial) {}
/**
* Class used to create a node based material built by assembling shader blocks
*/
export class NodeMaterial extends PushMaterial {
export class NodeMaterial extends NodeMaterialBase {
private static _BuildIdGenerator: number = 0;
private _options: INodeMaterialOptions;
private _vertexCompilationState: NodeMaterialBuildState;
Expand Down Expand Up @@ -416,30 +376,6 @@ export class NodeMaterial extends PushMaterial {
this._options = options;
}

/**
* Default configuration related to image processing available in the standard Material.
*/
protected _imageProcessingConfiguration: ImageProcessingConfiguration;

/**
* Gets the image processing configuration used either in this material.
*/
public get imageProcessingConfiguration(): ImageProcessingConfiguration {
return this._imageProcessingConfiguration;
}

/**
* Sets the Default image processing configuration used either in the this material.
*
* If sets to null, the scene one is in use.
*/
public set imageProcessingConfiguration(value: ImageProcessingConfiguration) {
this._attachImageProcessingConfiguration(value);

// Ensure the effect will be rebuilt.
this._markAllSubMeshesAsTexturesDirty();
}

/**
* Gets an array of blocks that needs to be serialized even if they are not yet connected
*/
Expand Down Expand Up @@ -513,40 +449,6 @@ export class NodeMaterial extends PushMaterial {
return "NodeMaterial";
}

/**
* Keep track of the image processing observer to allow dispose and replace.
*/
private _imageProcessingObserver: Nullable<Observer<ImageProcessingConfiguration>>;

/**
* Attaches a new image processing configuration to the Standard Material.
* @param configuration
*/
protected _attachImageProcessingConfiguration(configuration: Nullable<ImageProcessingConfiguration>): void {
if (configuration === this._imageProcessingConfiguration) {
return;
}

// Detaches observer.
if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
}

// Pick the scene configuration if needed.
if (!configuration) {
this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
} else {
this._imageProcessingConfiguration = configuration;
}

// Attaches observer.
if (this._imageProcessingConfiguration) {
this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(() => {
this._markAllSubMeshesAsImageProcessingDirty();
});
}
}

/**
* Get a block by its name
* @param name defines the name of the block to retrieve
Expand Down
5 changes: 5 additions & 0 deletions packages/dev/core/src/Materials/PBR/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from "./pbrBRDFConfiguration";
export * from "./pbrClearCoatConfiguration";
export * from "./pbrIridescenceConfiguration";
export * from "./pbrMaterial";
export * from "./openPbrMaterial";
export * from "./pbrMetallicRoughnessMaterial";
export * from "./pbrSpecularGlossinessMaterial";
export * from "./pbrSheenConfiguration";
Expand All @@ -15,3 +16,7 @@ export * from "../../ShadersWGSL/pbr.vertex";
export * from "../../ShadersWGSL/pbr.fragment";
export * from "../../Shaders/pbr.vertex";
export * from "../../Shaders/pbr.fragment";
export * from "../../ShadersWGSL/openpbr.vertex";
export * from "../../ShadersWGSL/openpbr.fragment";
export * from "../../Shaders/openpbr.vertex";
export * from "../../Shaders/openpbr.fragment";
Loading
Loading