128 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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 );
 |