UNPKG

three

Version:

JavaScript 3D library

129 lines (81 loc) 3.02 kB
import Node from '../core/Node.js'; import { normalLocal } from './Normal.js'; import { positionLocal } from './Position.js'; import { nodeProxy, vec3, mat3, mat4, int, ivec2, float, Fn } from '../tsl/TSLBase.js'; import { textureLoad } from './TextureNode.js'; import { textureSize } from './TextureSizeNode.js'; import { tangentLocal } from './Tangent.js'; import { instanceIndex, drawIndex } from '../core/IndexNode.js'; import { varyingProperty } from '../core/PropertyNode.js'; class BatchNode extends Node { static get type() { return 'BatchNode'; } constructor( batchMesh ) { super( 'void' ); this.batchMesh = batchMesh; this.batchingIdNode = null; } setup( builder ) { // POSITION if ( this.batchingIdNode === null ) { if ( builder.getDrawIndex() === null ) { this.batchingIdNode = instanceIndex; } else { this.batchingIdNode = drawIndex; } } const getIndirectIndex = Fn( ( [ id ] ) => { const size = textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ); const x = int( id ).modInt( int( size ) ); const y = int( id ).div( int( size ) ); return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x; } ).setLayout( { name: 'getIndirectIndex', type: 'uint', inputs: [ { name: 'id', type: 'int' } ] } ); const indirectId = getIndirectIndex( int( this.batchingIdNode ) ); const matricesTexture = this.batchMesh._matricesTexture; const size = textureSize( textureLoad( matricesTexture ), 0 ); const j = float( indirectId ).mul( 4 ).toInt().toVar(); const x = j.modInt( size ); const y = j.div( int( size ) ); const batchingMatrix = mat4( textureLoad( matricesTexture, ivec2( x, y ) ), textureLoad( matricesTexture, ivec2( x.add( 1 ), y ) ), textureLoad( matricesTexture, ivec2( x.add( 2 ), y ) ), textureLoad( matricesTexture, ivec2( x.add( 3 ), y ) ) ); const colorsTexture = this.batchMesh._colorsTexture; if ( colorsTexture !== null ) { const getBatchingColor = Fn( ( [ id ] ) => { const size = textureSize( textureLoad( colorsTexture ), 0 ).x; const j = id; const x = j.modInt( size ); const y = j.div( size ); return textureLoad( colorsTexture, ivec2( x, y ) ).rgb; } ).setLayout( { name: 'getBatchingColor', type: 'vec3', inputs: [ { name: 'id', type: 'int' } ] } ); const color = getBatchingColor( indirectId ); varyingProperty( 'vec3', 'vBatchColor' ).assign( color ); } const bm = mat3( batchingMatrix ); positionLocal.assign( batchingMatrix.mul( positionLocal ) ); const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) ); const batchingNormal = bm.mul( transformedNormal ).xyz; normalLocal.assign( batchingNormal ); if ( builder.hasGeometryAttribute( 'tangent' ) ) { tangentLocal.mulAssign( bm ); } } } export default BatchNode; export const batch = /*@__PURE__*/ nodeProxy( BatchNode );