Browse Source

Updated examples builds.

Mr.doob 3 years ago
parent
commit
3e5d141bcc

+ 51 - 35
examples/js/csm/CSMShader.js

@@ -92,19 +92,19 @@ IncidentLight directLight;
 		directionalLight = directionalLights[ i ];
 		directionalLight = directionalLights[ i ];
 		getDirectionalLightInfo( directionalLight, geometry, directLight );
 		getDirectionalLightInfo( directionalLight, geometry, directLight );
 
 
-		// NOTE: Depth gets larger away from the camera.
-		// cascade.x is closer, cascade.y is further
-		cascade = CSM_cascades[ i ];
-		cascadeCenter = ( cascade.x + cascade.y ) / 2.0;
-		closestEdge = linearDepth < cascadeCenter ? cascade.x : cascade.y;
-		margin = 0.25 * pow( closestEdge, 2.0 );
-		csmx = cascade.x - margin / 2.0;
-		csmy = cascade.y + margin / 2.0;
-		if( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS && linearDepth >= csmx && ( linearDepth < csmy || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 ) ) {
-
-			float dist = min( linearDepth - csmx, csmy - linearDepth );
-			float ratio = clamp( dist / margin, 0.0, 1.0 );
-			if( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) {
+	  	#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
+			// NOTE: Depth gets larger away from the camera.
+			// cascade.x is closer, cascade.y is further
+			cascade = CSM_cascades[ i ];
+			cascadeCenter = ( cascade.x + cascade.y ) / 2.0;
+			closestEdge = linearDepth < cascadeCenter ? cascade.x : cascade.y;
+			margin = 0.25 * pow( closestEdge, 2.0 );
+			csmx = cascade.x - margin / 2.0;
+			csmy = cascade.y + margin / 2.0;
+			if( linearDepth >= csmx && ( linearDepth < csmy || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 ) ) {
+
+				float dist = min( linearDepth - csmx, csmy - linearDepth );
+				float ratio = clamp( dist / margin, 0.0, 1.0 );
 
 
 				vec3 prevColor = directLight.color;
 				vec3 prevColor = directLight.color;
 				directionalLightShadow = directionalLightShadows[ i ];
 				directionalLightShadow = directionalLightShadows[ i ];
@@ -113,42 +113,58 @@ IncidentLight directLight;
 				bool shouldFadeLastCascade = UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth > cascadeCenter;
 				bool shouldFadeLastCascade = UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth > cascadeCenter;
 				directLight.color = mix( prevColor, directLight.color, shouldFadeLastCascade ? ratio : 1.0 );
 				directLight.color = mix( prevColor, directLight.color, shouldFadeLastCascade ? ratio : 1.0 );
 
 
-			}
-
-			ReflectedLight prevLight = reflectedLight;
-			RE_Direct( directLight, geometry, material, reflectedLight );
+				ReflectedLight prevLight = reflectedLight;
+				RE_Direct( directLight, geometry, material, reflectedLight );
 
 
-			bool shouldBlend = UNROLLED_LOOP_INDEX != CSM_CASCADES - 1 || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth < cascadeCenter;
-			float blendRatio = shouldBlend ? ratio : 1.0;
+				bool shouldBlend = UNROLLED_LOOP_INDEX != CSM_CASCADES - 1 || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth < cascadeCenter;
+				float blendRatio = shouldBlend ? ratio : 1.0;
 
 
-			reflectedLight.directDiffuse = mix( prevLight.directDiffuse, reflectedLight.directDiffuse, blendRatio );
-			reflectedLight.directSpecular = mix( prevLight.directSpecular, reflectedLight.directSpecular, blendRatio );
-			reflectedLight.indirectDiffuse = mix( prevLight.indirectDiffuse, reflectedLight.indirectDiffuse, blendRatio );
-			reflectedLight.indirectSpecular = mix( prevLight.indirectSpecular, reflectedLight.indirectSpecular, blendRatio );
+				reflectedLight.directDiffuse = mix( prevLight.directDiffuse, reflectedLight.directDiffuse, blendRatio );
+				reflectedLight.directSpecular = mix( prevLight.directSpecular, reflectedLight.directSpecular, blendRatio );
+				reflectedLight.indirectDiffuse = mix( prevLight.indirectDiffuse, reflectedLight.indirectDiffuse, blendRatio );
+				reflectedLight.indirectSpecular = mix( prevLight.indirectSpecular, reflectedLight.indirectSpecular, blendRatio );
 
 
-		}
+			}
+	  	#endif
 
 
 	}
 	}
 	#pragma unroll_loop_end
 	#pragma unroll_loop_end
 	#else
 	#else
 
 
