2
0
Эх сурвалжийг харах

Implement 'tangent' attribute.

Don McCurdy 7 жил өмнө
parent
commit
407b42d2df

+ 5 - 9
examples/js/loaders/GLTFLoader.js

@@ -1202,6 +1202,7 @@ THREE.GLTFLoader = ( function () {
 	var ATTRIBUTES = {
 	var ATTRIBUTES = {
 		POSITION: 'position',
 		POSITION: 'position',
 		NORMAL: 'normal',
 		NORMAL: 'normal',
+		TANGENT: 'tangent',
 		TEXCOORD_0: 'uv',
 		TEXCOORD_0: 'uv',
 		TEXCOORD_1: 'uv2',
 		TEXCOORD_1: 'uv2',
 		COLOR_0: 'color',
 		COLOR_0: 'color',
@@ -2397,14 +2398,6 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( materialDef.name !== undefined ) material.name = materialDef.name;
 			if ( materialDef.name !== undefined ) material.name = materialDef.name;
 
 
-			// Normal map textures use OpenGL conventions:
-			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
-			if ( material.normalScale ) {
-
-				material.normalScale.y = - material.normalScale.y;
-
-			}
-
 			// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
 			// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
 			if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
 			if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
@@ -2762,6 +2755,7 @@ THREE.GLTFLoader = ( function () {
 
 
 					var materials = isMultiMaterial ? mesh.material : [ mesh.material ];
 					var materials = isMultiMaterial ? mesh.material : [ mesh.material ];
 
 
+					var useVertexTangents = geometry.attributes.tangent !== undefined;
 					var useVertexColors = geometry.attributes.color !== undefined;
 					var useVertexColors = geometry.attributes.color !== undefined;
 					var useFlatShading = geometry.attributes.normal === undefined;
 					var useFlatShading = geometry.attributes.normal === undefined;
 					var useSkinning = mesh.isSkinnedMesh === true;
 					var useSkinning = mesh.isSkinnedMesh === true;
@@ -2814,12 +2808,13 @@ THREE.GLTFLoader = ( function () {
 						}
 						}
 
 
 						// Clone the material if it will be modified
 						// Clone the material if it will be modified
-						if ( useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
+						if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
 
 
 							var cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 							var cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 
 
 							if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 							if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 							if ( useSkinning ) cacheKey += 'skinning:';
 							if ( useSkinning ) cacheKey += 'skinning:';
+							if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
 							if ( useVertexColors ) cacheKey += 'vertex-colors:';
 							if ( useVertexColors ) cacheKey += 'vertex-colors:';
 							if ( useFlatShading ) cacheKey += 'flat-shading:';
 							if ( useFlatShading ) cacheKey += 'flat-shading:';
 							if ( useMorphTargets ) cacheKey += 'morph-targets:';
 							if ( useMorphTargets ) cacheKey += 'morph-targets:';
@@ -2834,6 +2829,7 @@ THREE.GLTFLoader = ( function () {
 									: material.clone();
 									: material.clone();
 
 
 								if ( useSkinning ) cachedMaterial.skinning = true;
 								if ( useSkinning ) cachedMaterial.skinning = true;
+								if ( useVertexTangents ) cachedMaterial.vertexTangents = THREE.VertexTangents;
 								if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
 								if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
 								if ( useFlatShading ) cachedMaterial.flatShading = true;
 								if ( useFlatShading ) cachedMaterial.flatShading = true;
 								if ( useMorphTargets ) cachedMaterial.morphTargets = true;
 								if ( useMorphTargets ) cachedMaterial.morphTargets = true;

+ 2 - 0
src/constants.js

@@ -14,6 +14,8 @@ export var BackSide = 1;
 export var DoubleSide = 2;
 export var DoubleSide = 2;
 export var FlatShading = 1;
 export var FlatShading = 1;
 export var SmoothShading = 2;
 export var SmoothShading = 2;
+export var AutoTangents = 0;
+export var VertexTangents = 1;
 export var NoColors = 0;
 export var NoColors = 0;
 export var FaceColors = 1;
 export var FaceColors = 1;
 export var VertexColors = 2;
 export var VertexColors = 2;

+ 12 - 0
src/core/BufferGeometry.js

@@ -154,6 +154,18 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 
 		}
 		}
 
 
+		var tangent = this.attributes.tangent;
+
+		if ( tangent !== undefined ) {
+
+			var normalMatrix = new Matrix3().getNormalMatrix( matrix );
+
+			// Tangent is vec4, but the '.w' component is a sign value (+1/-1).
+			normalMatrix.applyToBufferAttribute( tangent );
+			tangent.needsUpdate = true;
+
+		}
+
 		if ( this.boundingBox !== null ) {
 		if ( this.boundingBox !== null ) {
 
 
 			this.computeBoundingBox();
 			this.computeBoundingBox();

+ 2 - 1
src/materials/Material.js

@@ -1,5 +1,5 @@
 import { EventDispatcher } from '../core/EventDispatcher.js';
 import { EventDispatcher } from '../core/EventDispatcher.js';
-import { NoColors, FrontSide, FlatShading, NormalBlending, LessEqualDepth, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor } from '../constants.js';
+import { NoColors, FrontSide, FlatShading, NormalBlending, LessEqualDepth, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, AutoTangents } from '../constants.js';
 import { _Math } from '../math/Math.js';
 import { _Math } from '../math/Math.js';
 
 
 /**
 /**
@@ -24,6 +24,7 @@ function Material() {
 	this.blending = NormalBlending;
 	this.blending = NormalBlending;
 	this.side = FrontSide;
 	this.side = FrontSide;
 	this.flatShading = false;
 	this.flatShading = false;
+	this.vertexTangents = AutoTangents; // THREE.AutoTangents, THREE.VertexTangents
 	this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
 	this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors
 
 
 	this.opacity = 1;
 	this.opacity = 1;

+ 6 - 0
src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js

@@ -1,3 +1,9 @@
 export default /* glsl */`
 export default /* glsl */`
 vec3 objectNormal = vec3( normal );
 vec3 objectNormal = vec3( normal );
+
+#ifdef USE_TANGENT
+
+	vec3 objectTangent = vec3( tangent.xyz );
+
+#endif
 `;
 `;

+ 12 - 0
src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js

@@ -5,5 +5,17 @@ vec3 transformedNormal = normalMatrix * objectNormal;
 
 
 	transformedNormal = - transformedNormal;
 	transformedNormal = - transformedNormal;
 
 
+#endif
+
+#ifdef USE_TANGENT
+
+	vec3 transformedTangent = normalMatrix * objectTangent;
+
+	#ifdef FLIP_SIDED
+
+		transformedTangent = - transformedTangent;
+
+	#endif
+
 #endif
 #endif
 `;
 `;

+ 14 - 0
src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js

@@ -17,5 +17,19 @@ export default /* glsl */`
 
 
 	#endif
 	#endif
 
 
+	#ifdef USE_TANGENT
+
+		vec3 tangent = normalize( vTangent );
+		vec3 bitangent = normalize( vBitangent );
+
+		#ifdef DOUBLE_SIDED
+
+			tangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+			bitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+
+		#endif
+
+	#endif
+
 #endif
 #endif
 `;
 `;

+ 12 - 1
src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js

@@ -21,7 +21,18 @@ export default /* glsl */`
 
 
 	#else // tangent-space normal map
 	#else // tangent-space normal map
 
 
-		normal = perturbNormal2Arb( -vViewPosition, normal );
+		#ifdef USE_TANGENT
+
+			mat3 vTBN = mat3( tangent, bitangent, normal );
+			vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;
+			mapN.xy = normalScale * mapN.xy;
+			normal = normalize( vTBN * mapN );
+
+		#else
+
+			normal = perturbNormal2Arb( -vViewPosition, normal );
+
+		#endif
 
 
 	#endif
 	#endif
 
 

+ 6 - 0
src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl.js

@@ -10,5 +10,11 @@ export default /* glsl */`
 
 
 	objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
 	objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
 
 
+	#ifdef USE_TANGENT
+
+		objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;
+
+	#endif
+
 #endif
 #endif
 `;
 `;

+ 7 - 0
src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js

@@ -18,6 +18,13 @@ varying vec3 vViewPosition;
 
 
 	varying vec3 vNormal;
 	varying vec3 vNormal;
 
 
+	#ifdef USE_TANGENT
+
+		varying vec3 vTangent;
+		varying vec3 vBitangent;
+
+	#endif
+
 #endif
 #endif
 
 
 #include <common>
 #include <common>

+ 14 - 0
src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js

@@ -7,6 +7,13 @@ varying vec3 vViewPosition;
 
 
 	varying vec3 vNormal;
 	varying vec3 vNormal;
 
 
+	#ifdef USE_TANGENT
+
+		varying vec3 vTangent;
+		varying vec3 vBitangent;
+
+	#endif
+
 #endif
 #endif
 
 
 #include <common>
 #include <common>
@@ -37,6 +44,13 @@ void main() {
 
 
 	vNormal = normalize( transformedNormal );
 	vNormal = normalize( transformedNormal );
 
 
+	#ifdef USE_TANGENT
+
+		vTangent = normalize( transformedTangent );
+		vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );
+
+	#endif
+
 #endif
 #endif
 
 
 	#include <begin_vertex>
 	#include <begin_vertex>

+ 7 - 0
src/renderers/shaders/ShaderLib/normal_frag.glsl.js

@@ -13,6 +13,13 @@ uniform float opacity;
 
 
 	varying vec3 vNormal;
 	varying vec3 vNormal;
 
 
+	#ifdef USE_TANGENT
+
+		varying vec3 vTangent;
+		varying vec3 vBitangent;
+
+	#endif
+
 #endif
 #endif
 
 
 #include <packing>
 #include <packing>

+ 14 - 0
src/renderers/shaders/ShaderLib/normal_vert.glsl.js

@@ -11,6 +11,13 @@ export default /* glsl */`
 
 
 	varying vec3 vNormal;
 	varying vec3 vNormal;
 
 
+	#ifdef USE_TANGENT
+
+		varying vec3 vTangent;
+		varying vec3 vBitangent;
+
+	#endif
+
 #endif
 #endif
 
 
 #include <uv_pars_vertex>
 #include <uv_pars_vertex>
@@ -33,6 +40,13 @@ void main() {
 
 
 	vNormal = normalize( transformedNormal );
 	vNormal = normalize( transformedNormal );
 
 
+	#ifdef USE_TANGENT
+
+		vTangent = normalize( transformedTangent );
+		vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );
+
+	#endif
+
 #endif
 #endif
 
 
 	#include <begin_vertex>
 	#include <begin_vertex>

+ 10 - 0
src/renderers/webgl/WebGLProgram.js

@@ -359,6 +359,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
 			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
 			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
 			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
+
+			parameters.vertexTangents ? '#define USE_TANGENT' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',
 
 
 			parameters.flatShading ? '#define FLAT_SHADED' : '',
 			parameters.flatShading ? '#define FLAT_SHADED' : '',
@@ -390,6 +392,12 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 			'attribute vec3 normal;',
 			'attribute vec3 normal;',
 			'attribute vec2 uv;',
 			'attribute vec2 uv;',
 
 
+			'#ifdef USE_TANGENT',
+
+			'	attribute vec4 tangent;',
+
+			'#endif',
+
 			'#ifdef USE_COLOR',
 			'#ifdef USE_COLOR',
 
 
 			'	attribute vec3 color;',
 			'	attribute vec3 color;',
@@ -466,6 +474,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
 			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
 			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
 			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
+
+			parameters.vertexTangents ? '#define USE_TANGENT' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',
 
 
 			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
 			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',

+ 2 - 1
src/renderers/webgl/WebGLPrograms.js

@@ -31,7 +31,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 		"precision", "supportsVertexTextures", "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding",
 		"precision", "supportsVertexTextures", "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding",
 		"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
 		"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
 		"roughnessMap", "metalnessMap", "gradientMap",
 		"roughnessMap", "metalnessMap", "gradientMap",
-		"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
+		"alphaMap", "combine", "vertexColors", "vertexTangents", "fog", "useFog", "fogExp",
 		"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
 		"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
 		"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
 		"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
 		"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
 		"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
@@ -163,6 +163,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 
 
 			combine: material.combine,
 			combine: material.combine,
 
 
+			vertexTangents: material.vertexTangents,
 			vertexColors: material.vertexColors,
 			vertexColors: material.vertexColors,
 
 
 			fog: !! fog,
 			fog: !! fog,