Jump to content

About MaterialDefines memory consumption


BMWPilote
 Share

Recommended Posts

MaterialDefines is per SubMesh and if I have a lot of meshes in the Scene, the memory consumption can be crazy. For some reasons, I cannot merge my meshes (because I need to clone the picked mesh).

image.png.26d0b213cfeba4eefce9eec70ad0e3bd.png

My scene is static and the meshes are similar. I have only two types of meshes:

1. one use only diffuse color, diffuse texture, glossiness and specular color and IBL.

2. the other one has just an extra opacity value

 So, although I have a lot of meshes, theirs defines should really almost always the same. My question is that is there any way to share the MaterialDefines? 

image.thumb.png.461806eb4a1614e27c23005776507b3d.png

 

Link to comment
Share on other sites

Well you can still merge everything which will provide a large memory boost and you can just keep a disabled mesh as source for the clone.

 

Also, not tested but should work: just go through all submeshes and manually set the defines the one single value

Link to comment
Share on other sites

10 hours ago, Deltakosh said:

Well you can still merge everything which will provide a large memory boost and you can just keep a disabled mesh as source for the clone.

 

Also, not tested but should work: just go through all submeshes and manually set the defines the one single value

"you can just keep a disabled mesh as source for the clone". Could you please explain more?

Once merged. The source meshes are all removed...How can I still clone picked mesh dynamically?

Link to comment
Share on other sites

13 hours ago, Deltakosh said:

Well you can still merge everything which will provide a large memory boost and you can just keep a disabled mesh as source for the clone.

 

Also, not tested but should work: just go through all submeshes and manually set the defines the one single value

Unluckily, just assigning the same MaterialDefines did not work. Only some of the meshes were displayed.

Link to comment
Share on other sites

23 hours ago, Deltakosh said:

Can you repro the test your did for sharing the defines in the PG? I'll try to see if I can help

Actually I just copied the code of PBRBaseSimpleMaterial and instead of creating one PBRMaterialDefines for each SubMesh, I created a static PBRMaterailDefines and assign it to all the SubMeshes. Then some of the meshes could not be drawn correctly.

Link to comment
Share on other sites

On 7/31/2018 at 12:38 AM, Deltakosh said:

Then please share it :) So we can all work on the same code base

Finally I moved all what I don't need and now the Defines take lightly more than 300 bytes instead of 8000 bytes.

import * as BABYLON from 'babylonjs';
import * as custom_pbr_vert from '../../Graphics/Shaders/glsl/custom_pbr_vert.glsl';
import * as custom_pbr_frag from '../../Graphics/Shaders/glsl/custom_pbr_frag.glsl';
import * as MaterialUtils from '../MaterialUtils';

import { MAX_CUTPLANE_COUNT, CUTPLANES_UNIFORM_NAME, CUTPLANE_COUNT_UNIFORM_NAME } from '../MaterialCommonDefinitions';
import { ExtraDataHolder } from '../ExtraDataHolder';
import { RenderOptions } from '../../Preferences';
import { EnhancedScene } from '../../Scene/EnhancedScene';

export class SimplifiedPBRMaterialDefinesShared { 
    OPACITYRGB = false;
    ALPHAFROMALBEDO = false;
    SPECULAROVERALPHA = false;
    RADIANCEOVERALPHA = false;
    ALPHAFRESNEL = false;
    LINEARALPHAFRESNEL = false;
    PREMULTIPLYALPHA = false;

    METALLICWORKFLOW = false;
    ROUGHNESSSTOREINMETALMAPALPHA = false;
    ROUGHNESSSTOREINMETALMAPGREEN = false;
    METALLNESSSTOREINMETALMAPBLUE = false;
    AOSTOREINMETALMAPRED = false;
    ENVIRONMENTBRDF = false;

    USEPHYSICALLIGHTFALLOFF = false;
    TWOSIDEDLIGHTING = false;
    SHADOWFLOAT = false;

    FORCENORMALFORWARD = false;

    MICROSURFACEFROMREFLECTIVITYMAP = false;
    MICROSURFACEAUTOMATIC = false;
    LODBASEDMICROSFURACE = false;

    REFLECTION = false;
    REFLECTIONMAP_3D = false;
    REFLECTIONMAP_SPHERICAL = false;
    REFLECTIONMAP_PLANAR = false;
    REFLECTIONMAP_CUBIC = false;

