Browse Source

start of conversion

Andrew V Butt Sr 5 years ago
parent
commit
cd4a4bb80d

+ 2 - 1
materialsLibrary/src/index.ts

@@ -12,4 +12,5 @@ export * from "./simple";
 export * from "./sky";
 export * from "./terrain";
 export * from "./triPlanar";
-export * from "./water";
+export * from "./water";
+export * from "./skeletonDebug";

+ 26 - 0
materialsLibrary/src/skeletonDebug/IBoneWeightsMaterial.ts

@@ -0,0 +1,26 @@
+import { Color3, Skeleton } from 'babylonjs';
+/**
+ * Defines the constructor options for the BoneWeight Shader.
+ */
+export interface IBoneWeightsMaterialOptions{
+    /** Skeleton to Map */
+    skeleton: Skeleton;
+ 
+    /** Colors for Uninfluenced bones */
+    colorBase? : Color3;
+ 
+    /** Colors for 0.0-0.25 Weight bones */
+    colorZero? : Color3;
+ 
+    /** Color for 0.25-0.5 Weight Influence */
+    colorQuarter? : Color3;
+ 
+    /** Color for 0.5-0.75 Weight Influence */
+    colorHalf? : Color3;
+ 
+    /** Color for 0.75-1 Weight Influence */
+    colorFull? : Color3;
+ 
+    /** Color for Zero Weight Influence */
+    targetBoneIndex? : number;
+ }

+ 9 - 0
materialsLibrary/src/skeletonDebug/boneWeights.fragment.fx

@@ -0,0 +1,9 @@
+precision highp float;
+varying vec3 vPosition;
+
+varying vec3 vColor;
+
+void main() {
+	vec4 color = vec4(vColor, 1.0);
+	gl_FragColor = color;
+}

+ 53 - 0
materialsLibrary/src/skeletonDebug/boneWeights.vertex.fx

@@ -0,0 +1,53 @@
+precision highp float;
+
+attribute vec3 position;
+attribute vec2 uv;
+
+uniform mat4 view;
+uniform mat4 projection;
+uniform mat4 worldViewProjection;
+
+#include<bonesDeclaration>
+#include<instancesDeclaration>
+
+varying vec3 vColor;
+
+uniform vec3 colorBase;
+uniform vec3 colorZero;
+uniform vec3 colorQuarter;
+uniform vec3 colorHalf;
+uniform vec3 colorFull;
+
+uniform float targetBoneIndex;
+
+void main() {
+	vec3 positionUpdated = position;
+
+	#include<instancesVertex>
+	#include<bonesVertex>
+
+	vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
+
+	vec3 color = colorBase;
+	float totalWeight = 0.;
+	if(matricesIndices[0] == targetBoneIndex && matricesWeights[0] > 0.){
+		totalWeight += matricesWeights[0];
+	}
+	if(matricesIndices[1] == targetBoneIndex && matricesWeights[1] > 0.){
+		totalWeight += matricesWeights[1];
+	}
+	if(matricesIndices[2] == targetBoneIndex && matricesWeights[2] > 0.){
+		totalWeight += matricesWeights[2];
+	}
+	if(matricesIndices[3] == targetBoneIndex && matricesWeights[3] > 0.){
+		totalWeight += matricesWeights[3];
+	}
+
+	color = mix(color, colorZero, smoothstep(0., 0.25, totalWeight));
+	color = mix(color, colorQuarter, smoothstep(0.25, 0.5, totalWeight));
+	color = mix(color, colorHalf, smoothstep(0.5, 0.75, totalWeight));
+	color = mix(color, colorFull, smoothstep(0.75, 1.0, totalWeight));
+
+
+	gl_Position = projection * view * worldPos;
+}

+ 404 - 0
materialsLibrary/src/skeletonDebug/boneWeightsMaterial.ts

