import InputNode from '../core/InputNode.js'; import { addNodeClass } from '../core/Node.js'; import { varying } from '../core/VaryingNode.js'; import { nodeObject, addNodeElement } from '../shadernode/ShaderNode.js'; import { InterleavedBufferAttribute, InterleavedBuffer, StaticDrawUsage, DynamicDrawUsage } from 'three'; class BufferAttributeNode extends InputNode { constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) { super( value, bufferType ); this.isBufferNode = true; this.bufferType = bufferType; this.bufferStride = bufferStride; this.bufferOffset = bufferOffset; this.usage = StaticDrawUsage; this.instanced = false; this.attribute = null; if ( value && value.isBufferAttribute === true ) { this.attribute = value; this.usage = value.usage; this.instanced = value.isInstancedBufferAttribute; } } getNodeType( builder ) { if ( this.bufferType === null ) { this.bufferType = builder.getTypeFromAttribute( this.attribute ); } return this.bufferType; } setup( builder ) { if ( this.attribute !== null ) return; const type = this.getNodeType( builder ); const array = this.value; const itemSize = builder.getTypeLength( type ); const stride = this.bufferStride || itemSize; const offset = this.bufferOffset; const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride ); const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset ); buffer.setUsage( this.usage ); this.attribute = bufferAttribute; this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute } generate( builder ) { const nodeType = this.getNodeType( builder ); const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType ); const propertyName = builder.getPropertyName( nodeAttribute ); let output = null; if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { this.name = propertyName; output = propertyName; } else { const nodeVarying = varying( this ); output = nodeVarying.build( builder, nodeType ); } return output; } getInputType( /*builder*/ ) { return 'bufferAttribute'; } setUsage( value ) { this.usage = value; return this; } setInstanced( value ) { this.instanced = value; return this; } } export default BufferAttributeNode; export const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) ); export const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage ); export const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true ); export const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true ); addNodeElement( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) ); addNodeClass( 'BufferAttributeNode', BufferAttributeNode );