فهرست منبع

Fix compile materials issues in glTF loader

Gary Hsu 7 سال پیش
والد
کامیت
93db87da17

BIN
Playground/scenes/TwoQuads/TwoQuads.bin


+ 5 - 17
Playground/scenes/TwoQuads/TwoQuads.gltf

@@ -20,16 +20,10 @@
       "bufferView": 1,
       "componentType": 5126,
       "count": 4,
-      "type": "VEC3"
-    },
-    {
-      "bufferView": 2,
-      "componentType": 5126,
-      "count": 4,
       "type": "VEC2"
     },
     {
-      "bufferView": 3,
+      "bufferView": 2,
       "componentType": 5125,
       "count": 6,
       "type": "SCALAR"
@@ -41,7 +35,7 @@
   "buffers": [
     {
       "uri": "TwoQuads.bin",
-      "byteLength": 152
+      "byteLength": 104
     }
   ],
   "bufferViews": [
@@ -52,16 +46,11 @@
     {
       "buffer": 0,
       "byteOffset": 48,
-      "byteLength": 48
-    },
-    {
-      "buffer": 0,
-      "byteOffset": 96,
       "byteLength": 32
     },
     {
       "buffer": 0,
-      "byteOffset": 128,
+      "byteOffset": 80,
       "byteLength": 24
     }
   ],
@@ -122,10 +111,9 @@
         {
           "attributes": {
             "POSITION": 0,
-            "NORMAL": 1,
-            "TEXCOORD_0": 2
+            "TEXCOORD_0": 1
           },
-          "indices": 3,
+          "indices": 2,
           "material": 0
         }
       ]

+ 10 - 6
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -525,17 +525,18 @@ module BABYLON.GLTF2 {
                     babylonMesh._delayInfo.push(kind);
                 }
 
+                if (attribute === "COLOR_0") {
+                    // Assume vertex color has alpha on the mesh. The alphaMode of the material controls whether the material should use alpha or not.
+                    babylonMesh.hasVertexAlpha = true;
+                }
+
                 const accessor = GLTFLoader._GetProperty(`${context}/attributes/${attribute}`, this._gltf.accessors, attributes[attribute]);
 
                 promises.push(this._loadAccessorAsync(`#/accessors/${accessor._index}`, accessor).then(data => {
                     let attributeData = GLTFLoader._ConvertToFloat32Array(context, accessor, data);
 
-                    if (attribute === "COLOR_0") {
-                        // Assume vertex color has alpha on the mesh. The alphaMode of the material controls whether the material should use alpha or not.
-                        babylonMesh.hasVertexAlpha = true;
-                        if (accessor.type === "VEC3") {
-                            attributeData = GLTFLoader._ConvertVec3ToVec4(context, attributeData);
-                        }
+                    if (attribute === "COLOR_0" && accessor.type === "VEC3") {
+                        attributeData = GLTFLoader._ConvertVec3ToVec4(context, attributeData);
                     }
 
                     babylonVertexData.set(attributeData, kind);
@@ -1535,6 +1536,9 @@ module BABYLON.GLTF2 {
                     const babylonMeshes = material._babylonMeshes;
                     if (babylonMaterial && babylonMeshes) {
                         for (const babylonMesh of babylonMeshes) {
+                            // Ensure nonUniformScaling is set if necessary.
+                            babylonMesh.computeWorldMatrix(true);
+
                             promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));
                             if (this.useClipPlane) {
                                 promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));

+ 36 - 34
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -31,6 +31,9 @@ describe('Babylon Scene Loader', function () {
             deterministicLockstep: false,
             lockstepMaxSteps: 1
         });
+
+        // Avoid creating normals in PBR materials.
+        subject.getCaps().standardDerivatives = true;
     });
 
     /**
@@ -141,40 +144,6 @@ describe('Babylon Scene Loader', function () {
             return Promise.race(promises);
         });
 
-        it('Load BoomBox with compileMaterials', () => {
-            let createShaderProgramSpy: sinon.SinonSpy;
-
-            const promises = new Array<Promise<void>>();
-
-            BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
-                loader.compileMaterials = true;
-
-                promises.push(loader.whenCompleteAsync().then(() => {
-                    try {
-                        expect(createShaderProgramSpy.called, "createShaderProgramSpy.called").to.be.false;
-                    }
-                    finally {
-                        createShaderProgramSpy.restore();
-                    }
-                }));
-            }, undefined, undefined, undefined, true);
-
-            const scene = new BABYLON.Scene(subject);
-            promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(() => {
-                for (const mesh of scene.meshes) {
-                    if (mesh.material) {
-                        expect(mesh.material.isReady(mesh)).to.be.true;
-                    }
-                }
-
-                createShaderProgramSpy = sinon.spy(subject, "createShaderProgram");
-            }));
-
-            promises.push(scene.whenReadyAsync());
-
-            return Promise.all(promises);
-        });
-
         it('Load BoomBox with rootMesh.isEnabled check', () => {
             const scene = new BABYLON.Scene(subject);
             let rootMesh: BABYLON.AbstractMesh;
@@ -200,6 +169,39 @@ describe('Babylon Scene Loader', function () {
             });
         });
 
+        it('Load CompileMaterialsTest', () => {
+            const scene = new BABYLON.Scene(subject);
+            const promises = new Array<Promise<void>>();
+            let createShaderProgramSpy: sinon.SinonSpy;
+
+            subject.runRenderLoop(() => {
+                for (const mesh of scene.meshes) {
+                    if (mesh.material && mesh.isEnabled()) {
+                        expect(mesh.material.isReady(mesh), "mesh material is ready").to.be.true;
+                    }
+                }
+            });
+
+            BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
+                loader.compileMaterials = true;
+
+                promises.push(loader.whenCompleteAsync().then(() => {
+                    try {
+                        expect(createShaderProgramSpy.called, "createShaderProgramSpy.called").to.be.false;
+                    }
+                    finally {
+                        createShaderProgramSpy.restore();
+                    }
+                }));
+            }, undefined, undefined, undefined, true);
+
+            promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/CompileMaterialsTest/", "Test.gltf", scene).then(() => {
+                createShaderProgramSpy = sinon.spy(subject, "createShaderProgram");
+            }));
+
+            return Promise.all(promises);
+        });
+
         it('Load Alien', () => {
             const scene = new BABYLON.Scene(subject);
             return BABYLON.SceneLoader.ImportMeshAsync(null, "/Playground/scenes/Alien/", "Alien.gltf", scene).then(result => {