LDrawConditionalLineNodeMaterial.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { Color } from 'three';
  2. import { attribute, cameraProjectionMatrix, dot, float, Fn, modelViewMatrix, modelViewProjection, NodeMaterial, normalize, positionGeometry, sign, uniform, varyingProperty, vec2, vec4 } from 'three/tsl';
  3. /**
  4. * A special line material for meshes loaded via {@link LDrawLoader}.
  5. *
  6. * This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
  7. * import the class from `LDrawConditionalLineMaterial.js`.
  8. *
  9. * @augments NodeMaterial
  10. * @three_import import { LDrawConditionalLineMaterial } from 'three/addons/materials/LDrawConditionalLineMaterial.js';
  11. */
  12. class LDrawConditionalLineMaterial extends NodeMaterial {
  13. static get type() {
  14. return 'LDrawConditionalLineMaterial';
  15. }
  16. /**
  17. * Constructs a new conditional line material.
  18. *
  19. * @param {Object} [parameters] - An object with one or more properties
  20. * defining the material's appearance. Any property of the material
  21. * (including any property from inherited materials) can be passed
  22. * in here. Color values can be passed any type of value accepted
  23. * by {@link Color#set}.
  24. */
  25. constructor( parameters ) {
  26. super();
  27. const vertexNode = /*@__PURE__*/ Fn( () => {
  28. const control0 = attribute( 'control0', 'vec3' );
  29. const control1 = attribute( 'control1', 'vec3' );
  30. const direction = attribute( 'direction', 'vec3' );
  31. const mvp = cameraProjectionMatrix.mul( modelViewMatrix );
  32. // Transform the line segment ends and control points into camera clip space
  33. const c0 = mvp.mul( vec4( control0, 1 ) ).toVar();
  34. const c1 = mvp.mul( vec4( control1, 1 ) ).toVar();
  35. const p0 = mvp.mul( vec4( positionGeometry, 1 ) ).toVar();
  36. const p1 = mvp.mul( vec4( positionGeometry.add( direction ), 1 ) ).toVar();
  37. c0.xy.divAssign( c0.w );
  38. c1.xy.divAssign( c1.w );
  39. p0.xy.divAssign( p0.w );
  40. p1.xy.divAssign( p1.w );
  41. // Get the direction of the segment and an orthogonal vector
  42. const dir = p1.xy.sub( p0.xy ).toVar();
  43. const norm = vec2( dir.y.negate(), dir.x ).toVar();
  44. // Get control point directions from the line
  45. const c0dir = c0.xy.sub( p1.xy ).toVar();
  46. const c1dir = c1.xy.sub( p1.xy ).toVar();
  47. // If the vectors to the controls points are pointed in different directions away
  48. // from the line segment then the line should not be drawn.
  49. const d0 = dot( normalize( norm ), normalize( c0dir ) ).toVar();
  50. const d1 = dot( normalize( norm ), normalize( c1dir ) ).toVar();
  51. const discardFlag = sign( d0 ).notEqual( sign( d1 ) ).select( float( 1 ), float( 0 ) );
  52. varyingProperty( 'float', 'discardFlag' ).assign( discardFlag );
  53. return modelViewProjection;
  54. } )();
  55. const fragmentNode = /*@__PURE__*/ Fn( () => {
  56. const discardFlag = varyingProperty( 'float', 'discardFlag' );
  57. discardFlag.greaterThan( float( 0.5 ) ).discard();
  58. return vec4( this._diffuseUniform, this._opacityUniform );
  59. } )();
  60. this.vertexNode = vertexNode;
  61. this.fragmentNode = fragmentNode;
  62. this._diffuseUniform = uniform( new Color() );
  63. this._opacityUniform = uniform( 1 );
  64. //
  65. Object.defineProperties( this, {
  66. /**
  67. * The material's opacity.
  68. *
  69. * @name LDrawConditionalLineMaterial#opacity
  70. * @type {number}
  71. * @default 1
  72. */
  73. opacity: {
  74. get: function () {
  75. return this._opacityUniform.value;
  76. },
  77. set: function ( value ) {
  78. this._opacityUniform.value = value;
  79. }
  80. },
  81. /**
  82. * The material's color.
  83. *
  84. * @name LDrawConditionalLineMaterial#color
  85. * @type {Color}
  86. * @default (1,1,1)
  87. */
  88. color: {
  89. get: function () {
  90. return this._diffuseUniform.value;
  91. },
  92. set: function ( value ) {
  93. this._diffuseUniform.value.copy( value );
  94. }
  95. }
  96. } );
  97. this.setValues( parameters );
  98. /**
  99. * This flag can be used for type testing.
  100. *
  101. * @type {boolean}
  102. * @readonly
  103. * @default true
  104. */
  105. this.isLDrawConditionalLineMaterial = true;
  106. }
  107. }
  108. export { LDrawConditionalLineMaterial };