瀏覽代碼

Merge pull request #17987 from Mugen87/dev39

OutlineEffect: Refactor shaders.
Mr.doob 5 年之前
父節點
當前提交
35202837df
共有 2 個文件被更改,包括 191 次插入212 次删除
  1. 94 105
      examples/js/effects/OutlineEffect.js
  2. 97 107
      examples/jsm/effects/OutlineEffect.js

+ 94 - 105
examples/js/effects/OutlineEffect.js

@@ -54,9 +54,6 @@
  * 	visible: true,
  * 	visible: true,
  * 	keepAlive: true
  * 	keepAlive: true
  * };
  * };
- *
- * TODO
- *  - support shader material without objectNormal in its vertexShader
  */
  */
 
 
 THREE.OutlineEffect = function ( renderer, parameters ) {
 THREE.OutlineEffect = function ( renderer, parameters ) {
@@ -90,58 +87,57 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 	//this.cache = cache;  // for debug
 	//this.cache = cache;  // for debug
 
 
-	// copied from WebGLPrograms and removed some materials
-	var shaderIDs = {
-		MeshBasicMaterial: 'basic',
-		MeshLambertMaterial: 'lambert',
-		MeshPhongMaterial: 'phong',
-		MeshToonMaterial: 'phong',
-		MeshStandardMaterial: 'physical',
-		MeshPhysicalMaterial: 'physical'
-	};
-
-	var uniformsChunk = {
+	var uniformsOutline = {
 		outlineThickness: { value: defaultThickness },
 		outlineThickness: { value: defaultThickness },
 		outlineColor: { value: defaultColor },
 		outlineColor: { value: defaultColor },
 		outlineAlpha: { value: defaultAlpha }
 		outlineAlpha: { value: defaultAlpha }
 	};
 	};
 
 
-	var vertexShaderChunk = [
+	var vertexShader = [
+		"#include <common>",
+		"#include <uv_pars_vertex>",
+		"#include <displacementmap_pars_vertex>",
+		"#include <fog_pars_vertex>",
+		"#include <morphtarget_pars_vertex>",
+		"#include <skinning_pars_vertex>",
+		"#include <logdepthbuf_pars_vertex>",
+		"#include <clipping_planes_pars_vertex>",
 
 
 		"uniform float outlineThickness;",
 		"uniform float outlineThickness;",
 
 
-		"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
-
+		"vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {",
 		"	float thickness = outlineThickness;",
 		"	float thickness = outlineThickness;",
 		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
 		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
-		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );",
+		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );",
 		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
 		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
 		"	vec4 norm = normalize( pos - pos2 );",
 		"	vec4 norm = normalize( pos - pos2 );",
 		"	return pos + norm * thickness * pos.w * ratio;",
 		"	return pos + norm * thickness * pos.w * ratio;",
+		"}",
 
 
-		"}"
+		"void main() {",
 
 
-	].join( "\n" );
+		"	#include <uv_vertex>",
 
 
-	var vertexShaderChunk2 = [
+		"	#include <beginnormal_vertex>",
+		"	#include <morphnormal_vertex>",
+		"	#include <skinbase_vertex>",
+		"	#include <skinnormal_vertex>",
 
 
-		"#if ! defined( LAMBERT ) && ! defined( PHONG ) && ! defined( TOON ) && ! defined( STANDARD )",
-		"	#ifndef USE_ENVMAP",
-		"		vec3 objectNormal = normalize( normal );",
-		"	#endif",
-		"#endif",
+		"	#include <begin_vertex>",
+		"	#include <morphtarget_vertex>",
+		"	#include <skinning_vertex>",
+		"	#include <displacementmap_vertex>",
+		"	#include <project_vertex>",
 
 
-		"#ifdef FLIP_SIDED",
-		"	objectNormal = -objectNormal;",
-		"#endif",
+		"	vec3 outlineNormal = - objectNormal;", // the outline material is always rendered with THREE.BackSide
 
 
-		"#ifdef DECLARE_TRANSFORMED",
-		"	vec3 transformed = vec3( position );",
-		"#endif",
+		"	gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );",
 
 
-		"gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );",
+		"	#include <logdepthbuf_vertex>",
+		"	#include <clipping_planes_vertex>",
+		"	#include <fog_vertex>",
 
 
-		"#include <fog_vertex>"
+		"}",
 
 
 	].join( "\n" );
 	].join( "\n" );
 
 