-	#pragma unroll_loop_start
-	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
+		#pragma unroll_loop_start
+		for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
 
 
-		directionalLight = directionalLights[ i ];
-		getDirectionalLightInfo( directionalLight, geometry, directLight );
+			directionalLight = directionalLights[ i ];
+			getDirectionalLightInfo( directionalLight, geometry, directLight );
 
 
-		#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
+			#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
 
 
-		directionalLightShadow = directionalLightShadows[ i ];
-		if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
+			directionalLightShadow = directionalLightShadows[ i ];
+			if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 
 
-		#endif
+			if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometry, material, reflectedLight );
 
 
-		if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometry, material, reflectedLight );
+			#endif
 
 
-	}
-	#pragma unroll_loop_end
+		}
+		#pragma unroll_loop_end
+
+	#endif
+
+	#if ( NUM_DIR_LIGHTS > NUM_DIR_LIGHT_SHADOWS)
+		// compute the lights not casting shadows (if any)
+
+		#pragma unroll_loop_start
+		for ( int i = NUM_DIR_LIGHT_SHADOWS; i < NUM_DIR_LIGHTS; i ++ ) {
+
+			directionalLight = directionalLights[ i ];
+
+			getDirectionalLightInfo( directionalLight, geometry, directLight );
+
+			RE_Direct( directLight, geometry, material, reflectedLight );
+
+		}
+		#pragma unroll_loop_end
 
 
 	#endif
 	#endif
 
 

+ 1 - 1
examples/js/lines/LineMaterial.js

@@ -218,7 +218,7 @@
 				vec4 clip = projectionMatrix * worldPos;
 				vec4 clip = projectionMatrix * worldPos;
 
 
 				// shift the depth of the projected points so the line
 				// shift the depth of the projected points so the line
-				// segements overlap neatly
+				// segments overlap neatly
 				vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;
 				vec3 clipPose = ( position.y < 0.5 ) ? ndcStart : ndcEnd;
 				clip.z = clipPose.z * clip.w;
 				clip.z = clipPose.z * clip.w;
 
 

+ 213 - 138
examples/js/lines/LineSegments2.js

@@ -22,11 +22,13 @@
 
 
 	const _sphere = new THREE.Sphere();
 	const _sphere = new THREE.Sphere();
 
 
-	const _clipToWorldVector = new THREE.Vector4(); // Returns the margin required to expand by in world space given the distance from the camera,
+	const _clipToWorldVector = new THREE.Vector4();
+
+	let _ray, _instanceStart, _instanceEnd, _lineWidth; // Returns the margin required to expand by in world space given the distance from the camera,
 	// line width, resolution, and camera projection
 	// line width, resolution, and camera projection
 
 
 
 
-	function getWorldSpaceHalfWidth( camera, distance, lineWidth, resolution ) {
+	function getWorldSpaceHalfWidth( camera, distance, resolution ) {
 
 
 		// transform into clip space, adjust the x and y values by the pixel width offset, then
 		// transform into clip space, adjust the x and y values by the pixel width offset, then
 		// transform back into world space to get world offset. Note clip space is [-1, 1] so full
 		// transform back into world space to get world offset. Note clip space is [-1, 1] so full
@@ -35,8 +37,8 @@
 
 
 		_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
 		_clipToWorldVector.multiplyScalar( 1.0 / _clipToWorldVector.w );
 
 
-		_clipToWorldVector.x = lineWidth / resolution.width;
-		_clipToWorldVector.y = lineWidth / resolution.height;
+		_clipToWorldVector.x = _lineWidth / resolution.width;
+		_clipToWorldVector.y = _lineWidth / resolution.height;
 
 
 		_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse );
 		_clipToWorldVector.applyMatrix4( camera.projectionMatrixInverse );
 
 
@@ -46,234 +48,307 @@
 
 
 	}
 	}
 
 
