Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support object-space normal maps #14239

Merged
merged 1 commit into from
Jun 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating multiple document entries by moving the property to Texture. If not, add the documentation for MeshNormalMaterial.

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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider consolidating multiple document entries by moving the property to Texture. If not, add the documentation for MeshNormalMaterial.

<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;
Copy link
Contributor

@pailhead pailhead Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider nuking, would be serialized with the texture, there are possibly materials that extend Material that do not use normal maps, like the 13 other materials that all extend Material but this property is not added to.

Consider not making the super class aware of the sub classes.

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;
Copy link
Contributor

@pailhead pailhead Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider nuking, and moving to Texture. Introduces coupling with Material and overloads this Material.

If not, consider adding documentation for this class.

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;
Copy link
Contributor

@pailhead pailhead Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider nuking, and moving to Texture. Introduces coupling with Material and overloads this Material.

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;
Copy link
Contributor

@pailhead pailhead Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider nuking, and moving to Texture. Introduces coupling with Material and overloads this Material.

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,
Copy link
Contributor

@pailhead pailhead Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider decoupling from Material, use it as a property of the normal map (Texture)

objectSpaceNormalMap: material.normalMap.objectSpace,

displacementMap: !! material.displacementMap,
roughnessMap: !! material.roughnessMap,
metalnessMap: !! material.metalnessMap,
Expand Down