@@ -149,92 +145,39 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 		"#include <common>",
 		"#include <common>",
 		"#include <fog_pars_fragment>",
 		"#include <fog_pars_fragment>",
+		"#include <logdepthbuf_pars_fragment>",
+		"#include <clipping_planes_pars_fragment>",
 
 
 		"uniform vec3 outlineColor;",
 		"uniform vec3 outlineColor;",
 		"uniform float outlineAlpha;",
 		"uniform float outlineAlpha;",
 
 
 		"void main() {",
 		"void main() {",
 
 
+		"	#include <clipping_planes_fragment>",
+		"	#include <logdepthbuf_fragment>",
+
 		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
 		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
 
 
+		"	#include <premultiplied_alpha_fragment>",
+		"	#include <tonemapping_fragment>",
+		"	#include <encodings_fragment>",
 		"	#include <fog_fragment>",
 		"	#include <fog_fragment>",
 
 
 		"}"
 		"}"
 
 
 	].join( "\n" );
 	].join( "\n" );
 
 
-	function createInvisibleMaterial() {
-
-		return new THREE.ShaderMaterial( { name: 'invisible', visible: false } );
-
-	}
-
-	function createMaterial( originalMaterial ) {
-
-		var shaderID = shaderIDs[ originalMaterial.type ];
-		var originalUniforms, originalVertexShader;
-
-		if ( shaderID !== undefined ) {
-
-			var shader = THREE.ShaderLib[ shaderID ];
-			originalUniforms = shader.uniforms;
-			originalVertexShader = shader.vertexShader;
-
-		} else if ( originalMaterial.isRawShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-			if ( ! /attribute\s+vec3\s+position\s*;/.test( originalVertexShader ) ||
-			     ! /attribute\s+vec3\s+normal\s*;/.test( originalVertexShader ) ) {
-
-				console.warn( 'THREE.OutlineEffect requires both vec3 position and normal attributes in vertex shader, ' +
-				              'does not draw outline for ' + originalMaterial.name + '(uuid:' + originalMaterial.uuid + ') material.' );
-
-				return createInvisibleMaterial();
-
-			}
-
-		} else if ( originalMaterial.isShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-		} else {
-
-			return createInvisibleMaterial();
-
-		}
-
-		var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
-
-		var vertexShader = originalVertexShader
-			// put vertexShaderChunk right before "void main() {...}"
-			.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
-			// put vertexShaderChunk2 the end of "void main() {...}"
-			// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
-			.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
-			// remove any light related lines
-			// Note: here is very sensitive to originalVertexShader
-			// TODO: consider safer way
-			.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
-
-		var defines = {};
-
-		if ( ! /vec3\s+transformed\s*=/.test( originalVertexShader ) &&
-		     ! /#include\s+<begin_vertex>/.test( originalVertexShader ) ) defines.DECLARE_TRANSFORMED = true;
+	function createMaterial() {
 
 
 		return new THREE.ShaderMaterial( {
 		return new THREE.ShaderMaterial( {
-			defines: defines,
-			uniforms: uniforms,
+			uniforms: THREE.UniformsUtils.merge( [
+				THREE.UniformsLib[ 'fog' ],
+				THREE.UniformsLib[ 'displacementmap' ],
+				uniformsOutline
+			] ),
 			vertexShader: vertexShader,
 			vertexShader: vertexShader,
 			fragmentShader: fragmentShader,
 			fragmentShader: fragmentShader,
-			side: THREE.BackSide,
-			//wireframe: true,
-			skinning: false,
-			morphTargets: false,
-			morphNormals: false,
-			fog: false
+			side: THREE.BackSide
 		} );
 		} );
 
 
 	}
 	}
@@ -246,7 +189,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		if ( data === undefined ) {
 		if ( data === undefined ) {
 
 
 			data = {
 			data = {
-				material: createMaterial( originalMaterial ),
+				material: createMaterial(),
 				used: true,
 				used: true,
 				keepAlive: defaultKeepAlive,
 				keepAlive: defaultKeepAlive,
 				count: 0
 				count: 0
@@ -274,9 +217,32 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 	}
 	}
 
 
+	function isCompatible( object ) {
+
+		var geometry = object.geometry;
+		var hasNormals = false;
+
+		if ( object.geometry !== undefined ) {
+
+			if ( geometry.isBufferGeometry ) {
+
+				hasNormals = geometry.attributes.normal !== undefined;
+
+			} else {
+
+				hasNormals = true; // the renderer always produces a normal attribute for Geometry
+
+			}
+
+		}
+
+		return ( object.isMesh === true && object.material !== undefined && hasNormals === true );
+
+	}
+
 	function setOutlineMaterial( object ) {
 	function setOutlineMaterial( object ) {
 
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 
 		if ( Array.isArray( object.material ) ) {
 		if ( Array.isArray( object.material ) ) {
 
 
@@ -299,7 +265,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 	function restoreOriginalMaterial( object ) {
 	function restoreOriginalMaterial( object ) {
 
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 
 		if ( Array.isArray( object.material ) ) {
 		if ( Array.isArray( object.material ) ) {
 
 
@@ -344,6 +310,14 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 		}
 		}
 
 
+		if ( originalMaterial.displacementMap ) {
+
+			material.uniforms.displacementMap.value = originalMaterial.displacementMap;
+			material.uniforms.displacementScale.value = originalMaterial.displacementScale;
+			material.uniforms.displacementBias.value = originalMaterial.displacementBias;
+
+		}
+
 	}
 	}
 
 
 	function updateOutlineMaterial( material, originalMaterial ) {
 	function updateOutlineMaterial( material, originalMaterial ) {
@@ -356,6 +330,9 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphNormals = originalMaterial.morphNormals;
 		material.morphNormals = originalMaterial.morphNormals;
 		material.fog = originalMaterial.fog;
 		material.fog = originalMaterial.fog;
+		material.toneMapped = originalMaterial.toneMapped;
+		material.premultipliedAlpha = originalMaterial.premultipliedAlpha;
+		material.displacementMap = originalMaterial.displacementMap;
 
 
 		if ( outlineParameters !== undefined ) {
 		if ( outlineParameters !== undefined ) {
 
 
@@ -382,6 +359,18 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 
 		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
 		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
 
 
+		if ( originalMaterial.clippingPlanes ) {
+
+			material.clipping = true;
+
+			material.clippingPlanes = originalMaterial.clippingPlanes;
+			material.clipIntersection = originalMaterial.clipIntersection;
+			material.clipShadows = originalMaterial.clipShadows;
+
+		}
+
+		material.version = originalMaterial.version; // update outline material if necessary
+
 	}
 	}
 
 
 	function cleanupCache() {
 	function cleanupCache() {

+ 97 - 107
examples/jsm/effects/OutlineEffect.js

@@ -54,16 +54,14 @@
  * 	visible: true,
  * 	visible: true,
  * 	keepAlive: true
  * 	keepAlive: true
  * };
  * };
- *
- * TODO
- *  - support shader material without objectNormal in its vertexShader
  */
  */
 
 
 import {
 import {
 	BackSide,
 	BackSide,
 	Color,
 	Color,
-	ShaderLib,
-	ShaderMaterial
+	ShaderMaterial,
+	UniformsLib,
+	UniformsUtils
 } from "../../../build/three.module.js";
 } from "../../../build/three.module.js";
 
 
 var OutlineEffect = function ( renderer, parameters ) {
 var OutlineEffect = function ( renderer, parameters ) {
@@ -97,58 +95,57 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 	//this.cache = cache;  // for debug
 	//this.cache = cache;  // for debug
 
 
-	// copied from WebGLPrograms and removed some materials
-	var shaderIDs = {
-		MeshBasicMaterial: 'basic',
-		MeshLambertMaterial: 'lambert',
-		MeshPhongMaterial: 'phong',
-		MeshToonMaterial: 'phong',
-		MeshStandardMaterial: 'physical',
-		MeshPhysicalMaterial: 'physical'
-	};
-
-	var uniformsChunk = {
+	var uniformsOutline = {
 		outlineThickness: { value: defaultThickness },
 		outlineThickness: { value: defaultThickness },
 		outlineColor: { value: defaultColor },
 		outlineColor: { value: defaultColor },
 		outlineAlpha: { value: defaultAlpha }
 		outlineAlpha: { value: defaultAlpha }
 	};
 	};
 
 
-	var vertexShaderChunk = [
+	var vertexShader = [
+		"#include <common>",
+		"#include <uv_pars_vertex>",
+		"#include <displacementmap_pars_vertex>",
+		"#include <fog_pars_vertex>",
+		"#include <morphtarget_pars_vertex>",
+		"#include <skinning_pars_vertex>",
+		"#include <logdepthbuf_pars_vertex>",
+		"#include <clipping_planes_pars_vertex>",
 
 
 		"uniform float outlineThickness;",
 		"uniform float outlineThickness;",
 
 
-		"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
-
+		"vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {",
 		"	float thickness = outlineThickness;",
 		"	float thickness = outlineThickness;",
 		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
 		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
-		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );",
+		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );",
 		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
 		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
 		"	vec4 norm = normalize( pos - pos2 );",
 		"	vec4 norm = normalize( pos - pos2 );",
 		"	return pos + norm * thickness * pos.w * ratio;",
 		"	return pos + norm * thickness * pos.w * ratio;",
+		"}",
 
 
-		"}"
+		"void main() {",
 
 
-	].join( "\n" );
+		"	#include <uv_vertex>",
 
 
-	var vertexShaderChunk2 = [
+		"	#include <beginnormal_vertex>",
+		"	#include <morphnormal_vertex>",
+		"	#include <skinbase_vertex>",
+		"	#include <skinnormal_vertex>",
 
 
-		"#if ! defined( LAMBERT ) && ! defined( PHONG ) && ! defined( TOON ) && ! defined( STANDARD )",
-		"	#ifndef USE_ENVMAP",
-		"		vec3 objectNormal = normalize( normal );",
-		"	#endif",
-		"#endif",
+		"	#include <begin_vertex>",
+		"	#include <morphtarget_vertex>",
+		"	#include <skinning_vertex>",
+		"	#include <displacementmap_vertex>",
+		"	#include <project_vertex>",
 
 
-		"#ifdef FLIP_SIDED",
-		"	objectNormal = -objectNormal;",
-		"#endif",
+		"	vec3 outlineNormal = - objectNormal;", // the outline material is always rendered with BackSide
 
 
-		"#ifdef DECLARE_TRANSFORMED",
-		"	vec3 transformed = vec3( position );",
-		"#endif",
+		"	gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );",
 
 
-		"gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );",
+		"	#include <logdepthbuf_vertex>",
+		"	#include <clipping_planes_vertex>",
+		"	#include <fog_vertex>",
 
 
-		"#include <fog_vertex>"
+		"}",
 
 
 	].join( "\n" );
 	].join( "\n" );
 
 
@@ -156,92 +153,39 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 		"#include <common>",
 		"#include <common>",
 		"#include <fog_pars_fragment>",
 		"#include <fog_pars_fragment>",
+		"#include <logdepthbuf_pars_fragment>",
+		"#include <clipping_planes_pars_fragment>",
 
 
 		"uniform vec3 outlineColor;",
 		"uniform vec3 outlineColor;",
 		"uniform float outlineAlpha;",
 		"uniform float outlineAlpha;",
 
 
 		"void main() {",
 		"void main() {",
 
 
+		"	#include <clipping_planes_fragment>",
+		"	#include <logdepthbuf_fragment>",
+
 		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
 		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
 
 
+		"	#include <premultiplied_alpha_fragment>",
+		"	#include <tonemapping_fragment>",
+		"	#include <encodings_fragment>",
 		"	#include <fog_fragment>",
 		"	#include <fog_fragment>",
 
 
 		"}"
 		"}"
 
 
 	].join( "\n" );
 	].join( "\n" );
 
 
-	function createInvisibleMaterial() {
-
-		return new ShaderMaterial( { name: 'invisible', visible: false } );
-
-	}
-
-	function createMaterial( originalMaterial ) {
-
-		var shaderID = shaderIDs[ originalMaterial.type ];
-		var originalUniforms, originalVertexShader;
-
-		if ( shaderID !== undefined ) {
-
-			var shader = ShaderLib[ shaderID ];
-			originalUniforms = shader.uniforms;
-			originalVertexShader = shader.vertexShader;
-
-		} else if ( originalMaterial.isRawShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-			if ( ! /attribute\s+vec3\s+position\s*;/.test( originalVertexShader ) ||
-			     ! /attribute\s+vec3\s+normal\s*;/.test( originalVertexShader ) ) {
-
-				console.warn( 'THREE.OutlineEffect requires both vec3 position and normal attributes in vertex shader, ' +
-				              'does not draw outline for ' + originalMaterial.name + '(uuid:' + originalMaterial.uuid + ') material.' );
-
-				return createInvisibleMaterial();
-
-			}
-
-		} else if ( originalMaterial.isShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-		} else {
-
-			return createInvisibleMaterial();
-
-		}
-
-		var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
-
-		var vertexShader = originalVertexShader
-			// put vertexShaderChunk right before "void main() {...}"
-			.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
-			// put vertexShaderChunk2 the end of "void main() {...}"
-			// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
-			.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
-			// remove any light related lines
-			// Note: here is very sensitive to originalVertexShader
-			// TODO: consider safer way
-			.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
-
-		var defines = {};
-
-		if ( ! /vec3\s+transformed\s*=/.test( originalVertexShader ) &&
-		     ! /#include\s+<begin_vertex>/.test( originalVertexShader ) ) defines.DECLARE_TRANSFORMED = true;
+	function createMaterial() {
 
 
 		return new ShaderMaterial( {
 		return new ShaderMaterial( {
-			defines: defines,
-			uniforms: uniforms,
+			uniforms: UniformsUtils.merge( [
+				UniformsLib[ 'fog' ],
+				UniformsLib[ 'displacementmap' ],
+				uniformsOutline
+			] ),
 			vertexShader: vertexShader,
 			vertexShader: vertexShader,
 			fragmentShader: fragmentShader,
 			fragmentShader: fragmentShader,
-			side: BackSide,
-			//wireframe: true,
-			skinning: false,
-			morphTargets: false,
-			morphNormals: false,
-			fog: false
+			side: BackSide
 		} );
 		} );
 
 
 	}
 	}
@@ -253,7 +197,7 @@ var OutlineEffect = function ( renderer, parameters ) {
 		if ( data === undefined ) {
 		if ( data === undefined ) {
 
 
 			data = {
 			data = {
-				material: createMaterial( originalMaterial ),
+				material: createMaterial(),
 				used: true,
 				used: true,
 				keepAlive: defaultKeepAlive,
 				keepAlive: defaultKeepAlive,
 				count: 0
 				count: 0
@@ -281,9 +225,32 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 	}
 	}
 
 
+	function isCompatible( object ) {
+
+		var geometry = object.geometry;
+		var hasNormals = false;
+
+		if ( object.geometry !== undefined ) {
+
+			if ( geometry.isBufferGeometry ) {
+
+				hasNormals = geometry.attributes.normal !== undefined;
+
+			} else {
+
+				hasNormals = true; // the renderer always produces a normal attribute for Geometry
+
+			}
+
+		}
+
+		return ( object.isMesh === true && object.material !== undefined && hasNormals === true );
+
+	}
+
 	function setOutlineMaterial( object ) {
 	function setOutlineMaterial( object ) {
 
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 
 		if ( Array.isArray( object.material ) ) {
 		if ( Array.isArray( object.material ) ) {
 
 
@@ -306,7 +273,7 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 	function restoreOriginalMaterial( object ) {
 	function restoreOriginalMaterial( object ) {
 
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 
 		if ( Array.isArray( object.material ) ) {
 		if ( Array.isArray( object.material ) ) {
 
 
@@ -351,6 +318,14 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 		}
 		}
 
 
+		if ( originalMaterial.displacementMap ) {
+
+			material.uniforms.displacementMap.value = originalMaterial.displacementMap;
+			material.uniforms.displacementScale.value = originalMaterial.displacementScale;
+			material.uniforms.displacementBias.value = originalMaterial.displacementBias;
+
+		}
+
 	}
 	}
 
 
 	function updateOutlineMaterial( material, originalMaterial ) {
 	function updateOutlineMaterial( material, originalMaterial ) {
@@ -363,6 +338,9 @@ var OutlineEffect = function ( renderer, parameters ) {
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphNormals = originalMaterial.morphNormals;
 		material.morphNormals = originalMaterial.morphNormals;
 		material.fog = originalMaterial.fog;
 		material.fog = originalMaterial.fog;
+		material.toneMapped = originalMaterial.toneMapped;
+		material.premultipliedAlpha = originalMaterial.premultipliedAlpha;
+		material.displacementMap = originalMaterial.displacementMap;
 
 
 		if ( outlineParameters !== undefined ) {
 		if ( outlineParameters !== undefined ) {
 
 
@@ -389,6 +367,18 @@ var OutlineEffect = function ( renderer, parameters ) {
 
 
 		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
 		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
 
 
+		if ( originalMaterial.clippingPlanes ) {
+
+			material.clipping = true;
+
+			material.clippingPlanes = originalMaterial.clippingPlanes;
+			material.clipIntersection = originalMaterial.clipIntersection;
+			material.clipShadows = originalMaterial.clipShadows;
+
+		}
+
+		material.version = originalMaterial.version; // update outline material if necessary
+
 	}
 	}
 
 
 	function cleanupCache() {
 	function cleanupCache() {