UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

121 lines (115 loc) 3.95 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'; /** * This node implements the vertex shader logic which is required * when rendering 3D objects via batching. `BatchNode` must be used * with instances of {@link BatchedMesh}. * * @augments Node */ class BatchNode extends Node { static get type() { return 'BatchNode'; } /** * Constructs a new batch node. * * @param {BatchedMesh} batchMesh - A reference to batched mesh. */ constructor(batchMesh) { super('void'); /** * A reference to batched mesh. * * @type {BatchedMesh} */ this.batchMesh = batchMesh; /** * The batching index node. * * @type {?IndexNode} * @default null */ this.batchingIdNode = null; } /** * Setups the internal buffers and nodes and assigns the transformed vertex data * to predefined node variables for accumulation. That follows the same patterns * like with morph and skinning nodes. * * @param {NodeBuilder} builder - The current node builder. */ setup(builder) { if (this.batchingIdNode === null) { if (builder.getDrawIndex() === null) { this.batchingIdNode = instanceIndex; } else { this.batchingIdNode = drawIndex; } } const getIndirectIndex = Fn(([id]) => { const size = int(textureSize(textureLoad(this.batchMesh._indirectTexture), 0).x); const x = int(id).mod(size); const y = int(id).div(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 = int(textureSize(textureLoad(matricesTexture), 0).x); const j = float(indirectId).mul(4).toInt().toVar(); const x = j.mod(size); const y = j.div(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 = int(textureSize(textureLoad(colorsTexture), 0).x); const j = id; const x = j.mod(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; /** * TSL function for creating a batch node. * * @tsl * @function * @param {BatchedMesh} batchMesh - A reference to batched mesh. * @returns {BatchNode} */ export const batch = /*@__PURE__*/nodeProxy(BatchNode).setParameterLength(1);