瀏覽代碼

Added MeshDistanceMaterial

WestLangley 8 年之前
父節點
當前提交
af73e159d2

+ 3 - 19
examples/webgl_shadowmap_pointlight.html

@@ -90,7 +90,6 @@
 					specular: 0x222222,
 					alphaMap: texture, // alphaMap uses the g channel
 					alphaTest: 0.5,
-					transparent: true,
 					side: THREE.DoubleSide
 				} );
 
@@ -101,25 +100,10 @@
 				scene.add( torusKnot );
 
 				// custom distance material
-
-				var shader = THREE.ShaderLib[ "distanceRGBA" ];
-
-				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
-				uniforms.alphaMap.value = material.alphaMap;
-				uniforms.offsetRepeat.value.set( texture.offset.x, texture.offset.y, texture.repeat.x, texture.repeat.y );
-
-				var distanceMaterial = new THREE.ShaderMaterial( {
-					defines: {
-						'USE_SHADOWMAP': '',
-						'USE_ALPHAMAP': '',
-						'ALPHATEST': material.alphaTest
-					},
-					uniforms: uniforms,
-					vertexShader: shader.vertexShader,
-					fragmentShader: shader.fragmentShader,
-					side: THREE.DoubleSide
+				var distanceMaterial = new THREE.MeshDistanceMaterial( {
+					alphaMap: material.alphaMap,
+					alphaTest: material.alphaTest
 				} );
-
 				torusKnot.customDistanceMaterial = distanceMaterial;
 
 				//

+ 1 - 0
src/materials/Materials.js

@@ -10,6 +10,7 @@ export { MeshToonMaterial } from './MeshToonMaterial.js';
 export { MeshNormalMaterial } from './MeshNormalMaterial.js';
 export { MeshLambertMaterial } from './MeshLambertMaterial.js';
 export { MeshDepthMaterial } from './MeshDepthMaterial.js';
+export { MeshDistanceMaterial } from './MeshDistanceMaterial.js';
 export { MeshBasicMaterial } from './MeshBasicMaterial.js';
 export { LineDashedMaterial } from './LineDashedMaterial.js';
 export { LineBasicMaterial } from './LineBasicMaterial.js';

+ 83 - 0
src/materials/MeshDistanceMaterial.js

@@ -0,0 +1,83 @@
+import { Material } from './Material';
+
+/**
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * parameters = {
+ *
+ *  referencePosition: <float>,
+ *  nearDistance: <float>,
+ *  farDistance: <float>,
+ *
+ *  skinning: <bool>,
+ *  morphTargets: <bool>,
+ *
+ *  map: new THREE.Texture( <Image> ),
+ *
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
+ *  displacementMap: new THREE.Texture( <Image> ),
+ *  displacementScale: <float>,
+ *  displacementBias: <float>
+ *
+ * }
+ */
+
+function MeshDistanceMaterial( parameters ) {
+
+	Material.call( this );
+
+	this.type = 'MeshDistanceMaterial';
+
+	this.referencePosition = new THREE.Vector3();
+	this.nearDistance = 1;
+	this.farDistance = 1000;
+
+	this.skinning = false;
+	this.morphTargets = false;
+
+	this.map = null;
+
+	this.alphaMap = null;
+
+	this.displacementMap = null;
+	this.displacementScale = 1;
+	this.displacementBias = 0;
+
+	this.fog = false;
+	this.lights = false;
+
+	this.setValues( parameters );
+
+}
+
+MeshDistanceMaterial.prototype = Object.create( Material.prototype );
+MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
+
+MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
+
+MeshDistanceMaterial.prototype.copy = function ( source ) {
+
+	Material.prototype.copy.call( this, source );
+
+	this.referencePosition.copy( source.referencePosition );
+	this.nearDistance = source.nearDistance;
+	this.farDistance = source.farDistance;
+
+	this.skinning = source.skinning;
+	this.morphTargets = source.morphTargets;
+
+	this.map = source.map;
+
+	this.alphaMap = source.alphaMap;
+
+	this.displacementMap = source.displacementMap;
+	this.displacementScale = source.displacementScale;
+	this.displacementBias = source.displacementBias;
+
+	return this;
+
+};
+
+
+export { MeshDistanceMaterial };

+ 33 - 6
src/renderers/WebGLRenderer.js

@@ -1832,7 +1832,8 @@ function WebGLRenderer( parameters ) {
 				material.isMeshPhongMaterial ||
 				material.isMeshStandardMaterial ||
 				material.isMeshNormalMaterial ||
-				material.isMeshDepthMaterial ) {
+				material.isMeshDepthMaterial ||
+				material.isMeshDistanceMaterial ) {
 
 				refreshUniformsCommon( m_uniforms, material );
 
@@ -1875,13 +1876,11 @@ function WebGLRenderer( parameters ) {
 
 			} else if ( material.isMeshDepthMaterial ) {
 
-				if ( material.displacementMap ) {
+				refreshUniformsDepth( m_uniforms, material );
 
-					m_uniforms.displacementMap.value = material.displacementMap;
-					m_uniforms.displacementScale.value = material.displacementScale;
-					m_uniforms.displacementBias.value = material.displacementBias;
+			} else if ( material.isMeshDistanceMaterial ) {
 
-				}
+				refreshUniformsDistance( m_uniforms, material );
 
 			} else if ( material.isMeshNormalMaterial ) {
 
@@ -2192,6 +2191,34 @@ function WebGLRenderer( parameters ) {
 
 	}
 
+	function refreshUniformsDepth( uniforms, material ) {
+
+		if ( material.displacementMap ) {
+
+			uniforms.displacementMap.value = material.displacementMap;
+			uniforms.displacementScale.value = material.displacementScale;
+			uniforms.displacementBias.value = material.displacementBias;
+
+		}
+
+	}
+
+	function refreshUniformsDistance( uniforms, material ) {
+
+		if ( material.displacementMap ) {
+
+			uniforms.displacementMap.value = material.displacementMap;
+			uniforms.displacementScale.value = material.displacementScale;
+			uniforms.displacementBias.value = material.displacementBias;
+
+		}
+
+		uniforms.referencePosition.value.copy( material.referencePosition );
+		uniforms.nearDistance.value = material.nearDistance;
+		uniforms.farDistance.value = material.farDistance;
+
+	}
+
 	function refreshUniformsNormal( uniforms, material ) {
 
 		if ( material.bumpMap ) {

+ 1 - 1
src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl

@@ -1,4 +1,4 @@
-#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )
+#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
 
 	vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
 

+ 3 - 3
src/renderers/shaders/ShaderLib.js

@@ -194,9 +194,9 @@ var ShaderLib = {
 			UniformsLib.common,
 			UniformsLib.displacementmap,
 			{
-				lightPos: { value: new Vector3() },
-				shadowCameraNear: { value: 1 },
-				shadowCameraFar: { value: 1000 }
+				referencePosition: { value: new Vector3() },
+				nearDistance: { value: 1 },
+				farDistance: { value: 1000 }
 			}
 		] ),
 

+ 8 - 6
src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl

@@ -1,7 +1,9 @@
-uniform vec3 lightPos;
-uniform float shadowCameraNear;
-uniform float shadowCameraFar;
-varying vec4 vWorldPosition;
+#define DISTANCE
+
+uniform vec3 referencePosition;
+uniform float nearDistance;
+uniform float farDistance;
+varying vec3 vWorldPosition;
 
 #include <common>
 #include <packing>
@@ -20,8 +22,8 @@ void main () {
 	#include <alphamap_fragment>
 	#include <alphatest_fragment>
 
-	float dist = length( vWorldPosition.xyz - lightPos.xyz );
-	dist = ( dist - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );
+	float dist = length( vWorldPosition - referencePosition );
+	dist = ( dist - nearDistance ) / ( farDistance - nearDistance );
 	dist = saturate( dist ); // clamp to [ 0, 1 ]
 
 	gl_FragColor = packDepthToRGBA( dist );

+ 4 - 2
src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl

@@ -1,4 +1,6 @@
-varying vec4 vWorldPosition;
+#define DISTANCE
+
+varying vec3 vWorldPosition;
 
 #include <common>
 #include <uv_pars_vertex>
@@ -29,6 +31,6 @@ void main() {
 	#include <worldpos_vertex>
 	#include <clipping_planes_vertex>
 
-	vWorldPosition = worldPosition;
+	vWorldPosition = worldPosition.xyz;
 
 }

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

@@ -11,6 +11,7 @@ function WebGLPrograms( renderer, capabilities ) {
 
 	var shaderIDs = {
 		MeshDepthMaterial: 'depth',
+		MeshDistanceMaterial: 'distanceRGBA',
 		MeshNormalMaterial: 'normal',
 		MeshBasicMaterial: 'basic',
 		MeshLambertMaterial: 'lambert',

+ 19 - 23
src/renderers/webgl/WebGLShadowMap.js

@@ -9,6 +9,7 @@ import { ShaderMaterial } from '../../materials/ShaderMaterial';
 import { UniformsUtils } from '../shaders/UniformsUtils';
 import { ShaderLib } from '../shaders/ShaderLib';
 import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial';
+import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial';
 import { Vector4 } from '../../math/Vector4';
 import { Vector3 } from '../../math/Vector3';
 import { Vector2 } from '../../math/Vector2';
@@ -55,34 +56,29 @@ function WebGLShadowMap( _renderer, _shadows, _objects, capabilities ) {
 
 	// init
 
-	var depthMaterialTemplate = new MeshDepthMaterial();
-	depthMaterialTemplate.depthPacking = RGBADepthPacking;
-	depthMaterialTemplate.clipping = true;
-
-	var distanceShader = ShaderLib[ "distanceRGBA" ];
-	var distanceUniforms = UniformsUtils.clone( distanceShader.uniforms );
-
 	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
 
 		var useMorphing = ( i & _MorphingFlag ) !== 0;
 		var useSkinning = ( i & _SkinningFlag ) !== 0;
 
-		var depthMaterial = depthMaterialTemplate.clone();
-		depthMaterial.morphTargets = useMorphing;
-		depthMaterial.skinning = useSkinning;
+		var depthMaterial = new MeshDepthMaterial( {
+
+			depthPacking: RGBADepthPacking,
+
+			morphTargets: useMorphing,
+			skinning: useSkinning
+
+		} );
 
 		_depthMaterials[ i ] = depthMaterial;
 
-		var distanceMaterial = new ShaderMaterial( {
-			defines: {
-				'USE_SHADOWMAP': ''
-			},
-			uniforms: distanceUniforms,
-			vertexShader: distanceShader.vertexShader,
-			fragmentShader: distanceShader.fragmentShader,
+		//
+
+		var distanceMaterial = new MeshDistanceMaterial( {
+
 			morphTargets: useMorphing,
-			skinning: useSkinning,
-			clipping: true
+			skinning: useSkinning
+
 		} );
 
 		_distanceMaterials[ i ] = distanceMaterial;
@@ -384,11 +380,11 @@ function WebGLShadowMap( _renderer, _shadows, _objects, capabilities ) {
 		result.wireframeLinewidth = material.wireframeLinewidth;
 		result.linewidth = material.linewidth;
 
-		if ( isPointLight && result.uniforms.lightPos !== undefined ) {
+		if ( isPointLight && result.isMeshDistanceMaterial ) {
 
-			result.uniforms.lightPos.value.copy( lightPositionWorld );
-			result.uniforms.shadowCameraNear.value = shadowCameraNear;
-			result.uniforms.shadowCameraFar.value = shadowCameraFar;
+			result.referencePosition.copy( lightPositionWorld );
+			result.nearDistance = shadowCameraNear;
+			result.farDistance = shadowCameraFar;
 
 		}