import * as THREE from "three"; import vertexShader from "../../shaders/vertex.glsl?raw"; import fragmentShader from "../../shaders/fragment.glsl?raw"; export class PixelVoxelMesh { constructor(gridInfo, params, videoTexture) { this.gridInfo = gridInfo; this.params = params; this.dummy = new THREE.Object3D(); this.geometry = this.createGeometry(); this.material = this.createMaterial(videoTexture); this.mesh = new THREE.InstancedMesh(this.geometry, this.material, this.gridInfo.count); this.mesh.frustumCulled = false; } createGeometry() { return new THREE.BoxGeometry(this.gridInfo.cellSize, this.gridInfo.cellSize, this.gridInfo.cellSize); } createMaterial(videoTexture) { return new THREE.ShaderMaterial({ uniforms: { uMap: {value: videoTexture}, uGridDims: {value: new THREE.Vector2(this.gridInfo.cols, this.gridInfo.rows)}, uCubeSize: {value: new THREE.Vector2(this.gridInfo.cellSize, this.gridInfo.cellSize)}, uVoxelateProgress: {value: 0.0}, uRippleCenter: {value: new THREE.Vector2(0.5, 0.5)}, uEffectSpread: {value: this.params.effectSpread}, uEffectDepth: {value: this.params.effectDepth}, uHighlightIntensity: {value: this.params.highlightIntensity}, uHighlightColor: {value: new THREE.Color(this.params.highlightColor)}, uUseRandomDepth: {value: this.params.shape === "random" ? 1.0 : 0.0}, uOrganicMode: {value: this.params.organicMode ? 1.0 : 0.0}, uUsePixelate: {value: this.params.usePixelate ? 1.0 : 0.0}, uUseRGBShift: {value: this.params.useRGBShift ? 1.0 : 0.0}, }, side: THREE.DoubleSide, vertexShader, fragmentShader, }); } setMatrixAt(index, pos, rot) { this.dummy.position.set(pos.x, pos.y, pos.z); this.dummy.quaternion.set(rot.x, rot.y, rot.z, rot.w); this.dummy.scale.set(1, 1, 1); this.dummy.updateMatrix(); this.mesh.setMatrixAt(index, this.dummy.matrix); } setUniform(key, value) { if (this.material.uniforms[key]) { if (key === "uHighlightColor") { this.material.uniforms[key].value.set(value); } else { this.material.uniforms[key].value = value; } } } setRandomDepthAttribute(randomDepths) { this.geometry.setAttribute("aRandomDepth", new THREE.InstancedBufferAttribute(randomDepths, 1)); } requestMatrixUpdate() { this.mesh.instanceMatrix.needsUpdate = true; } dispose() { if (this.mesh) { this.mesh.geometry.dispose(); this.mesh.material.dispose(); } this.geometry = null; this.material = null; this.mesh = null; } }