@@ -0,0 +1,404 @@
+
+import { Matrix } from "babylonjs/Maths/math.vector";
+import { Nullable } from "babylonjs/types";
+import { IEffectCreationOptions } from "babylonjs/Materials/effect";
+
+import { MaterialHelper } from "babylonjs/Materials/materialHelper";
+import { PushMaterial } from "babylonjs/Materials/pushMaterial";
+
+import { VertexBuffer } from "babylonjs/Meshes/buffer";
+import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+import { SubMesh } from "babylonjs/Meshes/subMesh";
+import { Mesh } from "babylonjs/Meshes/mesh";
+import { Scene } from "babylonjs/scene";
+import { _TypeStore } from 'babylonjs/Misc/typeStore';
+
+import "./boneWeights.fragment";
+import "./boneWeights.vertex";
+import { EffectFallbacks } from 'babylonjs/Materials/effectFallbacks';
+import { IBoneWeightsMaterialOptions } from "./IBoneWeightsMaterial";
+import { Skeleton, Color3, Effect } from 'babylonjs';
+
+const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
+export class BoneWeightsMaterial extends PushMaterial {   
+
+    public skeleton: Skeleton;
+    public colorBase: Color3;
+    public colorZero: Color3;
+    public colorQuarter: Color3;
+    public colorHalf: Color3;
+    public colorFull: Color3;
+    public targetBoneIndex: number;  
+    private _renderId: number;
+    private _multiview: boolean = false;
+    private _cachedWorldViewProjectionMatrix = new Matrix();
+    private _cachedWorldViewMatrix = new Matrix();
+    private _cachedDefines: string;
+    public uniforms : string[];   
+
+    constructor(name: string, options:IBoneWeightsMaterialOptions, scene: Scene) {
+        super(name, scene);
+        this.skeleton = options.skeleton;
+        this.colorBase = options.colorBase ?? Color3.Black();
+        this.colorZero = options.colorZero ?? Color3.Blue();
+        this.colorQuarter = options.colorQuarter ?? Color3.Green();
+        this.colorHalf = options.colorHalf ?? Color3.Yellow();
+        this.colorFull = options.colorFull ?? Color3.Red();
+        this.targetBoneIndex = options.targetBoneIndex ?? 0;
+    }
+
+    public needAlphaBlending(): boolean {
+        return (this.alpha < 1.0);
+    }
+
+    public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
+        return this.needAlphaBlending() || (mesh.visibility < 1.0);
+    }
+
+    public needAlphaTesting(): boolean {
+        return false;
+    } 
+
+    // Methods
+    /*public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
+        if (this.isFrozen) {
+            if (subMesh.effect && subMesh.effect._wasPreviouslyReady) {
+                return true;
+            }
+        }
+
+        if (!subMesh._materialDefines) {
+            subMesh._materialDefines = new BoneWeightsMaterialDefines();
+        }
+
+        var defines = <BoneWeightsMaterialDefines>subMesh._materialDefines;
+        var scene = this.getScene();
+
+        if (this._isReadyForSubMesh(subMesh)) {
+            return true;
+        }
+
+        var engine = scene.getEngine();
+
+        // Values that need to be evaluated on every frame
+        MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false);
+        // Attribs
+        MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true);
+
+        // Get correct effect
+        if (defines.isDirty) {
+            defines.markAsProcessed();
+            scene.resetCachedMaterial();
+            // Fallbacks
+            var fallbacks = new EffectFallbacks(); 
+
+            if (defines.NUM_BONE_INFLUENCERS > 0) {
+                fallbacks.addCPUSkinningFallback(0, mesh);
+            }
+
+            //Attributes
+            var attribs = [VertexBuffer.PositionKind];
+
+            if (defines.NORMAL) {
+                attribs.push(VertexBuffer.NormalKind);
+            }
+
+            MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
+            MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
+            var shaderName = "boneWeights";
+            var join = defines.toString();
+
+            var uniforms = [
+                'world', 'worldView', 'worldViewProjection', 'view', 'projection', 'viewProjection',
+                'colorBase', 'colorZero', 'colorQuarter', 'colorHalf', 'colorFull', 'targetBoneIndex'
+            ]
+            var uniformBuffers = new Array<string>();
+
+            MaterialHelper.PrepareUniformsAndSamplersList(<IEffectCreationOptions>{
+                uniformsNames: uniforms,
+                uniformBuffersNames: uniformBuffers,
+                defines: defines,
+                maxSimultaneousLights: 4
+            });
+
+            subMesh.setEffect(scene.getEngine().createEffect(shaderName,
+                <IEffectCreationOptions>{
+                    attributes: attribs,
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: [],
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: this.onCompiled2,
+                    onError: this.onError2,
+                    indexParameters: { maxSimultaneousLights: 4 }
+                }, engine), defines);
+        }
+        if (!subMesh.effect || !subMesh.effect.isReady()) {
+            return false;
+        }
+
+        defines._renderId = scene.getRenderId();
+        subMesh.effect._wasPreviouslyReady = true;
+
+        return true;
+    }*/
+
+    private _checkCache(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+        if (!mesh) {
+            return true;
+        }
+
+        if (this._effect && (this._effect.defines.indexOf("#define INSTANCES") !== -1) !== useInstances) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Specifies that the submesh is ready to be used
+     * @param mesh defines the mesh to check
+     * @param subMesh defines which submesh to check
+     * @param useInstances specifies that instances should be used
+     * @returns a boolean indicating that the submesh is ready or not
+     */
+    public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
+        return this.isReady(mesh, useInstances);
+    }
+
+    /**
+     * Checks if the material is ready to render the requested mesh
+     * @param mesh Define the mesh to render
+     * @param useInstances Define whether or not the material is used with instances
+     * @returns true if ready, otherwise false
+     */
+    public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+        if (this._effect && this.isFrozen) {
+            if (this._effect._wasPreviouslyReady) {
+                return true;
+            }
+        }
+
+        var scene = this.getScene();
+        var engine = scene.getEngine();
+
+        if (!this.checkReadyOnEveryCall) {
+            if (this._renderId === scene.getRenderId()) {
+                if (this._checkCache(mesh, useInstances)) {
+                    return true;
+                }
+            }
+        }
+
+        // Instances
+        let defines = [];
+        let attribs = [];
+        let shaderUniforms:string[] = [
+            'world', 'worldView', 'worldViewProjection', 'view', 'projection', 'viewProjection',
+            'colorBase', 'colorZero', 'colorQuarter', 'colorHalf', 'colorFull', 'targetBoneIndex'
+        ]
+        let shaderSamplers:string[] = []
+        var fallbacks = new EffectFallbacks();       
+
+        attribs.push("position", "normal", "uv");  
+
+        if (useInstances) {
+            defines.push("#define INSTANCES");
+            MaterialHelper.PushAttributesForInstances(attribs);
+            if (mesh?.hasThinInstances) {
+                defines.push("#define THIN_INSTANCES");
+            }
+        }
+
+        // Bones
+        let numInfluencers = 0;
+
+        if (mesh && mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
+            attribs.push(VertexBuffer.MatricesIndicesKind);
+            attribs.push(VertexBuffer.MatricesWeightsKind);
+            if (mesh.numBoneInfluencers > 4) {
+                attribs.push(VertexBuffer.MatricesIndicesExtraKind);
+                attribs.push(VertexBuffer.MatricesWeightsExtraKind);
+            }
+
+            const skeleton = mesh.skeleton;
+            numInfluencers = mesh.numBoneInfluencers;
+
+            defines.push("#define NUM_BONE_INFLUENCERS " + numInfluencers);
+            fallbacks.addCPUSkinningFallback(0, mesh);
+
+            if (skeleton.isUsingTextureForMatrices) {
+                defines.push("#define BONETEXTURE");
+
+                if (shaderUniforms.indexOf("boneTextureWidth") === -1) {
+                    shaderUniforms.push("boneTextureWidth");
+                }
+
+                if (shaderSamplers.indexOf("boneSampler") === -1) {
+                    shaderSamplers.push("boneSampler");
+                }
+            } else {
+                defines.push("#define BonesPerMesh " + (skeleton.bones.length + 1));
+
+                if (shaderUniforms.indexOf("mBones") === -1) {
+                    shaderUniforms.push("mBones");
+                }
+            }
+
+        } else {
+            defines.push("#define NUM_BONE_INFLUENCERS 0");
+        }
+    
+        // Alpha test
+        if (mesh && this._shouldTurnAlphaTestOn(mesh)) {
+            defines.push("#define ALPHATEST");
+        }
+
+        let shaderName = 'boneWeights',
+            uniforms = shaderUniforms,
+            uniformBuffers:string[] = [],
+            samplers = shaderSamplers;
+
+        var previousEffect = this._effect;
+        var join = defines.join("\n");
+
+        if (this._cachedDefines !== join) {
+            this._cachedDefines = join;
+
+            this._effect = engine.createEffect(shaderName, <IEffectCreationOptions>{
+                attributes: attribs,
+                uniformsNames: uniforms,
+                uniformBuffersNames: uniformBuffers,
+                samplers: samplers,
+                defines: join,
+                fallbacks: fallbacks,
+                onCompiled: this.onCompiled,
+                onError: this.onError,
+                indexParameters: { maxSimultaneousMorphTargets: numInfluencers }
+            }, engine);
+
+            if (this._onEffectCreatedObservable) {
+                onCreatedEffectParameters.effect = this._effect;
+                this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+            }
+        }
+
+        this.uniforms = uniforms
+
+        if (!this._effect?.isReady() ?? true) {
+            return false;
+        }
+
+        if (previousEffect !== this._effect) {
+            scene.resetCachedMaterial();
+        }
+
+        this._renderId = scene.getRenderId();
+        this._effect._wasPreviouslyReady = true;
+
+        return true;
+    }
+
+    /**
+     * Binds the world matrix to the material
+     * @param world defines the world transformation matrix
+     * @param effectOverride - If provided, use this effect instead of internal effect
+     */
+    public bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void {
+        var scene = this.getScene();
+
+        const effect = effectOverride ?? this._effect;
+
+        if (!effect) {
+            return;
+        }
+
+        if (this.uniforms.indexOf("world") !== -1) {
+            effect.setMatrix("world", world);
+        }
+
+        if (this.uniforms.indexOf("worldView") !== -1) {
+            world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
+            effect.setMatrix("worldView", this._cachedWorldViewMatrix);
+        }
+
+        if (this.uniforms.indexOf("worldViewProjection") !== -1) {
+            world.multiplyToRef(scene.getTransformMatrix(), this._cachedWorldViewProjectionMatrix);
+            effect.setMatrix("worldViewProjection", this._cachedWorldViewProjectionMatrix);
+        }
+    }
+
+    /**
+     * Binds the submesh to this material by preparing the effect and shader to draw
+     * @param world defines the world transformation matrix
+     * @param mesh defines the mesh containing the submesh
+     * @param subMesh defines the submesh to bind the material to
+     */
+    public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+        this.bind(world, mesh, subMesh._effectOverride);
+    }
+
+    /**
+     * Binds the material to the mesh
+     * @param world defines the world transformation matrix
+     * @param mesh defines the mesh to bind the material to
+     * @param effectOverride - If provided, use this effect instead of internal effect
+     */
+    public bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void {
+        // Std values
+        this.bindOnlyWorldMatrix(world, effectOverride);
+
+        const effect = effectOverride ?? this._effect;
+
+        if (effect && this.getScene().getCachedMaterial() !== this) {
+            if (this.uniforms.indexOf("view") !== -1) {
+                effect.setMatrix("view", this.getScene().getViewMatrix());
+            }
+
+            if (this.uniforms.indexOf("projection") !== -1) {
+                effect.setMatrix("projection", this.getScene().getProjectionMatrix());
+            }
+
+            if (this.uniforms.indexOf("viewProjection") !== -1) {
+                effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
+                if (this._multiview) {
+                    effect.setMatrix("viewProjectionR", this.getScene()._transformMatrixR);
+                }
+            }
+
+            if (this.getScene().activeCamera && this.uniforms.indexOf("cameraPosition") !== -1) {
+                effect.setVector3("cameraPosition", this.getScene().activeCamera!.globalPosition);
+            }
+        }
+
+            // Bones
+            if(effect){
+                MaterialHelper.BindBonesParameters(mesh, effect);
+            }
+            const seffect = this._effect;
+
+            this._effect = effect; // make sure the active effect is the right one if there are some observers for onBind that would need to get the current effect
+            if(mesh){
+                this._afterBind(mesh);
+            }
+            this._effect = seffect;        
+    }   
+
+    protected _afterBind(mesh: Mesh): void {
+        super._afterBind(mesh);
+        this.getScene()._cachedEffect = this._effect;
+    }
+
+    public dispose(forceDisposeEffect?: boolean): void {
+        super.dispose(forceDisposeEffect);
+    }
+
+    public getClassName(): string {
+        return "BoneWeightsMaterial";
+    }
+
+}
+
+_TypeStore.RegisteredTypes["BABYLON.BoneWeightsMaterial"] = BoneWeightsMaterial;

