Przeglądaj źródła

Adding support for specifying tangents to vertex data

Dean Wadsworth 8 lat temu
rodzic
commit
c5ef2d449b

+ 8 - 0
src/Materials/babylon.pbrMaterial.ts

@@ -21,6 +21,7 @@
         public EMISSIVEFRESNEL = false;
         public FRESNEL = false;
         public NORMAL = false;
+        public TANGENT = false;
         public UV1 = false;
         public UV2 = false;
         public VERTEXCOLOR = false;
@@ -946,6 +947,9 @@
             if (mesh) {
                 if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     this._defines.NORMAL = true;
+                    if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                        this._defines.TANGENT = true;
+                    }
                 }
                 if (needUVs) {
                     if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
@@ -1050,6 +1054,10 @@
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
+                if (this._defines.TANGENT) {
+                    attribs.push(VertexBuffer.TangentKind);
+                }
+
                 if (this._defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }

+ 8 - 0
src/Materials/babylon.standardMaterial.ts

@@ -24,6 +24,7 @@
         public EMISSIVEFRESNEL = false;
         public FRESNEL = false;
         public NORMAL = false;
+        public TANGENT = false;
         public UV1 = false;
         public UV2 = false;
         public VERTEXCOLOR = false;
@@ -547,6 +548,9 @@
             if (mesh) {
                 if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     this._defines.NORMAL = true;
+                    if (mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                        this._defines.TANGENT = true;
+                    }
                 }
                 if (needUVs) {
                     if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
@@ -651,6 +655,10 @@
                     attribs.push(VertexBuffer.NormalKind);
                 }
 
+                if (this._defines.TANGENT) {
+                    attribs.push(VertexBuffer.TangentKind);
+                }
+
                 if (this._defines.UV1) {
                     attribs.push(VertexBuffer.UVKind);
                 }

+ 37 - 3
src/Math/babylon.math.ts

@@ -2200,7 +2200,7 @@
         /**
          * Returns a new Vector4 set from the starting index of the passed array.  
          */
-        public static FromArray(array: number[], offset?: number): Vector4 {
+        public static FromArray(array: number[]  | Float32Array, offset?: number): Vector4 {
             if (!offset) {
                 offset = 0;
             }
@@ -2209,7 +2209,7 @@
         /**
          * Updates the passed vector "result" from the starting index of the passed array.  
          */
-        public static FromArrayToRef(array: number[], offset: number, result: Vector4): void {
+        public static FromArrayToRef(array: number[] | Float32Array, offset: number, result: Vector4): void {
             result.x = array[offset];
             result.y = array[offset + 1];
             result.z = array[offset + 2];
@@ -2275,7 +2275,6 @@
         /**
          * Returns the squared distance (float) between the vectors "value1" and "value2".  
          */
-        publi
         public static DistanceSquared(value1: Vector4, value2: Vector4): number {
             var x = value1.x - value2.x;
             var y = value1.y - value2.y;
@@ -2292,6 +2291,41 @@
             center.scaleInPlace(0.5);
             return center;
         }
+
+        /**
+         * Returns a new Vector4 set with the result of the normal transformation by the passed matrix of the passed vector.  
+         * This methods computes transformed normalized direction vectors only.  
+         */
+        public static TransformNormal(vector: Vector4, transformation: Matrix): Vector4 {
+            var result = Vector4.Zero();
+            Vector4.TransformNormalToRef(vector, transformation, result);
+            return result;
+        }
+
+        /**
+         * Sets the passed vector "result" with the result of the normal transformation by the passed matrix of the passed vector.  
+         * This methods computes transformed normalized direction vectors only. 
+         */
+        public static TransformNormalToRef(vector: Vector4, transformation: Matrix, result: Vector4): void {
+            var x = (vector.x * transformation.m[0]) + (vector.y * transformation.m[4]) + (vector.z * transformation.m[8]);
+            var y = (vector.x * transformation.m[1]) + (vector.y * transformation.m[5]) + (vector.z * transformation.m[9]);
+            var z = (vector.x * transformation.m[2]) + (vector.y * transformation.m[6]) + (vector.z * transformation.m[10]);
+            result.x = x;
+            result.y = y;
+            result.z = z;
+            result.w = vector.w;
+        }
+
+        /**
+         * Sets the passed vector "result" with the result of the normal transformation by the passed matrix of the passed floats (x, y, z, w).  
+         * This methods computes transformed normalized direction vectors only. 
+         */
+        public static TransformNormalFromFloatsToRef(x: number, y: number, z: number, w: number, transformation: Matrix, result: Vector4): void {
+            result.x = (x * transformation.m[0]) + (y * transformation.m[4]) + (z * transformation.m[8]);
+            result.y = (x * transformation.m[1]) + (y * transformation.m[5]) + (z * transformation.m[9]);
+            result.z = (x * transformation.m[2]) + (y * transformation.m[6]) + (z * transformation.m[10]);
+            result.w = w;
+        }
     }
 
     export interface ISize {

+ 51 - 8
src/Mesh/babylon.mesh.vertexData.ts

@@ -14,6 +14,7 @@
     export class VertexData {
         public positions: number[] | Float32Array;
         public normals: number[] | Float32Array;
+        public tangents: number[] | Float32Array;
         public uvs: number[] | Float32Array;
         public uvs2: number[] | Float32Array;
         public uvs3: number[] | Float32Array;
@@ -35,6 +36,9 @@
                 case VertexBuffer.NormalKind:
                     this.normals = data;
                     break;
+                case VertexBuffer.TangentKind:
+                    this.tangents = data;
+                    break;
                 case VertexBuffer.UVKind:
                     this.uvs = data;
                     break;
@@ -118,6 +122,10 @@
                 meshOrGeometry.setVerticesData(VertexBuffer.NormalKind, this.normals, updatable);
             }
 
+            if (this.tangents) {
+                meshOrGeometry.setVerticesData(VertexBuffer.TangentKind, this.tangents, updatable);
+            }
+
             if (this.uvs) {
                 meshOrGeometry.setVerticesData(VertexBuffer.UVKind, this.uvs, updatable);
             }
@@ -177,6 +185,10 @@
                 meshOrGeometry.updateVerticesData(VertexBuffer.NormalKind, this.normals, updateExtends, makeItUnique);
             }
 
+            if (this.tangents) {
+                meshOrGeometry.updateVerticesData(VertexBuffer.TangentKind, this.tangents, updateExtends, makeItUnique);
+            }
+
             if (this.uvs) {
                 meshOrGeometry.updateVerticesData(VertexBuffer.UVKind, this.uvs, updateExtends, makeItUnique);
             }
@@ -259,6 +271,22 @@
                     this.normals[index + 2] = transformed.z;
                 }
             }
+
+            if (this.tangents) {
+                var tangent = Vector4.Zero();
+                var tangentTransformed = Vector4.Zero();
+
+                for (index = 0; index < this.tangents.length; index += 4) {
+                    Vector4.FromArrayToRef(this.tangents, index, tangent);
+
+                    Vector4.TransformNormalToRef(tangent, matrix, tangentTransformed);
+                    this.tangents[index] = tangentTransformed.x;
+                    this.tangents[index + 1] = tangentTransformed.y;
+                    this.tangents[index + 2] = tangentTransformed.z;
+                    this.tangents[index + 3] = tangentTransformed.w;
+                }
+            }
+
             return this;
         }
 
@@ -281,6 +309,7 @@
 
             this.positions = this._mergeElement(this.positions, other.positions);
             this.normals = this._mergeElement(this.normals, other.normals);
+            this.tangents = this._mergeElement(this.tangents, other.tangents);
             this.uvs = this._mergeElement(this.uvs, other.uvs);
             this.uvs2 = this._mergeElement(this.uvs2, other.uvs2);
             this.uvs3 = this._mergeElement(this.uvs3, other.uvs3);
@@ -339,6 +368,10 @@
                 serializationObject.normals = this.normals;
             }
 
