Skip to content

Commit

Permalink
Merge pull request #14239 from WestLangley/dev-object_space_normal_map
Browse files Browse the repository at this point in the history
Support object-space normal maps
  • Loading branch information
mrdoob committed Jun 17, 2018
2 parents 0be64f5 + e5f809a commit 6e89128
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 27 deletions.
7 changes: 7 additions & 0 deletions docs/api/materials/MeshPhongMaterial.html
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ <h3>[property:Texture normalMap]</h3>
the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
</p>

<h3>[property:Integer normalMapType]</h3>
<p>
The type of normal map.<br /><br />

Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
</p>

<h3>[property:Vector2 normalScale]</h3>
<p>
How much the normal map affects the material. Typical ranges are 0-1.
Expand Down
7 changes: 7 additions & 0 deletions docs/api/materials/MeshStandardMaterial.html
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ <h3>[property:Texture normalMap]</h3>
the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
</p>

<h3>[property:Integer normalMapType]</h3>
<p>
The type of normal map.<br /><br />

Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
</p>

<h3>[property:Vector2 normalScale]</h3>
<p>
How much the normal map affects the material. Typical ranges are 0-1.
Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,5 @@ export var RGBM16Encoding = 3005;
export var RGBDEncoding = 3006;
export var BasicDepthPacking = 3200;
export var RGBADepthPacking = 3201;
export var TangentSpaceNormalMap = 0;
export var ObjectSpaceNormalMap = 1;
3 changes: 2 additions & 1 deletion src/materials/Material.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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, TangentSpaceNormalMap } from '../constants.js';
import { _Math } from '../math/Math.js';