+ 1 - 0
materialsLibrary/src/skeletonDebug/index.ts

@@ -0,0 +1 @@
+export * from "./boneWeightsMaterial";

+ 0 - 26
src/Debug/ISkeletonViewer.ts

@@ -42,32 +42,6 @@ export interface ISkeletonViewerDisplayOptions{
 }
 
 /**
- * Defines the constructor options for the BoneWeight Shader.
- */
-export interface IBoneWeightShaderOptions{
-   /** Skeleton to Map */
-   skeleton: Skeleton;
-
-   /** Colors for Uninfluenced bones */
-   colorBase? : Color3;
-
-   /** Colors for 0.0-0.25 Weight bones */
-   colorZero? : Color3;
-
-   /** Color for 0.25-0.5 Weight Influence */
-   colorQuarter? : Color3;
-
-   /** Color for 0.5-0.75 Weight Influence */
-   colorHalf? : Color3;
-
-   /** Color for 0.75-1 Weight Influence */
-   colorFull? : Color3;
-
-   /** Color for Zero Weight Influence */
-   targetBoneIndex? : number;
-}
-
-/**
  * Simple structure of the gradient steps for the Color Map.
  */
 export interface ISkeletonMapShaderColorMapKnot{

+ 3 - 3
src/Debug/skeletonViewer.ts

@@ -15,7 +15,7 @@ import { ShaderMaterial } from '../Materials/shaderMaterial';
 import { DynamicTexture } from '../Materials/Textures/dynamicTexture';
 import { VertexBuffer } from '../Meshes/buffer';
 
-import { ISkeletonViewerOptions, IBoneWeightShaderOptions, ISkeletonMapShaderOptions, ISkeletonMapShaderColorMapKnot } from './ISkeletonViewer';
+import { ISkeletonViewerOptions, ISkeletonMapShaderOptions, ISkeletonMapShaderColorMapKnot } from './ISkeletonViewer';
 import { Observer } from '../Misc/observable';
 
 import { SphereBuilder } from '../Meshes/Builders/sphereBuilder';
@@ -38,7 +38,7 @@ export class SkeletonViewer {
      * @param scene The scene that the shader is scoped to
      * @returns The created ShaderMaterial
      */
-    static CreateBoneWeightShader(options: IBoneWeightShaderOptions, scene: Scene): ShaderMaterial {
+    /*static CreateBoneWeightShader(options: IBoneWeightShaderOptions, scene: Scene): ShaderMaterial {
 
         let skeleton: Skeleton = options.skeleton;
         let colorBase: Color3 = options.colorBase ?? Color3.Black();
@@ -134,7 +134,7 @@ export class SkeletonViewer {
         shader.transparencyMode = Material.MATERIAL_OPAQUE;
 
         return shader;
-    }
+    }*/
 
     /** public static method to create a BoneWeight Shader
      * @param options The constructor options