    USE_LOCAL_REFLECTIONMAP_CUBIC = false;
    REFLECTIONMAP_PROJECTION = false;
    REFLECTIONMAP_SKYBOX = false;
    REFLECTIONMAP_EXPLICIT = false;
    REFLECTIONMAP_EQUIRECTANGULAR = false;
    REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
    REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
    INVERTCUBICMAP = false;
    USESPHERICALFROMREFLECTIONMAP = false;
    USESPHERICALINVERTEX = false;
    REFLECTIONMAP_OPPOSITEZ = false;
    LODINREFLECTIONALPHA = false;
    GAMMAREFLECTION = false;

    CUTPLANE = false;
    MAX_CUTPLANE_COUNT = MAX_CUTPLANE_COUNT;
}

export class SimplifiedPBRMaterialDefines extends BABYLON.MaterialDefines {
    PBR = true;

    MAINUV1 = false;
    MAINUV2 = false;
    UV1 = false;
    UV2 = false;

    ALBEDO = false;
    EMISSIVE = false;
    REFLECTIVITY = false;
    OPACITY = false;
    BUMP = false;

    ALBEDODIRECTUV = 0;
    EMISSIVEDIRECTUV = 0;
    REFLECTIVITYDIRECTUV = 0;
    OPACITYDIRECTUV = 0;
    BUMPDIRECTUV = 0;

    NORMAL = false;
    TANGENT = false;

    ALPHABLEND = false;

    SPECULARTERM = false;
    LOGARITHMICDEPTH = false;

    _shared: SimplifiedPBRMaterialDefinesShared;

    /**
     * Initializes the PBR Material defines.
     */
    constructor(shared: SimplifiedPBRMaterialDefinesShared) {
        super();
        this._shared = shared;
        this.rebuild();
    }

    toString(): string {
        let result = super.toString();

        let keys = Object.keys(this._shared);
        for (var index = 0; index < keys.length; index++) {
            var prop = keys[index];
            var value = (this._shared as any)[prop];
            var type = typeof value;
            switch (type) {
                case "number":
                case "string":
                    result += "#define " + prop + " " + value + "\n";
                    break;
                default:
                    if (value) {
                        result += "#define " + prop + "\n";
                    }
                    break;
            }
        }

        return result;
    }

    /**
     * Resets the PBR Material defines.
     */
    reset(): void {
        super.reset();
        this.PBR = true;
    }

    get keys(): string[] {
        return this._keys;
    }

    set keys(keys: string[]) {
        this._keys = keys;
    }
}

export abstract class SimplifiedPBRBaseSimpleMaterial extends BABYLON.PBRBaseSimpleMaterial implements ExtraDataHolder {
    protected _extraData: any;
    protected _extraDataDirty: boolean = true;
    protected _sharedDefines: SimplifiedPBRMaterialDefinesShared;

    constructor(name: string, scene: BABYLON.Scene, extraData: any) {
        super(name, scene);

        if (RenderOptions.useLogarithmicDepth) {
            this.useLogarithmicDepth = true;
        }

        let shader = BABYLON.Effect.ShadersStore['custom_pbr' + 'VertexShader'];
        if (!shader) {
            let custom_pbr_vertex_shader: string = custom_pbr_vert;
            BABYLON.Effect.ShadersStore['custom_pbr' + 'VertexShader'] = custom_pbr_vertex_shader;
        }

        shader = BABYLON.Effect.ShadersStore['custom_pbr' + 'FragmentShader'];
        if (!shader) {
            let custom_pbr_fragment_shader: string = custom_pbr_frag;
            BABYLON.Effect.ShadersStore['custom_pbr' + 'FragmentShader'] = custom_pbr_fragment_shader;
        }

        if (extraData)
            this._extraData = extraData;
        else
            this._extraData = {};

        this.onBindObservable.add(() => {
            const scene = this.getScene() as EnhancedScene;
            if (this._extraDataDirty || (scene.extraDataDirty && this.alpha < 1.0)) {
                this.onCutPlanesUpdated();
                this._extraDataDirty = false;
            }
        });

        this._extraData.textureMaps = {};

        this._sharedDefines = new SimplifiedPBRMaterialDefinesShared();
    }

