InstanceNode.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import Node, { addNodeClass } from '../core/Node.js';
  2. import { varyingProperty } from '../core/PropertyNode.js';
  3. import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './BufferAttributeNode.js';
  4. import { normalLocal } from './NormalNode.js';
  5. import { positionLocal } from './PositionNode.js';
  6. import { nodeProxy, vec3, mat3, mat4 } from '../shadernode/ShaderNode.js';
  7. import { DynamicDrawUsage, InstancedInterleavedBuffer, InstancedBufferAttribute } from 'three';
  8. import { NodeUpdateType } from '../core/constants.js';
  9. class InstanceNode extends Node {
  10. constructor( instanceMesh ) {
  11. super( 'void' );
  12. this.instanceMesh = instanceMesh;
  13. this.instanceMatrixNode = null;
  14. this.instanceColorNode = null;
  15. this.updateType = NodeUpdateType.FRAME;
  16. this.buffer = null;
  17. this.bufferColor = null;
  18. }
  19. setup( /*builder*/ ) {
  20. let instanceMatrixNode = this.instanceMatrixNode;
  21. const instanceMesh = this.instanceMesh;
  22. if ( instanceMatrixNode === null ) {
  23. const instanceAttribute = instanceMesh.instanceMatrix;
  24. const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 );
  25. this.buffer = buffer;
  26. const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
  27. const instanceBuffers = [
  28. // F.Signature -> bufferAttribute( array, type, stride, offset )
  29. bufferFn( buffer, 'vec4', 16, 0 ),
  30. bufferFn( buffer, 'vec4', 16, 4 ),
  31. bufferFn( buffer, 'vec4', 16, 8 ),
  32. bufferFn( buffer, 'vec4', 16, 12 )
  33. ];
  34. instanceMatrixNode = mat4( ...instanceBuffers );
  35. this.instanceMatrixNode = instanceMatrixNode;
  36. }
  37. const instanceColorAttribute = instanceMesh.instanceColor;
  38. if ( instanceColorAttribute && this.instanceColorNode === null ) {
  39. const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 );
  40. const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
  41. this.bufferColor = buffer;
  42. this.instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) );
  43. }
  44. // POSITION
  45. const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz;
  46. // NORMAL
  47. const m = mat3( instanceMatrixNode[ 0 ].xyz, instanceMatrixNode[ 1 ].xyz, instanceMatrixNode[ 2 ].xyz );
  48. const transformedNormal = normalLocal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) );
  49. const instanceNormal = m.mul( transformedNormal ).xyz;
  50. // ASSIGNS
  51. positionLocal.assign( instancePosition );
  52. normalLocal.assign( instanceNormal );
  53. // COLOR
  54. if ( this.instanceColorNode !== null ) {
  55. varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode );
  56. }
  57. }
  58. update( /*frame*/ ) {
  59. if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) {
  60. this.buffer.version = this.instanceMesh.instanceMatrix.version;
  61. }
  62. if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) {
  63. this.bufferColor.version = this.instanceMesh.instanceColor.version;
  64. }
  65. }
  66. }
  67. export default InstanceNode;
  68. export const instance = nodeProxy( InstanceNode );
  69. addNodeClass( 'InstanceNode', InstanceNode );