BufferAttributeNode.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. if ( value && value.isBufferAttribute === true ) {
  17. this.attribute = value;
  18. this.usage = value.usage;
  19. this.instanced = value.isInstancedBufferAttribute;
  20. }
  21. }
  22. getNodeType( builder ) {
  23. if ( this.bufferType === null ) {
  24. this.bufferType = builder.getTypeFromAttribute( this.attribute );
  25. }
  26. return this.bufferType;
  27. }
  28. setup( builder ) {
  29. if ( this.attribute !== null ) return;
  30. const type = this.getNodeType( builder );
  31. const array = this.value;
  32. const itemSize = builder.getTypeLength( type );
  33. const stride = this.bufferStride || itemSize;
  34. const offset = this.bufferOffset;
  35. const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride );
  36. const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset );
  37. buffer.setUsage( this.usage );
  38. this.attribute = bufferAttribute;
  39. this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute
  40. }
  41. generate( builder ) {
  42. const nodeType = this.getNodeType( builder );
  43. const nodeUniform = builder.getBufferAttributeFromNode( this, nodeType );
  44. const propertyName = builder.getPropertyName( nodeUniform );
  45. let output = null;
  46. if ( builder.shaderStage === 'vertex' ) {
  47. output = propertyName;
  48. } else {
  49. const nodeVarying = varying( this );
  50. output = nodeVarying.build( builder, nodeType );
  51. }
  52. return output;
  53. }
  54. getInputType( /*builder*/ ) {
  55. return 'bufferAttribute';
  56. }
  57. setUsage( value ) {
  58. this.usage = value;
  59. return this;
  60. }
  61. setInstanced( value ) {
  62. this.instanced = value;
  63. return this;
  64. }
  65. }
  66. export default BufferAttributeNode;
  67. export const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) );
  68. export const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage );
  69. export const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true );
  70. export const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true );
  71. addNodeElement( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) );
  72. addNodeClass( 'BufferAttributeNode', BufferAttributeNode );