Просмотр исходного кода

LineMaterial: Trim line distances. (#33607)

Michael Herzog 4 недель назад
Родитель
Сommit
1141c8c5b3
2 измененных файлов с 80 добавлено и 33 удалено
  1. 35 15
      examples/jsm/lines/LineMaterial.js
  2. 45 18
      src/materials/nodes/Line2NodeMaterial.js

+ 35 - 15
examples/jsm/lines/LineMaterial.js

@@ -70,21 +70,20 @@ ShaderLib[ 'line' ] = {
 
 		#endif
 
-		void trimSegment( const in vec4 start, inout vec4 end ) {
+		float trimSegmentAlpha( const in vec4 start, const in vec4 end ) {
 
-			// trim end segment so it terminates between the camera plane and the near plane
+			// compute the interpolation factor needed to trim the 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
-			
+
 			// we need different nearEstimate formula for reversed and default depth buffer
 			// a is positive with a reversed depth buffer so it can be used for controlling the code flow
 			float nearEstimate = ( a > 0.0 ) ? ( - b / ( a + 1.0 ) ) : ( - 0.5 * b / a );
 
-			float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
-
-			end.xyz = mix( start.xyz, end.xyz, alpha );
+			return ( nearEstimate - start.z ) / ( end.z - start.z );
 
 		}
 
@@ -96,19 +95,19 @@ ShaderLib[ 'line' ] = {
 
 			#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 USE_DASH
+
+				float lineDistanceStart = dashScale * instanceDistanceStart;
+				float lineDistanceEnd = dashScale * instanceDistanceEnd;
+
+			#endif
+
 			#ifdef WORLD_UNITS
 
 				worldStart = start.xyz;
@@ -131,16 +130,37 @@ ShaderLib[ 'line' ] = {
 
 				if ( start.z < 0.0 && end.z >= 0.0 ) {
 
-					trimSegment( start, end );
+					float alpha = trimSegmentAlpha( start, end );
+					end.xyz = mix( start.xyz, end.xyz, alpha );
+
+					#ifdef USE_DASH
+
+						lineDistanceEnd = mix( lineDistanceStart, lineDistanceEnd, alpha );
+
+					#endif
 
 				} else if ( end.z < 0.0 && start.z >= 0.0 ) {
 
-					trimSegment( end, start );
+					float alpha = trimSegmentAlpha( end, start );
+					start.xyz = mix( end.xyz, start.xyz, alpha );
+
+					#ifdef USE_DASH
+
+						lineDistanceStart = mix( lineDistanceEnd, lineDistanceStart, alpha );
+
+					#endif
 
 				}
 
 			}
 
+			#ifdef USE_DASH
+
+				vLineDistance = ( position.y < 0.5 ) ? lineDistanceStart : lineDistanceEnd;
+				vUv = uv;
+
+			#endif
+
 			// clip space
 			vec4 clipStart = projectionMatrix * start;
 			vec4 clipEnd = projectionMatrix * end;

+ 45 - 18
src/materials/nodes/Line2NodeMaterial.js

@@ -137,7 +137,7 @@ class Line2NodeMaterial extends NodeMaterial {
 		const useDash = this._useDash;
 		const useWorldUnits = this._useWorldUnits;
 
-		const trimSegment = Fn( ( { start, end } ) => {
+		const trimSegmentAlpha = Fn( ( { start, end } ) => {
 
 			const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column
 			const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column
@@ -147,13 +147,11 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			const nearEstimate = a.greaterThan( 0 ).select( b.negate().div( a.add( 1 ) ), b.mul( - 0.5 ).div( a ) );
 
-			const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) );
-
-			return vec4( mix( start.xyz, end.xyz, alpha ), end.w );
+			return nearEstimate.sub( start.z ).div( end.z.sub( start.z ) );
 
 		} ).setLayout( {
-			name: 'trimSegment',
-			type: 'vec4',
+			name: 'trimSegmentAlpha',
+			type: 'float',
 			inputs: [
 				{ name: 'start', type: 'vec4' },
 				{ name: 'end', type: 'vec4' }
@@ -170,18 +168,12 @@ class Line2NodeMaterial extends NodeMaterial {
 			const start = vec4( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ).toVar( 'start' );
 			const end = vec4( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) ).toVar( 'end' );
 
-			if ( useDash ) {
-
-				const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale;
-				const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset;
-
-				const instanceDistanceStart = attribute( 'instanceDistanceStart' );
-				const instanceDistanceEnd = attribute( 'instanceDistanceEnd' );
+			let distanceStart, distanceEnd;
 
-				let lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( instanceDistanceStart ), dashScaleNode.mul( instanceDistanceEnd ) );
-				lineDistance = lineDistance.add( offsetNode );
+			if ( useDash ) {
 
-				varyingProperty( 'float', 'lineDistance' ).assign( lineDistance );
+				distanceStart = float( attribute( 'instanceDistanceStart' ) ).toVar( 'distanceStart' );
+				distanceEnd = float( attribute( 'instanceDistanceEnd' ) ).toVar( 'distanceEnd' );
 
 			}
 
@@ -205,16 +197,42 @@ class Line2NodeMaterial extends NodeMaterial {
 
 				If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => {
 
-					end.assign( trimSegment( { start: start, end: end } ) );
+					const alpha = trimSegmentAlpha( { start: start, end: end } );
+					end.assign( vec4( mix( start.xyz, end.xyz, alpha ), end.w ) );
+
+					if ( useDash ) {
+
+						distanceEnd.assign( mix( distanceStart, distanceEnd, alpha ) );
+
+					}
 
 				} ).ElseIf( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => {
 
-					start.assign( trimSegment( { start: end, end: start } ) );
+					const alpha = trimSegmentAlpha( { start: end, end: start } );
+					start.assign( vec4( mix( end.xyz, start.xyz, alpha ), start.w ) );
+
+					if ( useDash ) {
+
+						distanceStart.assign( mix( distanceEnd, distanceStart, alpha ) );
+
+					}
 
 			 	} );
 
 			} );
 
+			if ( useDash ) {
+
+				const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale;
+				const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset;
+
+				let lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( distanceStart ), dashScaleNode.mul( distanceEnd ) );
+				lineDistance = lineDistance.add( offsetNode );
+
+				varyingProperty( 'float', 'lineDistance' ).assign( lineDistance );
+
+			}
+
 			// clip space
 			const clipStart = cameraProjectionMatrix.mul( start );
 			const clipEnd = cameraProjectionMatrix.mul( end );
@@ -341,6 +359,15 @@ class Line2NodeMaterial extends NodeMaterial {
 
 			return vec2( mua, mub );
 
+		} ).setLayout( {
+			name: 'closestLineToLine',
+			type: 'vec2',
+			inputs: [
+				{ name: 'p1', type: 'vec3' },
+				{ name: 'p2', type: 'vec3' },
+				{ name: 'p3', type: 'vec3' },
+				{ name: 'p4', type: 'vec3' }
+			]
 		} );
 
 		this.colorNode = Fn( () => {

粤ICP备19079148号