Skip to content

Commit

Permalink
Merge pull request #15749 from donmccurdy/feat-attribute-tangents-v2
Browse files Browse the repository at this point in the history
Support stored vertex 'tangent' attribute
  • Loading branch information
mrdoob authored Feb 15, 2019
2 parents fe2a37c + 089ab74 commit f89180d
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 11 deletions.
7 changes: 7 additions & 0 deletions docs/api/en/materials/Material.html
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,13 @@ <h3>[property:Integer vertexColors]</h3>
Other options are [page:Materials THREE.VertexColors] and [page:Materials THREE.FaceColors].
</p>

<h3>[property:Boolean vertexTangents]</h3>
<p>
Defines whether precomputed vertex tangents, which must be provided in a vec4 "tangent" attribute,
are used. When disabled, tangents are derived automatically. Using precomputed tangents will give
more accurate normal map details in some cases, such as with mirrored UVs. Default is false.
</p>

<h3>[property:Boolean visible]</h3>
<p>
Defines whether this material is visible. Default is *true*.
Expand Down
4 changes: 4 additions & 0 deletions docs/api/zh/materials/Material.html
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ <h3>[property:Integer vertexColors]</h3>
其他选项有[page:Materials THREE.VertexColors] 和 [page:Materials THREE.FaceColors]。
</p>

<h3>[property:Boolean vertexTangents]</h3>
<p> TODO.
</p>