+            if (this.tangents) {
+                serializationObject.tangents = this.tangents;
+            }
+
             if (this.uvs) {
                 serializationObject.uvs = this.uvs;
             }
@@ -416,6 +449,10 @@
                 result.normals = meshOrGeometry.getVerticesData(VertexBuffer.NormalKind, copyWhenShared);
             }
 
+            if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                result.tangents = meshOrGeometry.getVerticesData(VertexBuffer.TangentKind, copyWhenShared);
+            }
+
             if (meshOrGeometry.isVerticesDataPresent(VertexBuffer.UVKind)) {
                 result.uvs = meshOrGeometry.getVerticesData(VertexBuffer.UVKind, copyWhenShared);
             }
@@ -2061,7 +2098,7 @@
          * bbSize : optional bounding box size data, required for facetPartitioning computation
          * bInfo : optional bounding info, required for facetPartitioning computation
          */
-        public static ComputeNormals(positions: any, indices: any, normals: any, 
+        public static ComputeNormals(positions: any, indices: any, normals: any,
             options?: { facetNormals?: any, facetPositions?: any, facetPartitioning?: any, ratio?: number, bInfo?: any, bbSize?: Vector3, subDiv?: any}): void {
 
             // temporary scalar variables
@@ -2095,7 +2132,7 @@
             }
 
             // facetPartitioning reinit if needed
-            if (computeFacetPartitioning) {  
+            if (computeFacetPartitioning) {
                 var ox = 0;                 // X partitioning index for facet position
                 var oy = 0;                 // Y partinioning index for facet position
                 var oz = 0;                 // Z partinioning index for facet position
@@ -2121,7 +2158,7 @@
                 var subSq = options.subDiv.max * options.subDiv.max;
                 options.facetPartitioning.length = 0;
             }
-        
+
             // reset the normals
             for (index = 0; index < positions.length; index++) {
                 normals[index] = 0.0;
@@ -2140,7 +2177,7 @@
                 v2z = v2x + 2;
                 v3x = indices[index * 3 + 2] * 3;
                 v3y = v3x + 1;
-                v3z = v3x + 2;        
+                v3z = v3x + 2;
 
                 p1p2x = positions[v1x] - positions[v2x];          // compute two vectors per facet : p1p2 and p3p2
                 p1p2y = positions[v1y] - positions[v2y];
@@ -2151,7 +2188,7 @@
                 p3p2z = positions[v3z] - positions[v2z];
 
                 // compute the face normal with the cross product
-                faceNormalx = p1p2y * p3p2z - p1p2z * p3p2y;            
+                faceNormalx = p1p2y * p3p2z - p1p2z * p3p2y;
                 faceNormaly = p1p2z * p3p2x - p1p2x * p3p2z;
                 faceNormalz = p1p2x * p3p2y - p1p2y * p3p2x;
                 // normalize this normal and store it in the array facetData
@@ -2162,7 +2199,7 @@
                 faceNormalz /= length;
 
                 if (computeFacetNormals) {
-                    options.facetNormals[index].x = faceNormalx;                                  
+                    options.facetNormals[index].x = faceNormalx;
                     options.facetNormals[index].y = faceNormaly;
                     options.facetNormals[index].z = faceNormalz;
                 }
@@ -2189,7 +2226,7 @@
                     b3x = Math.floor((positions[v3x] - options.bInfo.minimum.x * options.ratio) * xSubRatio);
                     b3y = Math.floor((positions[v3y] - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     b3z = Math.floor((positions[v3z] - options.bInfo.minimum.z * options.ratio) * zSubRatio);
-                    
+
                     block_idx_v1 = b1x + options.subDiv.max * b1y + subSq * b1z;
                     block_idx_v2 = b2x + options.subDiv.max * b2y + subSq * b2z;
                     block_idx_v3 = b3x + options.subDiv.max * b3y + subSq * b3z;
@@ -2209,7 +2246,7 @@
                         options.facetPartitioning[block_idx_v3].push(index);
                     }
                     if (!(block_idx_o == block_idx_v1 || block_idx_o == block_idx_v2 || block_idx_o == block_idx_v3)) {
-                        options.facetPartitioning[block_idx_o].push(index); 
+                        options.facetPartitioning[block_idx_o].push(index);
                     }
                 }
 
@@ -2314,6 +2351,12 @@
                 vertexData.set(normals, VertexBuffer.NormalKind);
             }
 
+            // tangents
+            var tangents = parsedVertexData.tangents;
+            if (tangents) {
+                vertexData.set(tangents, VertexBuffer.TangentKind);
+            }
+
             // uvs
             var uvs = parsedVertexData.uvs;
             if (uvs) {

+ 6 - 0
src/Mesh/babylon.vertexBuffer.ts

@@ -25,6 +25,7 @@
                     case VertexBuffer.UV6Kind:
                         stride = 2;
                         break;
+                    case VertexBuffer.TangentKind:
                     case VertexBuffer.ColorKind:
                         stride = 4;
                         break;
@@ -154,6 +155,7 @@
         // Enums
         private static _PositionKind = "position";
         private static _NormalKind = "normal";
+        private static _TangentKind = "tangent";
         private static _UVKind = "uv";
         private static _UV2Kind = "uv2";
         private static _UV3Kind = "uv3";
@@ -174,6 +176,10 @@
             return VertexBuffer._NormalKind;
         }
 
+        public static get TangentKind(): string {
+            return VertexBuffer._TangentKind;
+        }
+
         public static get UVKind(): string {
             return VertexBuffer._UVKind;
         }

+ 5 - 1
src/Shaders/ShadersInclude/bumpFragment.fx

@@ -1,7 +1,11 @@
 vec2 uvOffset = vec2(0.0, 0.0);
 
 #if defined(BUMP) || defined(PARALLAX)
-	mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, -viewDirectionW, vBumpUV);
+	#if defined(TANGENT) && defined(NORMAL)
+		mat3 TBN = vTBN;
+	#else
+		mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, -viewDirectionW, vBumpUV);
+	#endif
 #endif
 
 #ifdef PARALLAX