-	class LineSegments2 extends THREE.Mesh {
+	function raycastWorldUnits( lineSegments, intersects ) {
 
 
-		constructor( geometry = new THREE.LineSegmentsGeometry(), material = new THREE.LineMaterial( {
-			color: Math.random() * 0xffffff
-		} ) ) {
+		for ( let i = 0, l = _instanceStart.count; i < l; i ++ ) {
 
 
-			super( geometry, material );
-			this.type = 'LineSegments2';
+			_line.start.fromBufferAttribute( _instanceStart, i );
 
 
-		} // for backwards-compatability, but could be a method of THREE.LineSegmentsGeometry...
+			_line.end.fromBufferAttribute( _instanceEnd, i );
 
 
+			const pointOnLine = new THREE.Vector3();
+			const point = new THREE.Vector3();
 
 
-		computeLineDistances() {
+			_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
 
 
-			const geometry = this.geometry;
-			const instanceStart = geometry.attributes.instanceStart;
-			const instanceEnd = geometry.attributes.instanceEnd;
-			const lineDistances = new Float32Array( 2 * instanceStart.count );
+			const isInside = point.distanceTo( pointOnLine ) < _lineWidth * 0.5;
 
 
-			for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {
+			if ( isInside ) {
 
 
-				_start.fromBufferAttribute( instanceStart, i );
+				intersects.push( {
+					point,
+					pointOnLine,
+					distance: _ray.origin.distanceTo( point ),
+					object: lineSegments,
+					face: null,
+					faceIndex: i,
+					uv: null,
+					uv2: null
+				} );
 
 
-				_end.fromBufferAttribute( instanceEnd, i );
+			}
 
 
-				lineDistances[ j ] = j === 0 ? 0 : lineDistances[ j - 1 ];
-				lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end );
+		}
 
 
-			}
+	}
 
 
-			const instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1
+	function raycastScreenSpace( lineSegments, camera, intersects ) {
 
 
-			geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
+		const projectionMatrix = camera.projectionMatrix;
+		const material = lineSegments.material;
+		const resolution = material.resolution;
+		const matrixWorld = lineSegments.matrixWorld;
+		const geometry = lineSegments.geometry;
+		const instanceStart = geometry.attributes.instanceStart;
+		const instanceEnd = geometry.attributes.instanceEnd;
+		const near = - camera.near; //
+		// pick a point 1 unit out along the ray to avoid the ray origin
+		// sitting at the camera origin which will cause "w" to be 0 when
+		// applying the projection matrix.
 
 
-			geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
+		_ray.at( 1, _ssOrigin ); // ndc space [ - 1.0, 1.0 ]
 
 
-			return this;
 
 
-		}
+		_ssOrigin.w = 1;
 
 
-		raycast( raycaster, intersects ) {
+		_ssOrigin.applyMatrix4( camera.matrixWorldInverse );
 
 
-			if ( raycaster.camera === null ) {
+		_ssOrigin.applyMatrix4( projectionMatrix );
 
 
-				console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2.' );
+		_ssOrigin.multiplyScalar( 1 / _ssOrigin.w ); // screen space
 
 
-			}
 
 
-			const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0;
-			const ray = raycaster.ray;
-			const camera = raycaster.camera;
-			const projectionMatrix = camera.projectionMatrix;
-			const matrixWorld = this.matrixWorld;
-			const geometry = this.geometry;
-			const material = this.material;
-			const resolution = material.resolution;
-			const lineWidth = material.linewidth + threshold;
-			const instanceStart = geometry.attributes.instanceStart;
-			const instanceEnd = geometry.attributes.instanceEnd; // camera forward is negative
+		_ssOrigin.x *= resolution.x / 2;
+		_ssOrigin.y *= resolution.y / 2;
+		_ssOrigin.z = 0;
 
 
-			const near = - camera.near; //
-			// check if we intersect the sphere bounds
+		_ssOrigin3.copy( _ssOrigin );
 
 
-			if ( geometry.boundingSphere === null ) {
+		_mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
 
 
-				geometry.computeBoundingSphere();
+		for ( let i = 0, l = instanceStart.count; i < l; i ++ ) {
 
 
-			}
+			_start4.fromBufferAttribute( instanceStart, i );
 
 
-			_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld );
+			_end4.fromBufferAttribute( instanceEnd, i );
 
 
-			const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( ray.origin ) ); // increase the sphere bounds by the worst case line screen space width
+			_start4.w = 1;
+			_end4.w = 1; // camera space
 
 
-			const sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, lineWidth, resolution );
-			_sphere.radius += sphereMargin;
+			_start4.applyMatrix4( _mvMatrix );
 
 
-			if ( raycaster.ray.intersectsSphere( _sphere ) === false ) {
+			_end4.applyMatrix4( _mvMatrix ); // skip the segment if it's entirely behind the camera
 
 
-				return;
 
 
-			} //
-			// check if we intersect the box bounds
+			const isBehindCameraNear = _start4.z > near && _end4.z > near;
 
 
+			if ( isBehindCameraNear ) {
 
 
-			if ( geometry.boundingBox === null ) {
+				continue;
 
 
-				geometry.computeBoundingBox();
+			} // trim the segment if it extends behind camera near
+
+
+			if ( _start4.z > near ) {
+
+				const deltaDist = _start4.z - _end4.z;
+				const t = ( _start4.z - near ) / deltaDist;
+
+				_start4.lerp( _end4, t );
+
+			} else if ( _end4.z > near ) {
+
+				const deltaDist = _end4.z - _start4.z;
+				const t = ( _end4.z - near ) / deltaDist;
+
+				_end4.lerp( _start4, t );
+
+			} // clip space
+
+
+			_start4.applyMatrix4( projectionMatrix );
+
+			_end4.applyMatrix4( projectionMatrix ); // ndc space [ - 1.0, 1.0 ]
+
+
+			_start4.multiplyScalar( 1 / _start4.w );
+
+			_end4.multiplyScalar( 1 / _end4.w ); // screen space
+
+
+			_start4.x *= resolution.x / 2;
+			_start4.y *= resolution.y / 2;
+			_end4.x *= resolution.x / 2;
+			_end4.y *= resolution.y / 2; // create 2d segment
+
+			_line.start.copy( _start4 );
+
+			_line.start.z = 0;
+
+			_line.end.copy( _end4 );
+
+			_line.end.z = 0; // get closest point on ray to segment
+
+			const param = _line.closestPointToPointParameter( _ssOrigin3, true );
+
+			_line.at( param, _closestPoint ); // check if the intersection point is within clip space
+
+
+			const zPos = THREE.MathUtils.lerp( _start4.z, _end4.z, param );
+			const isInClipSpace = zPos >= - 1 && zPos <= 1;
+
+			const isInside = _ssOrigin3.distanceTo( _closestPoint ) < _lineWidth * 0.5;
+
+			if ( isInClipSpace && isInside ) {
+
+				_line.start.fromBufferAttribute( instanceStart, i );
+
+				_line.end.fromBufferAttribute( instanceEnd, i );
+
+				_line.start.applyMatrix4( matrixWorld );
+
+				_line.end.applyMatrix4( matrixWorld );
+
+				const pointOnLine = new THREE.Vector3();
+				const point = new THREE.Vector3();
+
+				_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
+
+				intersects.push( {
+					point: point,
+					pointOnLine: pointOnLine,
+					distance: _ray.origin.distanceTo( point ),
+					object: lineSegments,
+					face: null,
+					faceIndex: i,
+					uv: null,
+					uv2: null
+				} );
 
 
 			}
 			}
 
 
