UNPKG

@spearwolf/twopoint5d

Version:

a library to create 2.5d realtime graphics and pixelart with three.js

90 lines 3.54 kB
import { MathUtils, ShaderMaterial, WebGLRenderer, } from 'three'; export class CustomChunksShaderMaterial extends ShaderMaterial { constructor() { super(...arguments); this.#uuid = MathUtils.generateUUID(); this.#chunksSerial = 0; this.replaceVertexShaderChunks = []; this.replaceFragmentShaderChunks = []; this.staticChunks = []; this.chunks = ((material) => new Proxy({}, { set(target, propKey, value, receiver) { if (!(propKey in target) || target[propKey] !== value) { ++material.#chunksSerial; material.needsUpdate = true; if (value != null) { Reflect.set(target, propKey, value, receiver); } else { delete target[propKey]; } return true; } return false; }, get(target, propKey) { if (propKey in target) { return target[propKey]; } return material.staticChunks.reduce((value, chunks) => (propKey in chunks ? chunks[propKey] : value), undefined); }, }))(this); this.logShadersToConsole = false; } #uuid; #chunksSerial; customProgramCacheKey() { return `${this.#uuid},${this.#chunksSerial}`; } addStaticChunks(chunks) { if (this.staticChunks.indexOf(chunks) === -1) { this.staticChunks.push(chunks); ++this.#chunksSerial; return () => this.removeStaticChunks(chunks); } return () => void 0; } removeStaticChunks(chunks) { const idx = this.staticChunks.indexOf(chunks); if (idx !== -1) { ++this.#chunksSerial; this.staticChunks.splice(idx, 1); } } #customChunks() { const chunks = {}; [...this.staticChunks, this.chunks].forEach((staticChunks) => { Object.entries(staticChunks).forEach(([key, value]) => { chunks[key] = value; }); }); return Object.entries(chunks); } onBeforeCompile(shader, _renderer) { const customChunks = this.#customChunks(); const replaceChunk = (shaderType) => (chunkName) => { shader[shaderType] = customChunks.reduce((source, [customChunkName, customChunkValue]) => source.replace(`#include <${customChunkName}>`, customChunkValue), shader[shaderType].replace(`#include <${chunkName}>`, this.chunks[chunkName] ?? '')); }; this.replaceVertexShaderChunks.forEach(replaceChunk('vertexShader')); this.replaceFragmentShaderChunks.forEach(replaceChunk('fragmentShader')); if (this.logShadersToConsole) { console.groupCollapsed(`CustomChunksShaderMaterial.onBeforeCompile(), name= ${this.name ?? this.uuid}`); console.group('vertexShader'); console.log(shader.vertexShader); console.groupEnd(); console.group('fragmentShader'); console.log(shader.fragmentShader); console.groupEnd(); console.groupEnd(); } } updateBoolDefine(name, value) { if (value) { Object.assign(this.defines, this.defines, { [name]: 1 }); } else if (this.defines) { delete this.defines[name]; } } } //# sourceMappingURL=CustomChunksShaderMaterial.js.map