618 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			618 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /** | ||
|  |  * parameters = { | ||
|  |  *  color: <hex>, | ||
|  |  *  linewidth: <float>, | ||
|  |  *  dashed: <boolean>, | ||
|  |  *  dashScale: <float>, | ||
|  |  *  dashSize: <float>, | ||
|  |  *  dashOffset: <float>, | ||
|  |  *  gapSize: <float>, | ||
|  |  *  resolution: <Vector2>, // to be set by renderer
 | ||
|  |  * } | ||
|  |  */ | ||
|  | 
 | ||
|  | import { | ||
|  | 	ShaderLib, | ||
|  | 	ShaderMaterial, | ||
|  | 	UniformsLib, | ||
|  | 	UniformsUtils, | ||
|  | 	Vector2 | ||
|  | } from 'three'; | ||
|  | 
 | ||
|  | 
 | ||
|  | UniformsLib.line = { | ||
|  | 
 | ||
|  | 	worldUnits: { value: 1 }, | ||
|  | 	linewidth: { value: 1 }, | ||
|  | 	resolution: { value: new Vector2( 1, 1 ) }, | ||
|  | 	dashOffset: { value: 0 }, | ||
|  | 	dashScale: { value: 1 }, | ||
|  | 	dashSize: { value: 1 }, | ||
|  | 	gapSize: { value: 1 } // todo FIX - maybe change to totalSize
 | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | ShaderLib[ 'line' ] = { | ||
|  | 
 | ||
|  | 	uniforms: UniformsUtils.merge( [ | ||
|  | 		UniformsLib.common, | ||
|  | 		UniformsLib.fog, | ||
|  | 		UniformsLib.line | ||
|  | 	] ), | ||
|  | 
 | ||
|  | 	vertexShader: | ||
|  | 	/* glsl */`
 | ||
|  | 		#include <common> | ||
|  | 		#include <color_pars_vertex> | ||
|  | 		#include <fog_pars_vertex> | ||
|  | 		#include <logdepthbuf_pars_vertex> | ||
|  | 		#include <clipping_planes_pars_vertex> | ||
|  | 
 | ||
|  | 		uniform float linewidth; | ||
|  | 		uniform vec2 resolution; | ||
|  | 
 | ||
|  | 		attribute vec3 instanceStart; | ||
|  | 		attribute vec3 instanceEnd; | ||
|  | 
 | ||
|  | 		attribute vec3 instanceColorStart; | ||
|  | 		attribute vec3 instanceColorEnd; | ||
|  | 
 | ||
|  | 		#ifdef WORLD_UNITS | ||
|  | 
 | ||
|  | 			varying vec4 worldPos; | ||
|  | 			varying vec3 worldStart; | ||
|  | 			varying vec3 worldEnd; | ||
|  | 
 | ||
|  | 			#ifdef USE_DASH | ||
|  | 
 | ||
|  | 				varying vec2 vUv; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 		#else | ||
|  | 
 | ||
|  | 			varying vec2 vUv; | ||
|  | 
 | ||
|  | 		#endif | ||
|  | 
 | ||
|  | 		#ifdef USE_DASH | ||
|  | 
 | ||
|  | 			uniform float dashScale; | ||
|  | 			attribute float instanceDistanceStart; | ||
|  | 			attribute float instanceDistanceEnd; | ||
|  | 			varying float vLineDistance; | ||
|  | 
 | ||
|  | 		#endif | ||
|  | 
 | ||
|  | 		void trimSegment( const in vec4 start, inout vec4 end ) { | ||
|  | 
 | ||
|  | 			// trim end segment so it terminates between the camera plane and the near plane
 | ||
|  | 
 | ||
|  | 			// conservative estimate of the near plane
 | ||
|  | 			float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
 | ||
|  | 			float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
 | ||
|  | 			float nearEstimate = - 0.5 * b / a; | ||
|  | 
 | ||
|  | 			float alpha = ( nearEstimate - start.z ) / ( end.z - start.z ); | ||
|  | 
 | ||
|  | 			end.xyz = mix( start.xyz, end.xyz, alpha ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void main() { | ||
|  | 
 | ||
|  | 			#ifdef USE_COLOR | ||
|  | 
 | ||
|  | 				vColor.xyz = ( position.y < 0.5 ) ? instanceColorStart : instanceColorEnd; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			#ifdef USE_DASH | ||
|  | 
 | ||
|  | 				vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd; | ||
|  | 				vUv = uv; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			float aspect = resolution.x / resolution.y; | ||
|  | 
 | ||
|  | 			// camera space
 | ||
|  | 			vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 ); | ||
|  | 			vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 ); | ||
|  | 
 | ||
|  | 			#ifdef WORLD_UNITS | ||
|  | 
 | ||
|  | 				worldStart = start.xyz; | ||
|  | 				worldEnd = end.xyz; | ||
|  | 
 | ||
|  | 			#else | ||
|  | 
 | ||
|  | 				vUv = uv; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			// special case for perspective projection, and segments that terminate either in, or behind, the camera plane
 | ||
|  | 			// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
 | ||
|  | 			// but we need to perform ndc-space calculations in the shader, so we must address this issue directly
 | ||
|  | 			// perhaps there is a more elegant solution -- WestLangley
 | ||
|  | 
 | ||
|  | 			bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
 | ||
|  | 
 | ||
|  | 			if ( perspective ) { | ||
|  | 
 | ||
|  | 				if ( start.z < 0.0 && end.z >= 0.0 ) { | ||
|  | 
 | ||
|  | 					trimSegment( start, end ); | ||
|  | 
 | ||
|  | 				} else if ( end.z < 0.0 && start.z >= 0.0 ) { | ||
|  | 
 | ||
|  | 					trimSegment( end, start ); | ||
|  | 
 | ||
|  | 				} | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			// clip space
 | ||
|  | 			vec4 clipStart = projectionMatrix * start; | ||
|  | 			vec4 clipEnd = projectionMatrix * end; | ||
|  | 
 | ||
|  | 			// ndc space
 | ||
|  | 			vec3 ndcStart = clipStart.xyz / clipStart.w; | ||
|  | 			vec3 ndcEnd = clipEnd.xyz / clipEnd.w; | ||
|  | 
 | ||
|  | 			// direction
 | ||
|  | 			vec2 dir = ndcEnd.xy - ndcStart.xy; | ||
|  | 
 | ||
|  | 			// account for clip-space aspect ratio
 | ||
|  | 			dir.x *= aspect; | ||
|  | 			dir = normalize( dir ); | ||
|  | 
 | ||
|  | 			#ifdef WORLD_UNITS | ||
|  | 
 | ||
|  | 				vec3 worldDir = normalize( end.xyz - start.xyz ); | ||
|  | 				vec3 tmpFwd = normalize( mix( start.xyz, end.xyz, 0.5 ) ); | ||
|  | 				vec3 worldUp = normalize( cross( worldDir, tmpFwd ) ); | ||
|  | 				vec3 worldFwd = cross( worldDir, worldUp ); | ||
|  | 				worldPos = position.y < 0.5 ? start: end; | ||
|  | 
 | ||
|  | 				// height offset
 | ||
|  | 				float hw = linewidth * 0.5; | ||
|  | 				worldPos.xyz += position.x < 0.0 ? hw * worldUp : - hw * worldUp; | ||
|  | 
 | ||
|  | 				// don't extend the line if we're rendering dashes because we
 | ||
|  | 				// won't be rendering the endcaps
 | ||
|  | 				#ifndef USE_DASH | ||
|  | 
 | ||
|  | 					// cap extension
 | ||
|  | 					worldPos.xyz += position.y < 0.5 ? - hw * worldDir : hw * worldDir; | ||
|  | 
 | ||
|  | 					// add width to the box
 | ||
|  | 					worldPos.xyz += worldFwd * hw; | ||
|  | 
 | ||
|  | 					// endcaps
 | ||
|  | 					if ( position.y > 1.0 || position.y < 0.0 ) { | ||
|  | 
 | ||
|  | 						worldPos.xyz -= worldFwd * 2.0 * hw; | ||
|  | 
 | ||
|  | 					} | ||
|  | 
 | ||
|  | 				#endif | ||
|  | 
 | ||
|  | 				// project the worldpos
 | ||
|  | 				vec4 clip = projectionMatrix * worldPos; | ||
|  | 
 | ||
|  | 				// shift the depth of the projected points so the line
 | ||
|  | 				// segments overlap neatly
 | ||
|  | 				vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd; | ||
|  | 				clip.z = clipPose.z * clip.w; | ||
|  | 
 | ||
|  | 			#else | ||
|  | 
 | ||
|  | 				vec2 offset = vec2( dir.y, - dir.x ); | ||
|  | 				// undo aspect ratio adjustment
 | ||
|  | 				dir.x /= aspect; | ||
|  | 				offset.x /= aspect; | ||
|  | 
 | ||
|  | 				// sign flip
 | ||
|  | 				if ( position.x < 0.0 ) offset *= - 1.0; | ||
|  | 
 | ||
|  | 				// endcaps
 | ||
|  | 				if ( position.y < 0.0 ) { | ||
|  | 
 | ||
|  | 					offset += - dir; | ||
|  | 
 | ||
|  | 				} else if ( position.y > 1.0 ) { | ||
|  | 
 | ||
|  | 					offset += dir; | ||
|  | 
 | ||
|  | 				} | ||
|  | 
 | ||
|  | 				// adjust for linewidth
 | ||
|  | 				offset *= linewidth; | ||
|  | 
 | ||
|  | 				// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
 | ||
|  | 				offset /= resolution.y; | ||
|  | 
 | ||
|  | 				// select end
 | ||
|  | 				vec4 clip = ( position.y < 0.5 ) ? clipStart : clipEnd; | ||
|  | 
 | ||
|  | 				// back to clip space
 | ||
|  | 				offset *= clip.w; | ||
|  | 
 | ||
|  | 				clip.xy += offset; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			gl_Position = clip; | ||
|  | 
 | ||
|  | 			vec4 mvPosition = ( position.y < 0.5 ) ? start : end; // this is an approximation
 | ||
|  | 
 | ||
|  | 			#include <logdepthbuf_vertex> | ||
|  | 			#include <clipping_planes_vertex> | ||
|  | 			#include <fog_vertex> | ||
|  | 
 | ||
|  | 		} | ||
|  | 		`,
 | ||
|  | 
 | ||
|  | 	fragmentShader: | ||
|  | 	/* glsl */`
 | ||
|  | 		uniform vec3 diffuse; | ||
|  | 		uniform float opacity; | ||
|  | 		uniform float linewidth; | ||
|  | 
 | ||
|  | 		#ifdef USE_DASH | ||
|  | 
 | ||
|  | 			uniform float dashOffset; | ||
|  | 			uniform float dashSize; | ||
|  | 			uniform float gapSize; | ||
|  | 
 | ||
|  | 		#endif | ||
|  | 
 | ||
|  | 		varying float vLineDistance; | ||
|  | 
 | ||
|  | 		#ifdef WORLD_UNITS | ||
|  | 
 | ||
|  | 			varying vec4 worldPos; | ||
|  | 			varying vec3 worldStart; | ||
|  | 			varying vec3 worldEnd; | ||
|  | 
 | ||
|  | 			#ifdef USE_DASH | ||
|  | 
 | ||
|  | 				varying vec2 vUv; | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 		#else | ||
|  | 
 | ||
|  | 			varying vec2 vUv; | ||
|  | 
 | ||
|  | 		#endif | ||
|  | 
 | ||
|  | 		#include <common> | ||
|  | 		#include <color_pars_fragment> | ||
|  | 		#include <fog_pars_fragment> | ||
|  | 		#include <logdepthbuf_pars_fragment> | ||
|  | 		#include <clipping_planes_pars_fragment> | ||
|  | 
 | ||
|  | 		vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) { | ||
|  | 
 | ||
|  | 			float mua; | ||
|  | 			float mub; | ||
|  | 
 | ||
|  | 			vec3 p13 = p1 - p3; | ||
|  | 			vec3 p43 = p4 - p3; | ||
|  | 
 | ||
|  | 			vec3 p21 = p2 - p1; | ||
|  | 
 | ||
|  | 			float d1343 = dot( p13, p43 ); | ||
|  | 			float d4321 = dot( p43, p21 ); | ||
|  | 			float d1321 = dot( p13, p21 ); | ||
|  | 			float d4343 = dot( p43, p43 ); | ||
|  | 			float d2121 = dot( p21, p21 ); | ||
|  | 
 | ||
|  | 			float denom = d2121 * d4343 - d4321 * d4321; | ||
|  | 
 | ||
|  | 			float numer = d1343 * d4321 - d1321 * d4343; | ||
|  | 
 | ||
|  | 			mua = numer / denom; | ||
|  | 			mua = clamp( mua, 0.0, 1.0 ); | ||
|  | 			mub = ( d1343 + d4321 * ( mua ) ) / d4343; | ||
|  | 			mub = clamp( mub, 0.0, 1.0 ); | ||
|  | 
 | ||
|  | 			return vec2( mua, mub ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		void main() { | ||
|  | 
 | ||
|  | 			#include <clipping_planes_fragment> | ||
|  | 
 | ||
|  | 			#ifdef USE_DASH | ||
|  | 
 | ||
|  | 				if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
 | ||
|  | 
 | ||
|  | 				if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX
 | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			float alpha = opacity; | ||
|  | 
 | ||
|  | 			#ifdef WORLD_UNITS | ||
|  | 
 | ||
|  | 				// Find the closest points on the view ray and the line segment
 | ||
|  | 				vec3 rayEnd = normalize( worldPos.xyz ) * 1e5; | ||
|  | 				vec3 lineDir = worldEnd - worldStart; | ||
|  | 				vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd ); | ||
|  | 
 | ||
|  | 				vec3 p1 = worldStart + lineDir * params.x; | ||
|  | 				vec3 p2 = rayEnd * params.y; | ||
|  | 				vec3 delta = p1 - p2; | ||
|  | 				float len = length( delta ); | ||
|  | 				float norm = len / linewidth; | ||
|  | 
 | ||
|  | 				#ifndef USE_DASH | ||
|  | 
 | ||
|  | 					#ifdef USE_ALPHA_TO_COVERAGE | ||
|  | 
 | ||
|  | 						float dnorm = fwidth( norm ); | ||
|  | 						alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm ); | ||
|  | 
 | ||
|  | 					#else | ||
|  | 
 | ||
|  | 						if ( norm > 0.5 ) { | ||
|  | 
 | ||
|  | 							discard; | ||
|  | 
 | ||
|  | 						} | ||
|  | 
 | ||
|  | 					#endif | ||
|  | 
 | ||
|  | 				#endif | ||
|  | 
 | ||
|  | 			#else | ||
|  | 
 | ||
|  | 				#ifdef USE_ALPHA_TO_COVERAGE | ||
|  | 
 | ||
|  | 					// artifacts appear on some hardware if a derivative is taken within a conditional
 | ||
|  | 					float a = vUv.x; | ||
|  | 					float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | ||
|  | 					float len2 = a * a + b * b; | ||
|  | 					float dlen = fwidth( len2 ); | ||
|  | 
 | ||
|  | 					if ( abs( vUv.y ) > 1.0 ) { | ||
|  | 
 | ||
|  | 						alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 ); | ||
|  | 
 | ||
|  | 					} | ||
|  | 
 | ||
|  | 				#else | ||
|  | 
 | ||
|  | 					if ( abs( vUv.y ) > 1.0 ) { | ||
|  | 
 | ||
|  | 						float a = vUv.x; | ||
|  | 						float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0; | ||
|  | 						float len2 = a * a + b * b; | ||
|  | 
 | ||
|  | 						if ( len2 > 1.0 ) discard; | ||
|  | 
 | ||
|  | 					} | ||
|  | 
 | ||
|  | 				#endif | ||
|  | 
 | ||
|  | 			#endif | ||
|  | 
 | ||
|  | 			vec4 diffuseColor = vec4( diffuse, alpha ); | ||
|  | 
 | ||
|  | 			#include <logdepthbuf_fragment> | ||
|  | 			#include <color_fragment> | ||
|  | 
 | ||
|  | 			gl_FragColor = vec4( diffuseColor.rgb, alpha ); | ||
|  | 
 | ||
|  | 			#include <tonemapping_fragment> | ||
|  | 			#include <colorspace_fragment> | ||
|  | 			#include <fog_fragment> | ||
|  | 			#include <premultiplied_alpha_fragment> | ||
|  | 
 | ||
|  | 		} | ||
|  | 		`
 | ||
|  | }; | ||
|  | 
 | ||
|  | class LineMaterial extends ShaderMaterial { | ||
|  | 
 | ||
|  | 	constructor( parameters ) { | ||
|  | 
 | ||
|  | 		super( { | ||
|  | 
 | ||
|  | 			type: 'LineMaterial', | ||
|  | 
 | ||
|  | 			uniforms: UniformsUtils.clone( ShaderLib[ 'line' ].uniforms ), | ||
|  | 
 | ||
|  | 			vertexShader: ShaderLib[ 'line' ].vertexShader, | ||
|  | 			fragmentShader: ShaderLib[ 'line' ].fragmentShader, | ||
|  | 
 | ||
|  | 			clipping: true // required for clipping support
 | ||
|  | 
 | ||
|  | 		} ); | ||
|  | 
 | ||
|  | 		this.isLineMaterial = true; | ||
|  | 
 | ||
|  | 		this.setValues( parameters ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get color() { | ||
|  | 
 | ||
|  | 		return this.uniforms.diffuse.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set color( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.diffuse.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get worldUnits() { | ||
|  | 
 | ||
|  | 		return 'WORLD_UNITS' in this.defines; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set worldUnits( value ) { | ||
|  | 
 | ||
|  | 		if ( value === true ) { | ||
|  | 
 | ||
|  | 			this.defines.WORLD_UNITS = ''; | ||
|  | 
 | ||
|  | 		} else { | ||
|  | 
 | ||
|  | 			delete this.defines.WORLD_UNITS; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get linewidth() { | ||
|  | 
 | ||
|  | 		return this.uniforms.linewidth.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set linewidth( value ) { | ||
|  | 
 | ||
|  | 		if ( ! this.uniforms.linewidth ) return; | ||
|  | 		this.uniforms.linewidth.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get dashed() { | ||
|  | 
 | ||
|  | 		return 'USE_DASH' in this.defines; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set dashed( value ) { | ||
|  | 
 | ||
|  | 		if ( ( value === true ) !== this.dashed ) { | ||
|  | 
 | ||
|  | 			this.needsUpdate = true; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if ( value === true ) { | ||
|  | 
 | ||
|  | 			this.defines.USE_DASH = ''; | ||
|  | 
 | ||
|  | 		} else { | ||
|  | 
 | ||
|  | 			delete this.defines.USE_DASH; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get dashScale() { | ||
|  | 
 | ||
|  | 		return this.uniforms.dashScale.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set dashScale( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.dashScale.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get dashSize() { | ||
|  | 
 | ||
|  | 		return this.uniforms.dashSize.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set dashSize( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.dashSize.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get dashOffset() { | ||
|  | 
 | ||
|  | 		return this.uniforms.dashOffset.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set dashOffset( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.dashOffset.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get gapSize() { | ||
|  | 
 | ||
|  | 		return this.uniforms.gapSize.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set gapSize( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.gapSize.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get opacity() { | ||
|  | 
 | ||
|  | 		return this.uniforms.opacity.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set opacity( value ) { | ||
|  | 
 | ||
|  | 		if ( ! this.uniforms ) return; | ||
|  | 		this.uniforms.opacity.value = value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get resolution() { | ||
|  | 
 | ||
|  | 		return this.uniforms.resolution.value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set resolution( value ) { | ||
|  | 
 | ||
|  | 		this.uniforms.resolution.value.copy( value ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get alphaToCoverage() { | ||
|  | 
 | ||
|  | 		return 'USE_ALPHA_TO_COVERAGE' in this.defines; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set alphaToCoverage( value ) { | ||
|  | 
 | ||
|  | 		if ( ! this.defines ) return; | ||
|  | 
 | ||
|  | 		if ( ( value === true ) !== this.alphaToCoverage ) { | ||
|  | 
 | ||
|  | 			this.needsUpdate = true; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if ( value === true ) { | ||
|  | 
 | ||
|  | 			this.defines.USE_ALPHA_TO_COVERAGE = ''; | ||
|  | 
 | ||
|  | 		} else { | ||
|  | 
 | ||
|  | 			delete this.defines.USE_ALPHA_TO_COVERAGE; | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | export { LineMaterial }; |