-			_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld );
+		}
+
+	}
 
 
-			const distanceToBox = Math.max( camera.near, _box.distanceToPoint( ray.origin ) ); // increase the box bounds by the worst case line screen space width
+	class LineSegments2 extends THREE.Mesh {
 
 
-			const boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, lineWidth, resolution );
-			_box.max.x += boxMargin;
-			_box.max.y += boxMargin;
-			_box.max.z += boxMargin;
-			_box.min.x -= boxMargin;
-			_box.min.y -= boxMargin;
-			_box.min.z -= boxMargin;
+		constructor( geometry = new THREE.LineSegmentsGeometry(), material = new THREE.LineMaterial( {
+			color: Math.random() * 0xffffff
+		} ) ) {
 
 
-			if ( raycaster.ray.intersectsBox( _box ) === false ) {
+			super( geometry, material );
+			this.type = 'LineSegments2';
+
+		} // for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry...
 
 
-				return;
 
 
-			} //
-			// pick a point 1 unit out along the ray to avoid the ray origin
-			// sitting at the camera origin which will cause "w" to be 0 when
-			// applying the projection matrix.
+		computeLineDistances() {
 
 
+			const geometry = this.geometry;
+			const instanceStart = geometry.attributes.instanceStart;
+			const instanceEnd = geometry.attributes.instanceEnd;
+			const lineDistances = new Float32Array( 2 * instanceStart.count );
 
 
-			ray.at( 1, _ssOrigin ); // ndc space [ - 1.0, 1.0 ]
+			for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {
 
 
-			_ssOrigin.w = 1;
+				_start.fromBufferAttribute( instanceStart, i );
 
 
-			_ssOrigin.applyMatrix4( camera.matrixWorldInverse );
+				_end.fromBufferAttribute( instanceEnd, i );
 
 
-			_ssOrigin.applyMatrix4( projectionMatrix );
+				lineDistances[ j ] = j === 0 ? 0 : lineDistances[ j - 1 ];
+				lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end );
 
 
-			_ssOrigin.multiplyScalar( 1 / _ssOrigin.w ); // screen space
+			}
 
 
+			const instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1
 
 
-			_ssOrigin.x *= resolution.x / 2;
-			_ssOrigin.y *= resolution.y / 2;
-			_ssOrigin.z = 0;
+			geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
 
 
-			_ssOrigin3.copy( _ssOrigin );
+			geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1
 
 
-			_mvMatrix.multiplyMatrices( camera.matrixWorldInverse, matrixWorld );
+			return this;
 
 
-			for ( let i = 0, l = instanceStart.count; i < l; i ++ ) {
+		}
 
 
-				_start4.fromBufferAttribute( instanceStart, i );
+		raycast( raycaster, intersects ) {
 
 
-				_end4.fromBufferAttribute( instanceEnd, i );
+			const worldUnits = this.material.worldUnits;
+			const camera = raycaster.camera;
 
 
-				_start4.w = 1;
-				_end4.w = 1; // camera space
+			if ( camera === null && ! worldUnits ) {
 
 
-				_start4.applyMatrix4( _mvMatrix );
+				console.error( 'LineSegments2: "Raycaster.camera" needs to be set in order to raycast against LineSegments2 while worldUnits is set to false.' );
 
 
-				_end4.applyMatrix4( _mvMatrix ); // skip the segment if it's entirely behind the camera
+			}
 
 
+			const threshold = raycaster.params.Line2 !== undefined ? raycaster.params.Line2.threshold || 0 : 0;
+			_ray = raycaster.ray;
+			const matrixWorld = this.matrixWorld;
+			const geometry = this.geometry;
+			const material = this.material;
+			_lineWidth = material.linewidth + threshold;
+			_instanceStart = geometry.attributes.instanceStart;
+			_instanceEnd = geometry.attributes.instanceEnd; // check if we intersect the sphere bounds
 
 
-				const isBehindCameraNear = _start4.z > near && _end4.z > near;
+			if ( geometry.boundingSphere === null ) {
 
 
-				if ( isBehindCameraNear ) {
+				geometry.computeBoundingSphere();
 
 
-					continue;
+			}
 
 
-				} // trim the segment if it extends behind camera near
+			_sphere.copy( geometry.boundingSphere ).applyMatrix4( matrixWorld ); // increase the sphere bounds by the worst case line screen space width
 
 
 
 
-				if ( _start4.z > near ) {
+			let sphereMargin;
 
 
-					const deltaDist = _start4.z - _end4.z;
-					const t = ( _start4.z - near ) / deltaDist;
+			if ( worldUnits ) {
 
 
-					_start4.lerp( _end4, t );
+				sphereMargin = _lineWidth * 0.5;
 
 
-				} else if ( _end4.z > near ) {
+			} else {
 
 
-					const deltaDist = _end4.z - _start4.z;
-					const t = ( _end4.z - near ) / deltaDist;
+				const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( _ray.origin ) );
+				sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, material.resolution );
 
 
-					_end4.lerp( _start4, t );
+			}
 
 
-				} // clip space
+			_sphere.radius += sphereMargin;
 
 
+			if ( _ray.intersectsSphere( _sphere ) === false ) {
 
 
-				_start4.applyMatrix4( projectionMatrix );
+				return;
 
 
-				_end4.applyMatrix4( projectionMatrix ); // ndc space [ - 1.0, 1.0 ]
+			} // check if we intersect the box bounds
 
 
 
 
-				_start4.multiplyScalar( 1 / _start4.w );
+			if ( geometry.boundingBox === null ) {
 
 
-				_end4.multiplyScalar( 1 / _end4.w ); // screen space
+				geometry.computeBoundingBox();
 
 
+			}
 
 
-				_start4.x *= resolution.x / 2;
-				_start4.y *= resolution.y / 2;
-				_end4.x *= resolution.x / 2;
-				_end4.y *= resolution.y / 2; // create 2d segment
+			_box.copy( geometry.boundingBox ).applyMatrix4( matrixWorld ); // increase the box bounds by the worst case line width
 
 
-				_line.start.copy( _start4 );
 
 
-				_line.start.z = 0;
+			let boxMargin;
 
 
-				_line.end.copy( _end4 );
+			if ( worldUnits ) {
 
 
-				_line.end.z = 0; // get closest point on ray to segment
+				boxMargin = _lineWidth * 0.5;
 
 
-				const param = _line.closestPointToPointParameter( _ssOrigin3, true );
+			} else {
 
 
-				_line.at( param, _closestPoint ); // check if the intersection point is within clip space
+				const distanceToBox = Math.max( camera.near, _box.distanceToPoint( _ray.origin ) );
+				boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, material.resolution );
 
 
+			}
 
 
-				const zPos = THREE.MathUtils.lerp( _start4.z, _end4.z, param );
-				const isInClipSpace = zPos >= - 1 && zPos <= 1;
-				const isInside = _ssOrigin3.distanceTo( _closestPoint ) < lineWidth * 0.5;
+			_box.expandByScalar( boxMargin );
 
 
-				if ( isInClipSpace && isInside ) {
+			if ( _ray.intersectsBox( _box ) === false ) {
 
 
-					_line.start.fromBufferAttribute( instanceStart, i );
+				return;
 
 
-					_line.end.fromBufferAttribute( instanceEnd, i );
+			}
 
 
-					_line.start.applyMatrix4( matrixWorld );
+			if ( worldUnits ) {
 
 
-					_line.end.applyMatrix4( matrixWorld );
+				raycastWorldUnits( this, intersects );
 
 
-					const pointOnLine = new THREE.Vector3();
-					const point = new THREE.Vector3();
-					ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
-					intersects.push( {
-						point: point,
-						pointOnLine: pointOnLine,
-						distance: ray.origin.distanceTo( point ),
-						object: this,
-						face: null,
-						faceIndex: i,
-						uv: null,
-						uv2: null
-					} );
+			} else {
 
 
-				}
+				raycastScreenSpace( this, camera, intersects );
 
 
 			}
 			}
 
 