    bindForSubMesh(world: BABYLON.Matrix, mesh: BABYLON.Mesh, subMesh: BABYLON.SubMesh): void {
        var scene = this.getScene();

        var defines = <SimplifiedPBRMaterialDefines>subMesh._materialDefines;
        if (!defines) {
            return;
        }

        var effect = subMesh.effect;

        if (!effect) {
            return;
        }

        this._activeEffect = effect;

        // Matrices
        this.bindOnlyWorldMatrix(world);
        let mustRebind = this._mustRebind(scene, effect, mesh.visibility);


        let reflectionTexture: BABYLON.Nullable<BABYLON.BaseTexture> = null;
        if (mustRebind) {
            this._uniformBuffer.bindToEffect(effect, "Material");

            this.bindViewProjection(effect);
            reflectionTexture = this._getReflectionTexture();

            if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {

                // Texture uniforms
                if (scene.texturesEnabled) {
                    if (this._albedoTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
                        this._uniformBuffer.updateFloat2("vAlbedoInfos", this._albedoTexture.coordinatesIndex, this._albedoTexture.level);
                        BABYLON.MaterialHelper.BindTextureMatrix(this._albedoTexture, this._uniformBuffer, "albedo");
                    }

                    if (this._opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                        this._uniformBuffer.updateFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level);
                        BABYLON.MaterialHelper.BindTextureMatrix(this._opacityTexture, this._uniformBuffer, "opacity");
                    }

                    if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                        this._uniformBuffer.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix());
                        this._uniformBuffer.updateFloat2("vReflectionInfos", reflectionTexture.level, 0);

                        if ((<any>reflectionTexture).boundingBoxSize) {
                            let cubeTexture = <BABYLON.CubeTexture>reflectionTexture;

                            this._uniformBuffer.updateVector3("vReflectionPosition", cubeTexture.boundingBoxPosition);
                            this._uniformBuffer.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize);
                        }

                        var polynomials = reflectionTexture.sphericalPolynomial;
                        if (defines._shared.USESPHERICALFROMREFLECTIONMAP && polynomials) {
                            this._activeEffect.setFloat3("vSphericalX", polynomials.x.x, polynomials.x.y, polynomials.x.z);
                            this._activeEffect.setFloat3("vSphericalY", polynomials.y.x, polynomials.y.y, polynomials.y.z);
                            this._activeEffect.setFloat3("vSphericalZ", polynomials.z.x, polynomials.z.y, polynomials.z.z);
                            this._activeEffect.setFloat3("vSphericalXX_ZZ", polynomials.xx.x - polynomials.zz.x,
                                polynomials.xx.y - polynomials.zz.y,
                                polynomials.xx.z - polynomials.zz.z);
                            this._activeEffect.setFloat3("vSphericalYY_ZZ", polynomials.yy.x - polynomials.zz.x,
                                polynomials.yy.y - polynomials.zz.y,
                                polynomials.yy.z - polynomials.zz.z);
                            this._activeEffect.setFloat3("vSphericalZZ", polynomials.zz.x, polynomials.zz.y, polynomials.zz.z);
                            this._activeEffect.setFloat3("vSphericalXY", polynomials.xy.x, polynomials.xy.y, polynomials.xy.z);
                            this._activeEffect.setFloat3("vSphericalYZ", polynomials.yz.x, polynomials.yz.y, polynomials.yz.z);
                            this._activeEffect.setFloat3("vSphericalZX", polynomials.zx.x, polynomials.zx.y, polynomials.zx.z);
                        }

                        this._uniformBuffer.updateFloat3("vReflectionMicrosurfaceInfos",
                            reflectionTexture.getSize().width,
                            reflectionTexture.lodGenerationScale,
                            reflectionTexture.lodGenerationOffset);
                    }