/**
Expand Down Expand Up @@ -194,6 +194,7 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
if ( this.normalMap && this.normalMap.isTexture ) {

data.normalMap = this.normalMap.toJSON( meta ).uuid;
if ( this.normalMapType !== TangentSpaceNormalMap ) data.normalMapType = this.normalMapType;
data.normalScale = this.normalScale.toArray();

}
Expand Down
4 changes: 4 additions & 0 deletions src/materials/MeshNormalMaterial.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TangentSpaceNormalMap } from '../constants.js';
import { Material } from './Material.js';
import { Vector2 } from '../math/Vector2.js';

Expand All @@ -12,6 +13,7 @@ import { Vector2 } from '../math/Vector2.js';
* bumpScale: <float>,
*
* normalMap: new THREE.Texture( <Image> ),
* normalMapType: THREE.TangentSpaceNormalMap,
* normalScale: <Vector2>,
*
* displacementMap: new THREE.Texture( <Image> ),
Expand All @@ -37,6 +39,7 @@ function MeshNormalMaterial( parameters ) {
this.bumpScale = 1;

this.normalMap = null;
this.normalMapType = TangentSpaceNormalMap;
this.normalScale = new Vector2( 1, 1 );

this.displacementMap = null;
Expand Down Expand Up @@ -70,6 +73,7 @@ MeshNormalMaterial.prototype.copy = function ( source ) {
this.bumpScale = source.bumpScale;

this.normalMap = source.normalMap;
this.normalMapType = source.normalMapType;
this.normalScale.copy( source.normalScale );

this.displacementMap = source.displacementMap;
Expand Down
5 changes: 4 additions & 1 deletion src/materials/MeshPhongMaterial.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MultiplyOperation, TangentSpaceNormalMap } from '../constants.js';
import { Material } from './Material.js';
import { MultiplyOperation } from '../constants.js';
import { Vector2 } from '../math/Vector2.js';
import { Color } from '../math/Color.js';

Expand Down Expand Up @@ -29,6 +29,7 @@ import { Color } from '../math/Color.js';
* bumpScale: <float>,
*
* normalMap: new THREE.Texture( <Image> ),
* normalMapType: THREE.TangentSpaceNormalMap,
* normalScale: <Vector2>,
*
* displacementMap: new THREE.Texture( <Image> ),
Expand Down Expand Up @@ -79,6 +80,7 @@ function MeshPhongMaterial( parameters ) {
this.bumpScale = 1;

this.normalMap = null;
this.normalMapType = TangentSpaceNormalMap;
this.normalScale = new Vector2( 1, 1 );

this.displacementMap = null;
Expand Down Expand Up @@ -136,6 +138,7 @@ MeshPhongMaterial.prototype.copy = function ( source ) {
this.bumpScale = source.bumpScale;

this.normalMap = source.normalMap;
this.normalMapType = source.normalMapType;
this.normalScale.copy( source.normalScale );

this.displacementMap = source.displacementMap;
Expand Down
4 changes: 4 additions & 0 deletions src/materials/MeshStandardMaterial.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TangentSpaceNormalMap } from '../constants.js';
import { Material } from './Material.js';
import { Vector2 } from '../math/Vector2.js';
import { Color } from '../math/Color.js';
Expand Down Expand Up @@ -27,6 +28,7 @@ import { Color } from '../math/Color.js';
* bumpScale: <float>,
*
* normalMap: new THREE.Texture( <Image> ),
* normalMapType: THREE.TangentSpaceNormalMap,
* normalScale: <Vector2>,
*
* displacementMap: new THREE.Texture( <Image> ),
Expand Down Expand Up @@ -81,6 +83,7 @@ function MeshStandardMaterial( parameters ) {
this.bumpScale = 1;

this.normalMap = null;
this.normalMapType = TangentSpaceNormalMap;
this.normalScale = new Vector2( 1, 1 );

this.displacementMap = null;
Expand Down Expand Up @@ -142,6 +145,7 @@ MeshStandardMaterial.prototype.copy = function ( source ) {
this.bumpScale = source.bumpScale;

this.normalMap = source.normalMap;
this.normalMapType = source.normalMapType;
this.normalScale.copy( source.normalScale );

this.displacementMap = source.displacementMap;
Expand Down
24 changes: 23 additions & 1 deletion src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
#ifdef USE_NORMALMAP

normal = perturbNormal2Arb( -vViewPosition, normal );
#ifdef OBJECTSPACE_NORMALMAP

normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals

#ifdef FLIP_SIDED

normal = - normal;

#endif

#ifdef DOUBLE_SIDED

normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );

#endif

normal = normalize( normalMatrix * normal );

#else // tangent-space normal map

normal = perturbNormal2Arb( -vViewPosition, normal );

#endif

#elif defined( USE_BUMPMAP )

Expand Down
44 changes: 26 additions & 18 deletions src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,40 @@
uniform sampler2D normalMap;
uniform vec2 normalScale;

// Per-Pixel Tangent Space Normal Mapping
// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
#ifdef OBJECTSPACE_NORMALMAP

vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {
uniform mat3 normalMatrix;

// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
#else

vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );
vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );
vec2 st0 = dFdx( vUv.st );
vec2 st1 = dFdy( vUv.st );
// Per-Pixel Tangent Space Normal Mapping
// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html

float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude
vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {

vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );
vec3 N = normalize( surf_norm );
mat3 tsn = mat3( S, T, N );
// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988

vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;
vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );
vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );
vec2 st0 = dFdx( vUv.st );
vec2 st1 = dFdy( vUv.st );

mapN.xy *= normalScale;
mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude

return normalize( tsn * mapN );
vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );
vec3 N = normalize( surf_norm );
mat3 tsn = mat3( S, T, N );

}
vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;

mapN.xy *= normalScale;
mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );

return normalize( tsn * mapN );

}

#endif

#endif
2 changes: 1 addition & 1 deletion src/renderers/shaders/ShaderLib/normal_frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

uniform float opacity;

#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )
#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )

varying vec3 vViewPosition;

Expand Down
4 changes: 2 additions & 2 deletions src/renderers/shaders/ShaderLib/normal_vert.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#define NORMAL

#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )
#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )

varying vec3 vViewPosition;

Expand Down Expand Up @@ -41,7 +41,7 @@ void main() {
#include <project_vertex>
#include <logdepthbuf_vertex>

#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )
#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || ( defined( USE_NORMALMAP ) && ! defined( OBJECTSPACE_NORMALMAP ) )

vViewPosition = - mvPosition.xyz;

Expand Down
4 changes: 3 additions & 1 deletion src/renderers/webgl/WebGLProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function generateExtensions( extensions, parameters, rendererExtensions ) {
extensions = extensions || {};

var chunks = [
( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || ( parameters.normalMap && ! parameters.objectSpaceNormalMap ) || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
Expand Down Expand Up @@ -349,6 +349,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
Expand Down Expand Up @@ -455,6 +456,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
parameters.bumpMap ? '#define USE_BUMPMAP' : '',
parameters.normalMap ? '#define USE_NORMALMAP' : '',
( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
parameters.specularMap ? '#define USE_SPECULARMAP' : '',
parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
Expand Down
5 changes: 3 additions & 2 deletions src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @author mrdoob / http://mrdoob.com/
*/

import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding } from '../../constants.js';
import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding, ObjectSpaceNormalMap } from '../../constants.js';
import { WebGLProgram } from './WebGLProgram.js';

function WebGLPrograms( renderer, extensions, capabilities ) {
Expand All @@ -27,7 +27,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {

var parameterNames = [
"precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "displacementMap", "specularMap",
"roughnessMap", "metalnessMap", "gradientMap",
"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
Expand Down Expand Up @@ -148,6 +148,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
bumpMap: !! material.bumpMap,
normalMap: !! material.normalMap,
objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
displacementMap: !! material.displacementMap,
roughnessMap: !! material.roughnessMap,
metalnessMap: !! material.metalnessMap,
Expand Down

0 comments on commit 6e89128

Please sign in to comment.