+ 1 - 1
examples/js/lines/Wireframe.js

@@ -13,7 +13,7 @@
 			super( geometry, material );
 			super( geometry, material );
 			this.type = 'Wireframe';
 			this.type = 'Wireframe';
 
 
-		} // for backwards-compatability, but could be a method of THREE.LineSegmentsGeometry...
+		} // for backwards-compatibility, but could be a method of THREE.LineSegmentsGeometry...
 
 
 
 
 		computeLineDistances() {
 		computeLineDistances() {

+ 1 - 2
examples/js/loaders/GLTFLoader.js

@@ -1457,7 +1457,7 @@
 		constructor() {
 		constructor() {
 
 
 			this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
 			this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
-			this.specularGlossinessParams = [ 'color', 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalMapType', 'displacementMap', 'displacementScale', 'displacementBias', 'specularMap', 'specular', 'glossinessMap', 'glossiness', 'alphaMap', 'envMap', 'envMapIntensity', 'refractionRatio' ];
+			this.specularGlossinessParams = [ 'color', 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalMapType', 'displacementMap', 'displacementScale', 'displacementBias', 'specularMap', 'specular', 'glossinessMap', 'glossiness', 'alphaMap', 'envMap', 'envMapIntensity' ];
 
 
 		}
 		}
 
 
@@ -1538,7 +1538,6 @@
 			material.alphaMap = null;
 			material.alphaMap = null;
 			material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
 			material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
 			material.envMapIntensity = 1.0;
 			material.envMapIntensity = 1.0;
-			material.refractionRatio = 0.98;
 			return material;
 			return material;
 
 
 		}
 		}

+ 1 - 1
examples/js/loaders/VTKLoader.js

@@ -688,9 +688,9 @@
 						// The [DATA] portion stores contiguously every block appended together. The offset from the beginning of the data section to the beginning of a block is
 						// The [DATA] portion stores contiguously every block appended together. The offset from the beginning of the data section to the beginning of a block is
 						// computed by summing the compressed block sizes from preceding blocks according to the header.
 						// computed by summing the compressed block sizes from preceding blocks according to the header.
 
 
+
 						const textNode = ele[ '#text' ];
 						const textNode = ele[ '#text' ];
 						const rawData = Array.isArray( textNode ) ? textNode[ 0 ] : textNode;
 						const rawData = Array.isArray( textNode ) ? textNode[ 0 ] : textNode;
-
 						const byteData = Base64toByteArray( rawData );
 						const byteData = Base64toByteArray( rawData );
 						let blocks = byteData[ 0 ];
 						let blocks = byteData[ 0 ];