BufferAttributeNode.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import InputNode from '../core/InputNode.js';
  2. import { addNodeClass } from '../core/Node.js';
  3. import { varying } from '../core/VaryingNode.js';
  4. import { nodeObject, addNodeElement } from '../shadernode/ShaderNode.js';
  5. import { InterleavedBufferAttribute, InterleavedBuffer, StaticDrawUsage, DynamicDrawUsage } from 'three';
  6. class BufferAttributeNode extends InputNode {
  7. constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) {
  8. super( value, bufferType );
  9. this.isBufferNode = true;
  10. this.bufferType = bufferType;
  11. this.bufferStride = bufferStride;
  12. this.bufferOffset = bufferOffset;
  13. this.usage = StaticDrawUsage;
  14. this.instanced = false;
  15. this.attribute = null;
  16. this.global = true;
  17. if ( value && value.isBufferAttribute === true ) {
  18. this.attribute = value;
  19. this.usage = value.usage;
  20. this.instanced = value.isInstancedBufferAttribute;
  21. }
  22. }
  23. getHash( builder ) {
  24. if ( this.bufferStride === 0 && this.bufferOffset === 0 ) {
  25. let bufferData = builder.globalCache.getData( this.value );
  26. if ( bufferData === undefined ) {
  27. bufferData = {
  28. node: this
  29. };
  30. builder.globalCache.setData( this.value, bufferData );
  31. }
  32. return bufferData.node.uuid;
  33. }
  34. return this.uuid;
  35. }
  36. getNodeType( builder ) {
  37. if ( this.bufferType === null ) {
  38. this.bufferType = builder.getTypeFromAttribute( this.attribute );
  39. }
  40. return this.bufferType;
  41. }
  42. setup( builder ) {
  43. if ( this.attribute !== null ) return;
  44. const type = this.getNodeType( builder );
  45. const array = this.value;
  46. const itemSize = builder.getTypeLength( type );
  47. const stride = this.bufferStride || itemSize;
  48. const offset = this.bufferOffset;
  49. const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride );
  50. const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset );
  51. buffer.setUsage( this.usage );
  52. this.attribute = bufferAttribute;
  53. this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute
  54. }
  55. generate( builder ) {
  56. const nodeType = this.getNodeType( builder );
  57. const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType );
  58. const propertyName = builder.getPropertyName( nodeAttribute );
  59. let output = null;
  60. if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) {
  61. this.name = propertyName;
  62. output = propertyName;
  63. } else {
  64. const nodeVarying = varying( this );
  65. output = nodeVarying.build( builder, nodeType );
  66. }
  67. return output;
  68. }
  69. getInputType( /*builder*/ ) {
  70. return 'bufferAttribute';
  71. }
  72. setUsage( value ) {
  73. this.usage = value;
  74. if ( this.attribute && this.attribute.isBufferAttribute === true ) {
  75. this.attribute.usage = value;
  76. }
  77. return this;
  78. }
  79. setInstanced( value ) {
  80. this.instanced = value;
  81. return this;
  82. }
  83. }
  84. export default BufferAttributeNode;
  85. export const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) );
  86. export const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage );
  87. export const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true );
  88. export const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true );
  89. addNodeElement( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) );
  90. addNodeClass( 'BufferAttributeNode', BufferAttributeNode );