                    if (this._emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
                        this._uniformBuffer.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level);
                        BABYLON.MaterialHelper.BindTextureMatrix(this._emissiveTexture, this._uniformBuffer, "emissive");
                    }

                    if (BABYLON.StandardMaterial.SpecularTextureEnabled) {
                        if (this._metallicTexture) {
                            this._uniformBuffer.updateFloat3("vReflectivityInfos", this._metallicTexture.coordinatesIndex, this._metallicTexture.level, this._ambientTextureStrength);
                            BABYLON.MaterialHelper.BindTextureMatrix(this._metallicTexture, this._uniformBuffer, "reflectivity");
                        }
                        else if (this._reflectivityTexture) {
                            this._uniformBuffer.updateFloat3("vReflectivityInfos", this._reflectivityTexture.coordinatesIndex, this._reflectivityTexture.level, 1.0);
                            BABYLON.MaterialHelper.BindTextureMatrix(this._reflectivityTexture, this._uniformBuffer, "reflectivity");
                        }

                        if (this._microSurfaceTexture) {
                            this._uniformBuffer.updateFloat2("vMicroSurfaceSamplerInfos", this._microSurfaceTexture.coordinatesIndex, this._microSurfaceTexture.level);
                            BABYLON.MaterialHelper.BindTextureMatrix(this._microSurfaceTexture, this._uniformBuffer, "microSurfaceSampler");
                        }
                    }

                    if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled && !this._disableBumpMap) {
                        this._uniformBuffer.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, this._bumpTexture.level, this._parallaxScaleBias);
                        BABYLON.MaterialHelper.BindTextureMatrix(this._bumpTexture, this._uniformBuffer, "bump");

                        if (scene._mirroredCameraPosition) {
                            this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? 1.0 : -1.0, this._invertNormalMapY ? 1.0 : -1.0);
                        } else {
                            this._uniformBuffer.updateFloat2("vTangentSpaceParams", this._invertNormalMapX ? -1.0 : 1.0, this._invertNormalMapY ? -1.0 : 1.0);
                        }
                    }
                }

                // Colors
                if (defines._shared.METALLICWORKFLOW) {
                    BABYLON.PBRMaterial._scaledReflectivity.r = (this._metallic === undefined || this._metallic === null) ? 1 : this._metallic;
                    BABYLON.PBRMaterial._scaledReflectivity.g = (this._roughness === undefined || this._roughness === null) ? 1 : this._roughness;
                    this._uniformBuffer.updateColor4("vReflectivityColor", BABYLON.PBRMaterial._scaledReflectivity, 0);
                }
                else {
                    this._uniformBuffer.updateColor4("vReflectivityColor", this._reflectivityColor, this._microSurface);
                }

                this._uniformBuffer.updateColor3("vEmissiveColor", this._emissiveColor);
                this._uniformBuffer.updateColor3("vReflectionColor", this._reflectionColor);
                this._uniformBuffer.updateColor4("vAlbedoColor", this._albedoColor, this.alpha * mesh.visibility);


                // Misc
                this._lightingInfos.x = this._directIntensity;
                this._lightingInfos.y = this._emissiveIntensity;
                this._lightingInfos.z = this._environmentIntensity;
                this._lightingInfos.w = this._specularIntensity;

                this._uniformBuffer.updateVector4("vLightingIntensity", this._lightingInfos);
            }

            // Textures
            if (scene.texturesEnabled) {
                if (this._albedoTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
                    this._uniformBuffer.setTexture("albedoSampler", this._albedoTexture);
                }

                if (this._opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                    this._uniformBuffer.setTexture("opacitySampler", this._opacityTexture);
                }

                if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                    if (defines._shared.LODBASEDMICROSFURACE) {
                        this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
                    }
                    else {
                        this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture);
                        this._uniformBuffer.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture);
                        this._uniformBuffer.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture);
                    }
                }

                if (defines._shared.ENVIRONMENTBRDF) {
                    this._uniformBuffer.setTexture("environmentBrdfSampler", this._environmentBRDFTexture);
                }

                if (this._emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
                    this._uniformBuffer.setTexture("emissiveSampler", this._emissiveTexture);
                }

                if (BABYLON.StandardMaterial.SpecularTextureEnabled) {
                    if (this._metallicTexture) {
                        this._uniformBuffer.setTexture("reflectivitySampler", this._metallicTexture);
                    }
                    else if (this._reflectivityTexture) {
                        this._uniformBuffer.setTexture("reflectivitySampler", this._reflectivityTexture);
                    }

                    if (this._microSurfaceTexture) {
                        this._uniformBuffer.setTexture("microSurfaceSampler", this._microSurfaceTexture);
                    }
                }

                if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled && !this._disableBumpMap) {
                    this._uniformBuffer.setTexture("bumpSampler", this._bumpTexture);
                }
            }

            // Colors
            scene.ambientColor.multiplyToRef(this._ambientColor, this._globalAmbientColor);

            var eyePosition = scene._forcedViewPosition ? scene._forcedViewPosition : (scene._mirroredCameraPosition ? scene._mirroredCameraPosition : (<BABYLON.Camera>scene.activeCamera).globalPosition);
            var invertNormal = (scene.useRightHandedSystem === (scene._mirroredCameraPosition != null));
            effect.setFloat4("vEyePosition",
                eyePosition.x,
                eyePosition.y,
                eyePosition.z,
                invertNormal ? -1 : 1);
            effect.setColor3("vAmbientColor", this._globalAmbientColor);
        }

        if (mustRebind || !this.isFrozen) {
            // Lights
            if (scene.lightsEnabled && !this._disableLighting) {
                BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, this._usePhysicalLightFalloff);
            }

            // Log. depth
            BABYLON. MaterialHelper.BindLogDepth(defines, this._activeEffect, scene);
        }

        this._uniformBuffer.update();
        this._afterBind(mesh, this._activeEffect);
    }

    getClassName(): string {
        return 'SimplifiedPBRBaseSimpleMaterial';
    }

    get extraData(): any {
        return this._extraData;
    }

    get extraDataDirty(): boolean {
        return this._extraDataDirty;
    }

    set extraDataDirty(value: boolean) {
        this._extraDataDirty = value;
    }

    onCutPlanesUpdated(): void {
        if (this.extraData.cutPlanes) {
            MaterialUtils.updateCutPlanes(this.getEffect(), this.extraData.cutPlanes);
        }
    }

    isReadyForSubMesh(mesh: BABYLON.AbstractMesh, subMesh: BABYLON.SubMesh, useInstances?: boolean): boolean {
        if (subMesh.effect && this.isFrozen) {
            if (this._wasPreviouslyReady) {
                return true;
            }
        }

        if (!subMesh._materialDefines) {
            subMesh._materialDefines = new SimplifiedPBRMaterialDefines(this._sharedDefines);
        }

        const defines = <SimplifiedPBRMaterialDefines>subMesh._materialDefines;
        if (!this.checkReadyOnEveryCall && subMesh.effect) {
            if (defines._renderId === this.getScene().getRenderId()) {
                return true;
            }
        }

        const scene = this.getScene();
        const engine = scene.getEngine();

        if (defines._areTexturesDirty) {
            if (scene.texturesEnabled) {
                if (this._albedoTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
                    if (!this._albedoTexture.isReadyOrNotBlocking()) {
                        return false;
                    }
                }

                if (this._opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                    if (!this._opacityTexture.isReadyOrNotBlocking()) {
                        return false;
                    }
                }

                var reflectionTexture = this._getReflectionTexture();
                if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                    if (!reflectionTexture.isReadyOrNotBlocking()) {
                        return false;
                    }
                }

                if (this._emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
                    if (!this._emissiveTexture.isReadyOrNotBlocking()) {
                        return false;
                    }
                }

                if (BABYLON.StandardMaterial.SpecularTextureEnabled) {
                    if (this._metallicTexture) {
                        if (!this._metallicTexture.isReadyOrNotBlocking()) {
                            return false;
                        }
                    }
                    else if (this._reflectivityTexture) {
                        if (!this._reflectivityTexture.isReadyOrNotBlocking()) {
                            return false;
                        }
                    }

                    if (this._microSurfaceTexture) {
                        if (!this._microSurfaceTexture.isReadyOrNotBlocking()) {
                            return false;
                        }
                    }
                }

                if (engine.getCaps().standardDerivatives && this._bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled && !this._disableBumpMap) {
                    // Bump texture cannot be not blocking.
                    if (!this._bumpTexture.isReady()) {
                        return false;
                    }
                }

                if (this._environmentBRDFTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                    // This is blocking.
                    if (!this._environmentBRDFTexture.isReady()) {
                        return false;
                    }
                }
            }
        }

        if (!engine.getCaps().standardDerivatives) {
            let bufferMesh = null;
            if (mesh.getClassName() === "InstancedMesh") {
                bufferMesh = (mesh as BABYLON.InstancedMesh).sourceMesh;
            }
            else if (mesh.getClassName() === "Mesh") {
                bufferMesh = mesh as BABYLON.Mesh;
            }

            if (bufferMesh && bufferMesh.geometry && bufferMesh.geometry.isReady() && !bufferMesh.geometry.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
                bufferMesh.createNormals(true);
                BABYLON.Tools.Warn("PBRMaterial: Normals have been created for the mesh: " + bufferMesh.name);
            }
        }

        const effect = this._prepareEnhancedEffect(mesh, defines, this.onCompiled, this.onError, useInstances);
        if (effect) {
            scene.resetCachedMaterial();
            subMesh.setEffect(effect, defines);
            this.buildUniformLayout();
        }

        if (!subMesh.effect || !subMesh.effect.isReady()) {
            return false;
        }

        defines._renderId = scene.getRenderId();
        this._wasPreviouslyReady = true;

        return true;
    }

    protected _prepareEnhancedEffect(mesh: BABYLON.AbstractMesh, defines: SimplifiedPBRMaterialDefines, onCompiled: BABYLON.Nullable<(effect: BABYLON.Effect) => void> = null, onError: BABYLON.Nullable<(effect: BABYLON.Effect, errors: string) => void> = null, useInstances: BABYLON.Nullable<boolean> = null, useClipPlane: BABYLON.Nullable<boolean> = null): BABYLON.Nullable<BABYLON.Effect> {
        this._prepareSimplifiedDefines(mesh, defines, useInstances, useClipPlane);

        if (!defines.isDirty) {
            return null;
        }

        defines.markAsProcessed();

        const scene = this.getScene();
        const engine = scene.getEngine();

        // Fallbacks
        let fallbacks = new BABYLON.EffectFallbacks();
        let fallbackRank = 0;
        if (defines._shared.USESPHERICALINVERTEX) {
            fallbacks.addFallback(fallbackRank++, 'USESPHERICALINVERTEX');
        }

        if (defines.LOGARITHMICDEPTH) {
            fallbacks.addFallback(fallbackRank, 'LOGARITHMICDEPTH');
        }

        if (defines._shared.ENVIRONMENTBRDF) {
            fallbacks.addFallback(fallbackRank++, 'ENVIRONMENTBRDF');
        }

        if (defines.TANGENT) {
            fallbacks.addFallback(fallbackRank++, 'TANGENT');
        }

        if (defines.BUMP) {
            fallbacks.addFallback(fallbackRank++, 'BUMP');
        }

        fallbackRank = BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights, fallbackRank++);

        if (defines.SPECULARTERM) {
            fallbacks.addFallback(fallbackRank++, 'SPECULARTERM');
        }

        if (defines._shared.USESPHERICALFROMREFLECTIONMAP) {
            fallbacks.addFallback(fallbackRank++, 'USESPHERICALFROMREFLECTIONMAP');
        }

        if (defines.NORMAL) {
            fallbacks.addFallback(fallbackRank++, 'NORMAL');
        }

        if (defines.EMISSIVE) {
            fallbacks.addFallback(fallbackRank++, 'EMISSIVE');
        }

        //Attributes
        let attribs = [BABYLON.VertexBuffer.PositionKind];

        if (defines.NORMAL) {
            attribs.push(BABYLON.VertexBuffer.NormalKind);
        }

        if (defines.TANGENT) {
            attribs.push(BABYLON.VertexBuffer.TangentKind);
        }

        if (defines.UV1) {
            attribs.push(BABYLON.VertexBuffer.UVKind);
        }

        if (defines.UV2) {
            attribs.push(BABYLON.VertexBuffer.UV2Kind);
        }

        let uniforms = ['world', 'view', 'viewProjection', 'vEyePosition', 'vLightsType', 'vAmbientColor', 'vAlbedoColor', 'vReflectivityColor', 'vEmissiveColor', 'vReflectionColor',
            'vAlbedoInfos', 'vOpacityInfos', 'vReflectionInfos', 'vReflectionPosition', 'vReflectionSize', 'vEmissiveInfos', 'vReflectivityInfos',
            'vMicroSurfaceSamplerInfos', 'vBumpInfos',
            'albedoMatrix', 'opacityMatrix', 'reflectionMatrix', 'emissiveMatrix', 'reflectivityMatrix', 'normalMatrix', 'microSurfaceSamplerMatrix', 'bumpMatrix',
            'vLightingIntensity',
            'logarithmicDepthConstant',
            'vSphericalX', 'vSphericalY', 'vSphericalZ',
            'vSphericalXX', 'vSphericalYY', 'vSphericalZZ',
            'vSphericalXY', 'vSphericalYZ', 'vSphericalZX',
            'vReflectionMicrosurfaceInfos',
            'vTangentSpaceParams',
            CUTPLANE_COUNT_UNIFORM_NAME, CUTPLANES_UNIFORM_NAME
        ];

        if (this.extraData.cutPlanes.length > 0) {
            defines._shared.CUTPLANE = true;
            defines._shared.MAX_CUTPLANE_COUNT = MAX_CUTPLANE_COUNT;
        }

        let samplers = ['albedoSampler', 'reflectivitySampler', 'emissiveSampler',
            'bumpSampler', 'opacitySampler',
            'reflectionSampler', 'reflectionSamplerLow', 'reflectionSamplerHigh',
            'microSurfaceSampler', 'environmentBrdfSampler'];
        let uniformBuffers = ['Material', 'Scene'];

        BABYLON.MaterialHelper.PrepareUniformsAndSamplersList(<BABYLON.EffectCreationOptions>{
            uniformsNames: uniforms,
            uniformBuffersNames: uniformBuffers,
            samplers: samplers,
            defines: defines,
            maxSimultaneousLights: this._maxSimultaneousLights
        });

        if (!defines.keys) {
            defines.rebuild();
        }
        let join = defines.toString();
        defines.keys = undefined;

        return engine.createEffect('custom_pbr', <BABYLON.EffectCreationOptions>{
            attributes: attribs,
            uniformsNames: uniforms,
            uniformBuffersNames: uniformBuffers,
            samplers: samplers,
            defines: join,
            fallbacks: fallbacks,
            onCompiled: onCompiled,
            onError: onError,
            indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
        }, engine);
    }

    private _prepareSimplifiedDefines(mesh: BABYLON.AbstractMesh, defines: SimplifiedPBRMaterialDefines, useInstances: BABYLON.Nullable<boolean> = null, useClipPlane: BABYLON.Nullable<boolean> = null): void {
        const scene = this.getScene();

        // Lights
        //BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, this._maxSimultaneousLights, this._disableLighting);
        defines._needNormals = true;

        // Textures
        defines._shared.METALLICWORKFLOW = super.isMetallicWorkflow();
        if (defines._areTexturesDirty) {
            defines._needUVs = false;
            if (scene.texturesEnabled) {
                if (scene.getEngine().getCaps().textureLOD) {
                    defines._shared.LODBASEDMICROSFURACE = true;
                }

                if (this._albedoTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
                    BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._albedoTexture, defines, "ALBEDO");
                } else {
                    defines.ALBEDO = false;
                }

                if (this._opacityTexture && BABYLON.StandardMaterial.OpacityTextureEnabled) {
                    BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._opacityTexture, defines, "OPACITY");
                    defines._shared.OPACITYRGB = this._opacityTexture.getAlphaFromRGB;
                } else {
                    defines.OPACITY = false;
                }

                var reflectionTexture = this._getReflectionTexture();
                if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                    defines._shared.REFLECTION = true;
                    defines._shared.GAMMAREFLECTION = reflectionTexture.gammaSpace;
                    defines._shared.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
                    defines._shared.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;

                    if (reflectionTexture.coordinatesMode === BABYLON.Texture.INVCUBIC_MODE) {
                        defines._shared.INVERTCUBICMAP = true;
                    }

                    defines._shared.REFLECTIONMAP_3D = reflectionTexture.isCube;

                    switch (reflectionTexture.coordinatesMode) {
                        case BABYLON.Texture.CUBIC_MODE:
                        case BABYLON.Texture.INVCUBIC_MODE:
                            defines._shared.REFLECTIONMAP_CUBIC = true;
                            defines._shared.USE_LOCAL_REFLECTIONMAP_CUBIC = (<any>reflectionTexture).boundingBoxSize ? true : false;
                            break;
                        case BABYLON.Texture.EXPLICIT_MODE:
                            defines._shared.REFLECTIONMAP_EXPLICIT = true;
                            break;
                        case BABYLON.Texture.PLANAR_MODE:
                            defines._shared.REFLECTIONMAP_PLANAR = true;
                            break;
                        case BABYLON.Texture.PROJECTION_MODE:
                            defines._shared.REFLECTIONMAP_PROJECTION = true;
                            break;
                        case BABYLON.Texture.SKYBOX_MODE:
                            defines._shared.REFLECTIONMAP_SKYBOX = true;
                            break;
                        case BABYLON.Texture.SPHERICAL_MODE:
                            defines._shared.REFLECTIONMAP_SPHERICAL = true;
                            break;
                        case BABYLON.Texture.EQUIRECTANGULAR_MODE:
                            defines._shared.REFLECTIONMAP_EQUIRECTANGULAR = true;
                            break;
                        case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MODE:
                            defines._shared.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
                            break;
                        case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
                            defines._shared.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
                            break;
                    }

                    if (reflectionTexture.coordinatesMode !== BABYLON.Texture.SKYBOX_MODE) {
                        if (reflectionTexture.sphericalPolynomial) {
                            defines._shared.USESPHERICALFROMREFLECTIONMAP = true;
                            if (this._forceIrradianceInFragment || scene.getEngine().getCaps().maxVaryingVectors <= 8) {
                                defines._shared.USESPHERICALINVERTEX = false;
                            }
                            else {
                                defines._shared.USESPHERICALINVERTEX = true;
                            }
                        }
                    }
                } else {
                    defines._shared.REFLECTION = false;
                    defines._shared.REFLECTIONMAP_3D = false;
                    defines._shared.REFLECTIONMAP_SPHERICAL = false;
                    defines._shared.REFLECTIONMAP_PLANAR = false;
                    defines._shared.REFLECTIONMAP_CUBIC = false;
                    defines._shared.USE_LOCAL_REFLECTIONMAP_CUBIC = false;
                    defines._shared.REFLECTIONMAP_PROJECTION = false;
                    defines._shared.REFLECTIONMAP_SKYBOX = false;
                    defines._shared.REFLECTIONMAP_EXPLICIT = false;
                    defines._shared.REFLECTIONMAP_EQUIRECTANGULAR = false;
                    defines._shared.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
                    defines._shared.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
                    defines._shared.INVERTCUBICMAP = false;
                    defines._shared.USESPHERICALFROMREFLECTIONMAP = false;
                    defines._shared.USESPHERICALINVERTEX = false;
                    defines._shared.REFLECTIONMAP_OPPOSITEZ = false;
                    defines._shared.LODINREFLECTIONALPHA = false;
                    defines._shared.GAMMAREFLECTION = false;
                }

                if (this._emissiveTexture && BABYLON.StandardMaterial.EmissiveTextureEnabled) {
                    BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._emissiveTexture, defines, "EMISSIVE");
                } else {
                    defines.EMISSIVE = false;
                }

                if (BABYLON.StandardMaterial.SpecularTextureEnabled) {
                    if (this._metallicTexture) {
                        BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._metallicTexture, defines, "REFLECTIVITY");
                        defines._shared.ROUGHNESSSTOREINMETALMAPALPHA = this._useRoughnessFromMetallicTextureAlpha;
                        defines._shared.ROUGHNESSSTOREINMETALMAPGREEN = !this._useRoughnessFromMetallicTextureAlpha && this._useRoughnessFromMetallicTextureGreen;
                        defines._shared.METALLNESSSTOREINMETALMAPBLUE = this._useMetallnessFromMetallicTextureBlue;
                        defines._shared.AOSTOREINMETALMAPRED = this._useAmbientOcclusionFromMetallicTextureRed;
                    }
                    else if (this._reflectivityTexture) {
                        BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._reflectivityTexture, defines, "REFLECTIVITY");
                    } else {
                        defines.REFLECTIVITY = false;
                    }

                } else {
                    defines.REFLECTIVITY = false;
                }

                if (scene.getEngine().getCaps().standardDerivatives && this._bumpTexture && BABYLON.StandardMaterial.BumpTextureEnabled && !this._disableBumpMap) {
                    BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._bumpTexture, defines, "BUMP");
                } else {
                    defines.BUMP = false;
                }

                if (this._environmentBRDFTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
                    defines._shared.ENVIRONMENTBRDF = true;
                } else {
                    defines._shared.ENVIRONMENTBRDF = false;
                }

                if (this._shouldUseAlphaFromAlbedoTexture()) {
                    defines._shared.ALPHAFROMALBEDO = true;
                } else {
                    defines._shared.ALPHAFROMALBEDO = false;
                }
            }

            defines._shared.SPECULAROVERALPHA = this._useSpecularOverAlpha;

            defines._shared.USEPHYSICALLIGHTFALLOFF = this._usePhysicalLightFalloff;

            defines._shared.RADIANCEOVERALPHA = this._useRadianceOverAlpha;

            if (!this.backFaceCulling && this._twoSidedLighting) {
                defines._shared.TWOSIDEDLIGHTING = true;
            } else {
                defines._shared.TWOSIDEDLIGHTING = false;
            }

            defines._shared.PREMULTIPLYALPHA = (this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED || this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
            defines.ALPHABLEND = this.needAlphaBlendingForMesh(mesh);
            defines._shared.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel;
            defines._shared.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel;
        }


        defines._shared.FORCENORMALFORWARD = this._forceNormalForward;

        // Misc.
        this._pareDefinesForMisc(mesh, this._useLogarithmicDepth, defines);

        // Attribs
        this._prepareDefinesForAttributes(mesh, defines);
    }

    private _pareDefinesForMisc(mesh: BABYLON.AbstractMesh, useLogarithmicDepth: boolean, defines: any): void {
        if (defines._areMiscDirty) {
            defines["LOGARITHMICDEPTH"] = useLogarithmicDepth;
        }
    }

    private _prepareDefinesForAttributes(mesh: BABYLON.AbstractMesh, defines: any): boolean {
        if (!defines._areAttributesDirty && defines._needNormals === defines._normals && defines._needUVs === defines._uvs) {
            return false;
        }
        defines._normals = defines._needNormals;
        defines._uvs = defines._needUVs;
        defines["NORMAL"] = (defines._needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind));
        if (defines._needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
            defines["TANGENT"] = true;
        }
        if (defines._needUVs) {
            defines["UV1"] = mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind);
            defines["UV2"] = mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind);
        }
        else {
            defines["UV1"] = false;
            defines["UV2"] = false;
        }
        return true;
    }
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...