Bläddra i källkod

MeshToonMaterial: Stop deriving from MeshPhongMaterial.

Mugen87 5 år sedan
förälder
incheckning
e8829adbdc

+ 2 - 4
examples/webgl_materials_variations_toon.html

@@ -85,9 +85,7 @@
 								bumpScale: bumpScale,
 								color: diffuseColor,
 								specular: specularColor,
-								reflectivity: beta,
 								shininess: specularShininess,
-								envMap: alphaIndex % 2 === 0 ? null : reflectionCube
 							} );
 
 							var mesh = new THREE.Mesh( geometry, material );
@@ -126,8 +124,8 @@
 				addLabel( "-shininess", new THREE.Vector3( - 350, 0, 0 ) );
 				addLabel( "+shininess", new THREE.Vector3( 350, 0, 0 ) );
 
-				addLabel( "-specular, -reflectivity", new THREE.Vector3( 0, - 300, 0 ) );
-				addLabel( "+specular, +reflectivity", new THREE.Vector3( 0, 300, 0 ) );
+				addLabel( "-specular", new THREE.Vector3( 0, - 300, 0 ) );
+				addLabel( "+specular", new THREE.Vector3( 0, 300, 0 ) );
 
 				addLabel( "-diffuse", new THREE.Vector3( 0, 0, - 300 ) );
 				addLabel( "+diffuse", new THREE.Vector3( 0, 0, 300 ) );

+ 123 - 5
src/materials/MeshToonMaterial.js

@@ -1,38 +1,156 @@
-import { MeshPhongMaterial } from './MeshPhongMaterial.js';
+import { TangentSpaceNormalMap } from '../constants.js';
+import { Material } from './Material.js';
+import { Vector2 } from '../math/Vector2.js';
+import { Color } from '../math/Color.js';
 
 /**
  * @author takahirox / http://github.com/takahirox
  *
  * parameters = {
- *  gradientMap: new THREE.Texture( <Image> )
+ *  color: <hex>,
+ *  specular: <hex>,
+ *  shininess: <float>,
+ *
+ *  map: new THREE.Texture( <Image> ),
+ *  gradientMap: new THREE.Texture( <Image> ),
+ *
+ *  lightMap: new THREE.Texture( <Image> ),
+ *  lightMapIntensity: <float>
+ *
+ *  aoMap: new THREE.Texture( <Image> ),
+ *  aoMapIntensity: <float>
+ *
+ *  emissive: <hex>,
+ *  emissiveIntensity: <float>
+ *  emissiveMap: new THREE.Texture( <Image> ),
+ *
+ *  bumpMap: new THREE.Texture( <Image> ),
+ *  bumpScale: <float>,
+ *
+ *  normalMap: new THREE.Texture( <Image> ),
+ *  normalMapType: THREE.TangentSpaceNormalMap,
+ *  normalScale: <Vector2>,
+ *
+ *  displacementMap: new THREE.Texture( <Image> ),
+ *  displacementScale: <float>,
+ *  displacementBias: <float>,
+ *
+ *  specularMap: new THREE.Texture( <Image> ),
+ *
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
+ *  wireframe: <boolean>,
+ *  wireframeLinewidth: <float>,
+ *
+ *  skinning: <bool>,
+ *  morphTargets: <bool>,
+ *  morphNormals: <bool>
  * }
  */
 
 function MeshToonMaterial( parameters ) {
 
-	MeshPhongMaterial.call( this );
+	Material.call( this );
 
 	this.defines = { 'TOON': '' };
 
 	this.type = 'MeshToonMaterial';
 
+	this.color = new Color( 0xffffff );
+	this.specular = new Color( 0x111111 );
+	this.shininess = 30;
+
+	this.map = null;
 	this.gradientMap = null;
 
+	this.lightMap = null;
+	this.lightMapIntensity = 1.0;
+
+	this.aoMap = null;
+	this.aoMapIntensity = 1.0;
+
+	this.emissive = new Color( 0x000000 );
+	this.emissiveIntensity = 1.0;
+	this.emissiveMap = null;
+
+	this.bumpMap = null;
+	this.bumpScale = 1;
+
+	this.normalMap = null;
+	this.normalMapType = TangentSpaceNormalMap;
+	this.normalScale = new Vector2( 1, 1 );
+
+	this.displacementMap = null;
+	this.displacementScale = 1;
+	this.displacementBias = 0;
+
+	this.specularMap = null;
+
+	this.alphaMap = null;
+
+	this.wireframe = false;
+	this.wireframeLinewidth = 1;
+	this.wireframeLinecap = 'round';
+	this.wireframeLinejoin = 'round';
+
+	this.skinning = false;
+	this.morphTargets = false;
+	this.morphNormals = false;
+
 	this.setValues( parameters );
 
 }
 
-MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype );
+MeshToonMaterial.prototype = Object.create( Material.prototype );
 MeshToonMaterial.prototype.constructor = MeshToonMaterial;
 
 MeshToonMaterial.prototype.isMeshToonMaterial = true;
 
 MeshToonMaterial.prototype.copy = function ( source ) {
 
-	MeshPhongMaterial.prototype.copy.call( this, source );
+	Material.prototype.copy.call( this, source );
+
+	this.color.copy( source.color );
+	this.specular.copy( source.specular );
+	this.shininess = source.shininess;
 
+	this.map = source.map;
 	this.gradientMap = source.gradientMap;
 
+	this.lightMap = source.lightMap;
+	this.lightMapIntensity = source.lightMapIntensity;
+
+	this.aoMap = source.aoMap;
+	this.aoMapIntensity = source.aoMapIntensity;
+
+	this.emissive.copy( source.emissive );
+	this.emissiveMap = source.emissiveMap;
+	this.emissiveIntensity = source.emissiveIntensity;
+
+	this.bumpMap = source.bumpMap;
+	this.bumpScale = source.bumpScale;
+
+	this.normalMap = source.normalMap;
+	this.normalMapType = source.normalMapType;
+	this.normalScale.copy( source.normalScale );
+
+	this.displacementMap = source.displacementMap;
+	this.displacementScale = source.displacementScale;
+	this.displacementBias = source.displacementBias;
+
+	this.specularMap = source.specularMap;
+
+	this.alphaMap = source.alphaMap;
+
+	this.wireframe = source.wireframe;
+	this.wireframeLinewidth = source.wireframeLinewidth;
+	this.wireframeLinecap = source.wireframeLinecap;
+	this.wireframeLinejoin = source.wireframeLinejoin;
+
+	this.skinning = source.skinning;
+	this.morphTargets = source.morphTargets;
+	this.morphNormals = source.morphNormals;
+
 	return this;
 
 };

+ 41 - 11
src/renderers/WebGLRenderer.js