+ 3 - 0
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -2,6 +2,9 @@
 	varying vec2 vBumpUV;
 	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
+#if defined(TANGENT) && defined(NORMAL) 
+	varying mat3 vTBN;
+#endif
 
 	// Thanks to http://www.thetenthplanet.de/archives/1180
 	mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)

+ 6 - 0
src/Shaders/ShadersInclude/bumpVertex.fx

@@ -0,0 +1,6 @@
+#if defined(BUMP) || defined(PARALLAX)
+	#if defined(TANGENT) && defined(NORMAL) 
+		vec3 bitangent = cross(normal, tangent.xyz) * sign(tangent.w); //aka binormal
+		vTBN = mat3(tangent.xyz, bitangent, normal);
+	#endif
+#endif

+ 5 - 0
src/Shaders/ShadersInclude/bumpVertexDeclaration.fx

@@ -0,0 +1,5 @@
+#if defined(BUMP) || defined(PARALLAX)
+	#if defined(TANGENT) && defined(NORMAL) 
+		varying mat3 vTBN;
+	#endif
+#endif

+ 6 - 0
src/Shaders/default.vertex.fx

@@ -3,6 +3,9 @@ attribute vec3 position;
 #ifdef NORMAL
 attribute vec3 normal;
 #endif
+#ifdef TANGENT
+attribute vec4 tangent;
+#endif
 #ifdef UV1
 attribute vec2 uv;
 #endif
@@ -75,6 +78,8 @@ varying vec3 vNormalW;
 varying vec4 vColor;
 #endif
 
+#include<bumpVertexDeclaration>
+
 #include<clipPlaneVertexDeclaration>
 
 #include<fogVertexDeclaration>
@@ -196,6 +201,7 @@ void main(void) {
 	}
 #endif
 
+#include<bumpVertex>
 #include<clipPlaneVertex>
 #include<fogVertex>
 #include<shadowsVertex>[0..maxSimultaneousLights]

+ 7 - 0
src/Shaders/pbr.vertex.fx

@@ -5,6 +5,9 @@ attribute vec3 position;
 #ifdef NORMAL
 attribute vec3 normal;
 #endif
+#ifdef TANGENT
+attribute vec4 tangent;
+#endif
 #ifdef UV1
 attribute vec2 uv;
 #endif
@@ -80,6 +83,7 @@ varying vec4 vColor;
 #endif
 
 
+#include<bumpVertexDeclaration>
 #include<clipPlaneVertexDeclaration>
 #include<fogVertexDeclaration>
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
@@ -200,6 +204,9 @@ void main(void) {
     }
 #endif
 
+    // TBN
+#include<bumpVertex>
+
     // Clip plane
 #include<clipPlaneVertex>