Explorar o código

Merge pull request #9724 from Popov72/fix-shadermaterial-morpth

ShaderMaterial: Add support for morph targets
sebavan %!s(int64=4) %!d(string=hai) anos
pai
achega
1e4815113b
Modificáronse 2 ficheiros con 62 adicións e 9 borrados
  1. 1 0
      dist/preview release/what's new.md
  2. 61 9
      src/Materials/shaderMaterial.ts

+ 1 - 0
dist/preview release/what's new.md

@@ -35,6 +35,7 @@
 ### Materials
 
 - Added an `OcclusionMaterial` to simplify depth-only rendering of geometry ([rgerd](https://github.com/rgerd))
+- Added support for morph targets to `ShaderMaterial` ([Popov72](https://github.com/Popov72))
 
 ### Inspector
 

+ 61 - 9
src/Materials/shaderMaterial.ts

@@ -504,6 +504,11 @@ export class ShaderMaterial extends Material {
         var attribs = [];
         var fallbacks = new EffectFallbacks();
 
+        let shaderName = this._shaderPath,
+            uniforms = this._options.uniforms,
+            uniformBuffers = this._options.uniformBuffers,
+            samplers = this._options.samplers;
+
         // global multiview
         if (engine.getCaps().multiview &&
             scene.activeCamera &&
@@ -539,7 +544,6 @@ export class ShaderMaterial extends Material {
         }
 
         // Bones
-        let numInfluencers = 0;
         if (mesh && mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
             attribs.push(VertexBuffer.MatricesIndicesKind);
             attribs.push(VertexBuffer.MatricesWeightsKind);
@@ -550,8 +554,7 @@ export class ShaderMaterial extends Material {
 
             const skeleton = mesh.skeleton;
 
-            numInfluencers = mesh.numBoneInfluencers;
-            defines.push("#define NUM_BONE_INFLUENCERS " + numInfluencers);
+            defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
             fallbacks.addCPUSkinningFallback(0, mesh);
 
             if (skeleton.isUsingTextureForMatrices) {
@@ -575,6 +578,50 @@ export class ShaderMaterial extends Material {
             defines.push("#define NUM_BONE_INFLUENCERS 0");
         }
 
+        // Morph
+        let numInfluencers = 0;
+        const manager = (<Mesh>mesh).morphTargetManager;
+        if (manager) {
+            const uv = manager.supportsUVs && defines.indexOf("#define UV1") !== -1;
+            const tangent = manager.supportsTangents && defines.indexOf("#define TANGENT") !== -1;
+            const normal = manager.supportsNormals && defines.indexOf("#define NORMAL") !== -1;
+            numInfluencers = manager.numInfluencers;
+            if (uv) {
+                defines.push("#define MORPHTARGETS_UV");
+            }
+            if (tangent) {
+                defines.push("#define MORPHTARGETS_TANGENT");
+            }
+            if (normal) {
+                defines.push("#define MORPHTARGETS_NORMAL");
+            }
+            if (numInfluencers > 0) {
+                defines.push("#define MORPHTARGETS");
+            }
+            defines.push("#define NUM_MORPH_INFLUENCERS " + numInfluencers);
+            for (var index = 0; index < numInfluencers; index++) {
+                attribs.push(VertexBuffer.PositionKind + index);
+
+                if (normal) {
+                    attribs.push(VertexBuffer.NormalKind + index);
+                }
+
+                if (tangent) {
+                    attribs.push(VertexBuffer.TangentKind + index);
+                }
+
+                if (uv) {
+                    attribs.push(VertexBuffer.UVKind + "_" + index);
+                }
+            }
+            if (numInfluencers > 0) {
+                uniforms = uniforms.slice();
+                uniforms.push("morphTargetInfluences");
+            }
+        } else {
+            defines.push("#define NUM_MORPH_INFLUENCERS 0");
+        }
+
         // Textures
         for (var name in this._textures) {
             if (!this._textures[name].isReady()) {
@@ -587,11 +634,6 @@ export class ShaderMaterial extends Material {
             defines.push("#define ALPHATEST");
         }
 
-        let shaderName = this._shaderPath,
-            uniforms = this._options.uniforms,
-            uniformBuffers = this._options.uniformBuffers,
-            samplers = this._options.samplers;
-
         if (this.customShaderNameResolve) {
             uniforms = uniforms.slice();
             uniformBuffers = uniformBuffers.slice();
@@ -688,7 +730,9 @@ export class ShaderMaterial extends Material {
 
         const effect = effectOverride ?? this._effect;
 
-        if (effect && this.getScene().getCachedMaterial() !== this) {
+        let mustRebind = this.getScene().getCachedMaterial() !== this;
+
+        if (effect && mustRebind) {
             if (this._options.uniforms.indexOf("view") !== -1) {
                 effect.setMatrix("view", this.getScene().getViewMatrix());
             }
@@ -809,6 +853,14 @@ export class ShaderMaterial extends Material {
             }
         }
 
+        if (effect && mesh && (mustRebind || !this.isFrozen)) {
+            // Morph targets
+            const manager = (<Mesh>mesh).morphTargetManager;
+            if (manager && manager.numInfluencers > 0) {
+                MaterialHelper.BindMorphTargetParameters(<Mesh>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