@@ -1775,6 +1775,7 @@ function WebGLRenderer( parameters ) {
 
 			if ( material.isShaderMaterial ||
 				material.isMeshPhongMaterial ||
+				material.isMeshToonMaterial ||
 				material.isMeshStandardMaterial ||
 				material.envMap ) {
 
@@ -1790,6 +1791,7 @@ function WebGLRenderer( parameters ) {
 			}
 
 			if ( material.isMeshPhongMaterial ||
+				material.isMeshToonMaterial ||
 				material.isMeshLambertMaterial ||
 				material.isMeshBasicMaterial ||
 				material.isMeshStandardMaterial ||
@@ -1800,6 +1802,7 @@ function WebGLRenderer( parameters ) {
 			}
 
 			if ( material.isMeshPhongMaterial ||
+				material.isMeshToonMaterial ||
 				material.isMeshLambertMaterial ||
 				material.isMeshBasicMaterial ||
 				material.isMeshStandardMaterial ||
@@ -1919,19 +1922,15 @@ function WebGLRenderer( parameters ) {
 				refreshUniformsCommon( m_uniforms, material );
 				refreshUniformsLambert( m_uniforms, material );
 
-			} else if ( material.isMeshPhongMaterial ) {
+			} else if ( material.isMeshToonMaterial ) {
 
 				refreshUniformsCommon( m_uniforms, material );
+				refreshUniformsToon( m_uniforms, material );
 
-				if ( material.isMeshToonMaterial ) {
-
-					refreshUniformsToon( m_uniforms, material );
-
-				} else {
-
-					refreshUniformsPhong( m_uniforms, material );
+			} else if ( material.isMeshPhongMaterial ) {
 
-				}
+				refreshUniformsCommon( m_uniforms, material );
+				refreshUniformsPhong( m_uniforms, material );
 
 			} else if ( material.isMeshStandardMaterial ) {
 
@@ -2355,7 +2354,8 @@ function WebGLRenderer( parameters ) {
 
 	function refreshUniformsToon( uniforms, material ) {
 
-		refreshUniformsPhong( uniforms, material );
+		uniforms.specular.value.copy( material.specular );
+		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
 
 		if ( material.gradientMap ) {
 
@@ -2363,6 +2363,36 @@ function WebGLRenderer( parameters ) {
 
 		}
 
+		if ( material.emissiveMap ) {
+
+			uniforms.emissiveMap.value = material.emissiveMap;
+
+		}
+
+		if ( material.bumpMap ) {
+
+			uniforms.bumpMap.value = material.bumpMap;
+			uniforms.bumpScale.value = material.bumpScale;
+			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
+
+		}
+
+		if ( material.normalMap ) {
+
+			uniforms.normalMap.value = material.normalMap;
+			uniforms.normalScale.value.copy( material.normalScale );
+			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
+
+		}
+
+		if ( material.displacementMap ) {
+
+			uniforms.displacementMap.value = material.displacementMap;
+			uniforms.displacementScale.value = material.displacementScale;
+			uniforms.displacementBias.value = material.displacementBias;
+
+		}
+
 	}
 
 	function refreshUniformsStandard( uniforms, material ) {
@@ -2555,7 +2585,7 @@ function WebGLRenderer( parameters ) {
 
 	function materialNeedsLights( material ) {
 
-		return material.isMeshLambertMaterial || material.isMeshPhongMaterial ||
+		return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
 			material.isMeshStandardMaterial || material.isShadowMaterial ||
 			( material.isShaderMaterial && material.lights === true );
 

+ 8 - 0
src/renderers/shaders/ShaderChunk.js

@@ -39,6 +39,8 @@ import lightmap_pars_fragment from './ShaderChunk/lightmap_pars_fragment.glsl.js
 import lights_lambert_vertex from './ShaderChunk/lights_lambert_vertex.glsl.js';
 import lights_pars_begin from './ShaderChunk/lights_pars_begin.glsl.js';
 import envmap_physical_pars_fragment from './ShaderChunk/envmap_physical_pars_fragment.glsl.js';
+import lights_toon_fragment from './ShaderChunk/lights_toon_fragment.glsl.js';
+import lights_toon_pars_fragment from './ShaderChunk/lights_toon_pars_fragment.glsl.js';
 import lights_phong_fragment from './ShaderChunk/lights_phong_fragment.glsl.js';
 import lights_phong_pars_fragment from './ShaderChunk/lights_phong_pars_fragment.glsl.js';
 import lights_physical_fragment from './ShaderChunk/lights_physical_fragment.glsl.js';
@@ -110,6 +112,8 @@ import meshlambert_frag from './ShaderLib/meshlambert_frag.glsl.js';
 import meshlambert_vert from './ShaderLib/meshlambert_vert.glsl.js';
 import meshmatcap_frag from './ShaderLib/meshmatcap_frag.glsl.js';
 import meshmatcap_vert from './ShaderLib/meshmatcap_vert.glsl.js';
+import meshtoon_frag from './ShaderLib/meshtoon_frag.glsl.js';
+import meshtoon_vert from './ShaderLib/meshtoon_vert.glsl.js';
 import meshphong_frag from './ShaderLib/meshphong_frag.glsl.js';
 import meshphong_vert from './ShaderLib/meshphong_vert.glsl.js';
 import meshphysical_frag from './ShaderLib/meshphysical_frag.glsl.js';
@@ -165,6 +169,8 @@ export var ShaderChunk = {
 	lightmap_pars_fragment: lightmap_pars_fragment,
 	lights_lambert_vertex: lights_lambert_vertex,
 	lights_pars_begin: lights_pars_begin,
+	lights_toon_fragment: lights_toon_fragment,
+	lights_toon_pars_fragment: lights_toon_pars_fragment,
 	lights_phong_fragment: lights_phong_fragment,
 	lights_phong_pars_fragment: lights_phong_pars_fragment,
 	lights_physical_fragment: lights_physical_fragment,
@@ -236,6 +242,8 @@ export var ShaderChunk = {
 	meshlambert_vert: meshlambert_vert,
 	meshmatcap_frag: meshmatcap_frag,
 	meshmatcap_vert: meshmatcap_vert,
+	meshtoon_frag: meshtoon_frag,
+	meshtoon_vert: meshtoon_vert,
 	meshphong_frag: meshphong_frag,
 	meshphong_vert: meshphong_vert,
 	meshphysical_frag: meshphysical_frag,

+ 13 - 12
src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js

@@ -1,26 +1,27 @@
 export default /* glsl */`
-#ifdef TOON
+
+#ifdef USE_GRADIENTMAP
 
 	uniform sampler2D gradientMap;
 
-	vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {
+#endif
 
-		// dotNL will be from -1.0 to 1.0
-		float dotNL = dot( normal, lightDirection );
-		vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );
+vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {
 
-		#ifdef USE_GRADIENTMAP
+	// dotNL will be from -1.0 to 1.0
+	float dotNL = dot( normal, lightDirection );
+	vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );
 
-			return texture2D( gradientMap, coord ).rgb;
+	#ifdef USE_GRADIENTMAP
 
-		#else
+		return texture2D( gradientMap, coord ).rgb;
 
-			return ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );
+	#else
 
-		#endif
+		return ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );
 
+	#endif
 
-	}
+}
 
-#endif
 `;

+ 2 - 10
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js

@@ -19,16 +19,8 @@ struct BlinnPhongMaterial {
 
 void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {
 
-	#ifdef TOON
-
-		vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;
-
-	#else
-
-		float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
-		vec3 irradiance = dotNL * directLight.color;
-
-	#endif
+	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
+	vec3 irradiance = dotNL * directLight.color;
 
 	#ifndef PHYSICALLY_CORRECT_LIGHTS
 

+ 7 - 0
src/renderers/shaders/ShaderChunk/lights_toon_fragment.glsl.js

@@ -0,0 +1,7 @@
+export default /* glsl */`
+ToonMaterial material;
+material.diffuseColor = diffuseColor.rgb;
+material.specularColor = specular;
+material.specularShininess = shininess;
+material.specularStrength = specularStrength;
+`;

+ 46 - 0
src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js

@@ -0,0 +1,46 @@
+export default /* glsl */`
+varying vec3 vViewPosition;
+
+#ifndef FLAT_SHADED
+
+	varying vec3 vNormal;
+
+#endif
+
+
+struct ToonMaterial {
+
+	vec3	diffuseColor;
+	vec3	specularColor;
+	float	specularShininess;
+	float	specularStrength;
+
+};
+
+void RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {
+
+	vec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;
+
+	#ifndef PHYSICALLY_CORRECT_LIGHTS
+
+		irradiance *= PI; // punctual light
+
+	#endif
+
+	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+	reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;
+
+}
+
+void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {
+
+	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+}
+
+#define RE_Direct				RE_Direct_Toon
+#define RE_IndirectDiffuse		RE_IndirectDiffuse_Toon
+
+#define Material_LightProbeLOD( material )	(0)
+`;

+ 26 - 1
src/renderers/shaders/ShaderLib.js

@@ -63,7 +63,6 @@ var ShaderLib = {
 			UniformsLib.bumpmap,
 			UniformsLib.normalmap,
 			UniformsLib.displacementmap,
-			UniformsLib.gradientmap,
 			UniformsLib.fog,
 			UniformsLib.lights,
 			{
@@ -106,6 +105,32 @@ var ShaderLib = {
 
 	},
 
+	toon: {
+
+		uniforms: mergeUniforms( [
+			UniformsLib.common,
+			UniformsLib.specularmap,
+			UniformsLib.aomap,
+			UniformsLib.lightmap,
+			UniformsLib.emissivemap,
+			UniformsLib.bumpmap,
+			UniformsLib.normalmap,
+			UniformsLib.displacementmap,
+			UniformsLib.gradientmap,
+			UniformsLib.fog,
+			UniformsLib.lights,
+			{
+				emissive: { value: new Color( 0x000000 ) },
+				specular: { value: new Color( 0x111111 ) },
+				shininess: { value: 30 }
+			}
+		] ),
+
+		vertexShader: ShaderChunk.meshtoon_vert,
+		fragmentShader: ShaderChunk.meshtoon_frag
+
+	},
+
 	matcap: {
 
 		uniforms: mergeUniforms( [

+ 0 - 1
src/renderers/shaders/ShaderLib/meshphong_frag.glsl.js

@@ -20,7 +20,6 @@ uniform float opacity;
 #include <emissivemap_pars_fragment>
 #include <envmap_common_pars_fragment>
 #include <envmap_pars_fragment>
-#include <gradientmap_pars_fragment>
 #include <fog_pars_fragment>
 #include <bsdfs>
 #include <lights_pars_begin>

+ 71 - 0
src/renderers/shaders/ShaderLib/meshtoon_frag.glsl.js

@@ -0,0 +1,71 @@
+export default /* glsl */`
+#define TOON
+
+uniform vec3 diffuse;
+uniform vec3 emissive;
+uniform vec3 specular;
+uniform float shininess;
+uniform float opacity;
+
+#include <common>
+#include <packing>
+#include <dithering_pars_fragment>
+#include <color_pars_fragment>
+#include <uv_pars_fragment>
+#include <uv2_pars_fragment>
+#include <map_pars_fragment>
+#include <alphamap_pars_fragment>
+#include <aomap_pars_fragment>
+#include <lightmap_pars_fragment>
+#include <emissivemap_pars_fragment>
+#include <gradientmap_pars_fragment>
+#include <fog_pars_fragment>
+#include <bsdfs>
+#include <lights_pars_begin>
+#include <lights_toon_pars_fragment>
+#include <shadowmap_pars_fragment>
+#include <bumpmap_pars_fragment>
+#include <normalmap_pars_fragment>
+#include <specularmap_pars_fragment>
+#include <logdepthbuf_pars_fragment>
+#include <clipping_planes_pars_fragment>
+
+void main() {
+
+	#include <clipping_planes_fragment>
+
+	vec4 diffuseColor = vec4( diffuse, opacity );
+	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
+	vec3 totalEmissiveRadiance = emissive;
+
+	#include <logdepthbuf_fragment>
+	#include <map_fragment>
+	#include <color_fragment>
+	#include <alphamap_fragment>
+	#include <alphatest_fragment>
+	#include <specularmap_fragment>
+	#include <normal_fragment_begin>
+	#include <normal_fragment_maps>
+	#include <emissivemap_fragment>
+
+	// accumulation
+	#include <lights_toon_fragment>
+	#include <lights_fragment_begin>
+	#include <lights_fragment_maps>
+	#include <lights_fragment_end>
+
+	// modulation
+	#include <aomap_fragment>
+
+	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
+
+	gl_FragColor = vec4( outgoingLight, diffuseColor.a );
+
+	#include <tonemapping_fragment>
+	#include <encodings_fragment>
+	#include <fog_fragment>
+	#include <premultiplied_alpha_fragment>
+	#include <dithering_fragment>
+
+}
+`;

+ 57 - 0
src/renderers/shaders/ShaderLib/meshtoon_vert.glsl.js

@@ -0,0 +1,57 @@
+export default /* glsl */`
+#define TOON
+
+varying vec3 vViewPosition;
+
+#ifndef FLAT_SHADED
+
+	varying vec3 vNormal;
+
+#endif
+
+#include <common>
+#include <uv_pars_vertex>
+#include <uv2_pars_vertex>
+#include <displacementmap_pars_vertex>
+#include <color_pars_vertex>
+#include <fog_pars_vertex>
+#include <morphtarget_pars_vertex>
+#include <skinning_pars_vertex>
+#include <shadowmap_pars_vertex>
+#include <logdepthbuf_pars_vertex>
+#include <clipping_planes_pars_vertex>
+
+void main() {
+
+	#include <uv_vertex>
+	#include <uv2_vertex>
+	#include <color_vertex>
+
+	#include <beginnormal_vertex>
+	#include <morphnormal_vertex>
+	#include <skinbase_vertex>
+	#include <skinnormal_vertex>
+	#include <defaultnormal_vertex>
+
+#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED
+
+	vNormal = normalize( transformedNormal );
+
+#endif
+
+	#include <begin_vertex>
+	#include <morphtarget_vertex>
+	#include <skinning_vertex>
+	#include <displacementmap_vertex>
+	#include <project_vertex>
+	#include <logdepthbuf_vertex>
+	#include <clipping_planes_vertex>
+
+	vViewPosition = - mvPosition.xyz;
+
+	#include <worldpos_vertex>
+	#include <shadowmap_vertex>
+	#include <fog_vertex>
+
+}
+`;

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

@@ -23,7 +23,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 		MeshBasicMaterial: 'basic',
 		MeshLambertMaterial: 'lambert',
 		MeshPhongMaterial: 'phong',
-		MeshToonMaterial: 'phong',
+		MeshToonMaterial: 'toon',
 		MeshStandardMaterial: 'physical',
 		MeshPhysicalMaterial: 'physical',
 		MeshMatcapMaterial: 'matcap',