UNPKG

three

Version:

JavaScript 3D library

154 lines (107 loc) 3.87 kB
import { Color } from 'three'; import { attribute, cameraProjectionMatrix, dot, float, Fn, modelViewMatrix, modelViewProjection, NodeMaterial, normalize, positionGeometry, sign, uniform, varyingProperty, vec2, vec4 } from 'three/tsl'; /** * A special line material for meshes loaded via {@link LDrawLoader}. * * This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer}, * import the class from `LDrawConditionalLineMaterial.js`. * * @augments NodeMaterial */ class LDrawConditionalLineMaterial extends NodeMaterial { static get type() { return 'LDrawConditionalLineMaterial'; } /** * Constructs a new conditional line material. * * @param {Object} [parameters] - An object with one or more properties * defining the material's appearance. Any property of the material * (including any property from inherited materials) can be passed * in here. Color values can be passed any type of value accepted * by {@link Color#set}. */ constructor( parameters ) { super(); const vertexNode = /*@__PURE__*/ Fn( () => { const control0 = attribute( 'control0', 'vec3' ); const control1 = attribute( 'control1', 'vec3' ); const direction = attribute( 'direction', 'vec3' ); const mvp = cameraProjectionMatrix.mul( modelViewMatrix ); // Transform the line segment ends and control points into camera clip space const c0 = mvp.mul( vec4( control0, 1 ) ).toVar(); const c1 = mvp.mul( vec4( control1, 1 ) ).toVar(); const p0 = mvp.mul( vec4( positionGeometry, 1 ) ).toVar(); const p1 = mvp.mul( vec4( positionGeometry.add( direction ), 1 ) ).toVar(); c0.xy.divAssign( c0.w ); c1.xy.divAssign( c1.w ); p0.xy.divAssign( p0.w ); p1.xy.divAssign( p1.w ); // Get the direction of the segment and an orthogonal vector const dir = p1.xy.sub( p0.xy ).toVar(); const norm = vec2( dir.y.negate(), dir.x ).toVar(); // Get control point directions from the line const c0dir = c0.xy.sub( p1.xy ).toVar(); const c1dir = c1.xy.sub( p1.xy ).toVar(); // If the vectors to the controls points are pointed in different directions away // from the line segment then the line should not be drawn. const d0 = dot( normalize( norm ), normalize( c0dir ) ).toVar(); const d1 = dot( normalize( norm ), normalize( c1dir ) ).toVar(); const discardFlag = sign( d0 ).notEqual( sign( d1 ) ).select( float( 1 ), float( 0 ) ); varyingProperty( 'float', 'discardFlag' ).assign( discardFlag ); return modelViewProjection; } )(); const fragmentNode = /*@__PURE__*/ Fn( () => { const discardFlag = varyingProperty( 'float', 'discardFlag' ); discardFlag.greaterThan( float( 0.5 ) ).discard(); return vec4( this._diffuseUniform, this._opacityUniform ); } )(); this.vertexNode = vertexNode; this.fragmentNode = fragmentNode; this._diffuseUniform = uniform( new Color() ); this._opacityUniform = uniform( 1 ); // Object.defineProperties( this, { /** * The material's opacity. * * @name LDrawConditionalLineMaterial#opacity * @type {number} * @default 1 */ opacity: { get: function () { return this._opacityUniform.value; }, set: function ( value ) { this._opacityUniform.value = value; } }, /** * The material's color. * * @name LDrawConditionalLineMaterial#color * @type {Color} * @default (1,1,1) */ color: { get: function () { return this._diffuseUniform.value; }, set: function ( value ) { this._diffuseUniform.value.copy( value ); } } } ); this.setValues( parameters ); /** * This flag can be used for type testing. * * @type {boolean} * @readonly * @default true */ this.isLDrawConditionalLineMaterial = true; } } export { LDrawConditionalLineMaterial };