InstancedPointsNodeMaterial.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
  2. import { varying } from '../core/VaryingNode.js';
  3. import { property } from '../core/PropertyNode.js';
  4. import { attribute } from '../core/AttributeNode.js';
  5. import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
  6. import { materialColor, materialPointWidth } from '../accessors/MaterialNode.js'; // or should this be a property, instead?
  7. import { modelViewMatrix } from '../accessors/ModelNode.js';
  8. import { positionGeometry } from '../accessors/PositionNode.js';
  9. import { smoothstep } from '../math/MathNode.js';
  10. import { tslFn, vec2, vec4 } from '../shadernode/ShaderNode.js';
  11. import { uv } from '../accessors/UVNode.js';
  12. import { viewport } from '../display/ViewportNode.js';
  13. import { PointsMaterial } from 'three';
  14. const defaultValues = new PointsMaterial();
  15. class InstancedPointsNodeMaterial extends NodeMaterial {
  16. constructor( params = {} ) {
  17. super();
  18. this.normals = false;
  19. this.lights = false;
  20. this.useAlphaToCoverage = true;
  21. this.useColor = params.vertexColors;
  22. this.pointWidth = 1;
  23. this.pointColorNode = null;
  24. this.setDefaultValues( defaultValues );
  25. this.setupShaders();
  26. this.setValues( params );
  27. }
  28. setupShaders() {
  29. const useAlphaToCoverage = this.alphaToCoverage;
  30. const useColor = this.useColor;
  31. this.vertexNode = tslFn( () => {
  32. //vUv = uv;
  33. varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this
  34. const instancePosition = attribute( 'instancePosition' );
  35. // camera space
  36. const mvPos = property( 'vec4', 'mvPos' );
  37. mvPos.assign( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) );
  38. const aspect = viewport.z.div( viewport.w );
  39. // clip space
  40. const clipPos = cameraProjectionMatrix.mul( mvPos );
  41. // offset in ndc space
  42. const offset = property( 'vec2', 'offset' );
  43. offset.assign( positionGeometry.xy );
  44. offset.assign( offset.mul( materialPointWidth ) );
  45. offset.assign( offset.div( viewport.z ) );
  46. offset.y.assign( offset.y.mul( aspect ) );
  47. // back to clip space
  48. offset.assign( offset.mul( clipPos.w ) );
  49. //clipPos.xy += offset;
  50. clipPos.assign( clipPos.add( vec4( offset, 0, 0 ) ) );
  51. return clipPos;
  52. //vec4 mvPosition = mvPos; // this was used for somethihng...
  53. } )();
  54. this.fragmentNode = tslFn( () => {
  55. const vUv = varying( vec2(), 'vUv' );
  56. // force assignment into correct place in flow
  57. const alpha = property( 'float', 'alpha' );
  58. alpha.assign( 1 );
  59. const a = vUv.x;
  60. const b = vUv.y;
  61. const len2 = a.mul( a ).add( b.mul( b ) );
  62. if ( useAlphaToCoverage ) {
  63. // force assignment out of following 'if' statement - to avoid uniform control flow errors
  64. const dlen = property( 'float', 'dlen' );
  65. dlen.assign( len2.fwidth() );
  66. alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
  67. } else {
  68. len2.greaterThan( 1.0 ).discard();
  69. }
  70. let pointColorNode;
  71. if ( this.pointColorNode ) {
  72. pointColorNode = this.pointColorNode;
  73. } else {
  74. if ( useColor ) {
  75. const instanceColor = attribute( 'instanceColor' );
  76. pointColorNode = instanceColor.mul( materialColor );
  77. } else {
  78. pointColorNode = materialColor;
  79. }
  80. }
  81. return vec4( pointColorNode, alpha );
  82. } )();
  83. this.needsUpdate = true;
  84. }
  85. get alphaToCoverage() {
  86. return this.useAlphaToCoverage;
  87. }
  88. set alphaToCoverage( value ) {
  89. if ( this.useAlphaToCoverage !== value ) {
  90. this.useAlphaToCoverage = value;
  91. this.setupShaders();
  92. }
  93. }
  94. }
  95. export default InstancedPointsNodeMaterial;
  96. addNodeMaterial( 'InstancedPointsNodeMaterial', InstancedPointsNodeMaterial );