<h3>[property:Boolean visible]</h3>
<p> 此材质是否可见。默认为*true*。
</p>
Expand Down
14 changes: 5 additions & 9 deletions examples/js/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ THREE.GLTFLoader = ( function () {
var ATTRIBUTES = {
POSITION: 'position',
NORMAL: 'normal',
TANGENT: 'tangent',
TEXCOORD_0: 'uv',
TEXCOORD_1: 'uv2',
COLOR_0: 'color',
Expand Down Expand Up @@ -2409,14 +2410,6 @@ THREE.GLTFLoader = ( function () {

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.
if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
Expand Down Expand Up @@ -2774,6 +2767,7 @@ THREE.GLTFLoader = ( function () {

var materials = isMultiMaterial ? mesh.material : [ mesh.material ];

var useVertexTangents = geometry.attributes.tangent !== undefined;
var useVertexColors = geometry.attributes.color !== undefined;
var useFlatShading = geometry.attributes.normal === undefined;
var useSkinning = mesh.isSkinnedMesh === true;
Expand Down Expand Up @@ -2826,12 +2820,13 @@ THREE.GLTFLoader = ( function () {
}

// Clone the material if it will be modified
if ( useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {

var cacheKey = 'ClonedMaterial:' + material.uuid + ':';

if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
if ( useSkinning ) cacheKey += 'skinning:';
if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
if ( useVertexColors ) cacheKey += 'vertex-colors:';
if ( useFlatShading ) cacheKey += 'flat-shading:';
if ( useMorphTargets ) cacheKey += 'morph-targets:';
Expand All @@ -2846,6 +2841,7 @@ THREE.GLTFLoader = ( function () {
: material.clone();

if ( useSkinning ) cachedMaterial.skinning = true;
if ( useVertexTangents ) cachedMaterial.vertexTangents = true;
if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
if ( useFlatShading ) cachedMaterial.flatShading = true;
if ( useMorphTargets ) cachedMaterial.morphTargets = true;
Expand Down
12 changes: 12 additions & 0 deletions src/core/BufferGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {

this.computeBoundingBox();
Expand Down
6 changes: 6 additions & 0 deletions src/materials/Material.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface MaterialParameters {
side?: Side;
transparent?: boolean;
vertexColors?: Colors;
vertexTangents?: boolean;
visible?: boolean;
}

Expand Down Expand Up @@ -234,6 +235,11 @@ export class Material extends EventDispatcher {
*/
vertexColors: Colors;

/**
* Defines whether precomputed vertex tangents are used. Default is false.
*/
vertexTangents: boolean;

/**
* Defines whether this material is visible. Default is true.
*/
Expand Down
1 change: 1 addition & 0 deletions src/materials/Material.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function Material() {
this.blending = NormalBlending;
this.side = FrontSide;
this.flatShading = false;
this.vertexTangents = false;
this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors

this.opacity = 1;
Expand Down
6 changes: 6 additions & 0 deletions src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export default /* glsl */`
vec3 objectNormal = vec3( normal );
#ifdef USE_TANGENT
vec3 objectTangent = vec3( tangent.xyz );
#endif
`;
12 changes: 12 additions & 0 deletions src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,17 @@ vec3 transformedNormal = normalMatrix * objectNormal;
transformedNormal = - transformedNormal;
#endif
#ifdef USE_TANGENT
vec3 transformedTangent = normalMatrix * objectTangent;
#ifdef FLIP_SIDED
transformedTangent = - transformedTangent;
#endif
#endif
`;
14 changes: 14 additions & 0 deletions src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,19 @@ export default /* glsl */`
#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
`;
13 changes: 12 additions & 1 deletion src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@ export default /* glsl */`
#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
Expand Down
6 changes: 6 additions & 0 deletions src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ export default /* glsl */`
objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;
#ifdef USE_TANGENT
objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;
#endif
#endif
`;
7 changes: 7 additions & 0 deletions src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ varying vec3 vViewPosition;
varying vec3 vNormal;
#ifdef USE_TANGENT
varying vec3 vTangent;
varying vec3 vBitangent;
#endif
#endif
#include <common>
Expand Down
14 changes: 14 additions & 0 deletions src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ varying vec3 vViewPosition;
varying vec3 vNormal;
#ifdef USE_TANGENT
varying vec3 vTangent;
varying vec3 vBitangent;
#endif
#endif
#include <common>
Expand Down Expand Up @@ -37,6 +44,13 @@ void main() {
vNormal = normalize( transformedNormal );
#ifdef USE_TANGENT
vTangent = normalize( transformedTangent );
vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );
#endif
#endif
#include <begin_vertex>
Expand Down
7 changes: 7 additions & 0 deletions src/renderers/shaders/ShaderLib/normal_frag.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ uniform float opacity;
varying vec3 vNormal;
#ifdef USE_TANGENT
varying vec3 vTangent;
varying vec3 vBitangent;
#endif
#endif
#include <packing>
Expand Down
14 changes: 14 additions & 0 deletions src/renderers/shaders/ShaderLib/normal_vert.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export default /* glsl */`
varying vec3 vNormal;
#ifdef USE_TANGENT
varying vec3 vTangent;
varying vec3 vBitangent;
#endif
#endif
#include <uv_pars_vertex>
Expand All @@ -33,6 +40,13 @@ void main() {
vNormal = normalize( transformedNormal );
#ifdef USE_TANGENT
vTangent = normalize( transformedTangent );
vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );
#endif
#endif
#include <begin_vertex>
Expand Down
10 changes: 10 additions & 0 deletions src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',

parameters.vertexTangents ? '#define USE_TANGENT' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',

parameters.flatShading ? '#define FLAT_SHADED' : '',
Expand Down Expand Up @@ -390,6 +392,12 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
'attribute vec3 normal;',
'attribute vec2 uv;',

'#ifdef USE_TANGENT',

' attribute vec4 tangent;',

'#endif',

'#ifdef USE_COLOR',

' attribute vec3 color;',
Expand Down Expand Up @@ -466,6 +474,8 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
parameters.alphaMap ? '#define USE_ALPHAMAP' : '',

parameters.vertexTangents ? '#define USE_TANGENT' : '',
parameters.vertexColors ? '#define USE_COLOR' : '',

parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
Expand Down
3 changes: 2 additions & 1 deletion src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
"precision", "supportsVertexTextures", "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding",
"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
"roughnessMap", "metalnessMap", "gradientMap",
"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
"alphaMap", "combine", "vertexColors", "vertexTangents", "fog", "useFog", "fogExp",
"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
Expand Down Expand Up @@ -163,6 +163,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {

combine: material.combine,

vertexTangents: material.vertexTangents,
vertexColors: material.vertexColors,

fog: !! fog,
Expand Down

0 comments on commit f89180d

Please sign in to comment.