@adatechnology/game-vfx-three 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/renderer.ts","../src/shaders/glow.ts","../src/shaders/noise.ts","../src/shaders/puff.ts","../src/shaders/spark.ts","../src/instanced.ts","../src/lights.ts","../src/canvas.ts","../src/marks.ts","../src/mesh-layer.ts","../src/screen-overlay.ts","../src/shaders/shock.ts","../src/shocks.ts","../src/shaders/sprite.ts","../src/sprites.ts","../src/shaders/workshop-sprite.ts","../src/workshop-layers.ts","../src/bench/module.ts","../src/bench/text.ts","../src/ground-patch.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport type { ControlValue } from '@adatechnology/game-contracts'\nimport { markKitOrigin } from '@adatechnology/game-contracts'\nimport { colorOfChunk, createVfx, hexToLinearRgb } from '@adatechnology/game-vfx'\nimport type { ScreenState, VfxWorld, WorkshopEngine } from '@adatechnology/game-vfx'\nimport { createChunkLayer, createGlowLayer, createPuffLayer, createSparkLayer } from './instanced'\nimport type { PuffUniforms } from './instanced'\nimport { createLightLayer } from './lights'\nimport { createMarkLayer } from './marks'\nimport { createMeshLayerProbes } from './mesh-layer'\nimport { createScreenOverlay } from './screen-overlay'\nimport { createShockLayer } from './shocks'\nimport { createSpriteLayer } from './sprites'\nimport type { ThreeLib, VfxRenderer, VfxRendererOptions } from './types'\nimport { createWorkshopLayers } from './workshop-layers'\nimport type { WorkshopLayers } from './workshop-layers'\n\nconst LAB_LIGHT_DIRECTION = [-14, 26, 12] as const\nconst SKY_COLOR = 0x6f7c92\nconst GROUND_COLOR = 0x2a241f\nconst LOD_BANDS: Readonly<Record<string, number | null>> = { auto: null, near: 1, middle: 0.5, far: 0.2 }\n/** The quality names the bench offers, as the Workshop's levels (0 keeps every particle). */\nconst QUALITY_LEVELS: Readonly<Record<string, number>> = { high: 0, medium: 1, low: 2 }\n/** `configure({ layer_<id>: false })` hides a layer of the renderer: `puffs`, `sparks`, `glows`, `debris`, `shock`, `sprites`. */\nexport const VFX_LAYERS = ['puffs', 'sparks', 'glows', 'debris', 'shock', 'sprites'] as const\nconst LAYER_PREFIX = 'layer_'\nconst SHAKE_REACH = 0.18\nconst SHAKE_FLOOR = 0.001\n\nfunction isWorld(value: unknown): value is VfxWorld {\n return typeof value === 'object' && value !== null && 'explosion' in value && typeof (value as VfxWorld).explosion === 'function'\n}\n\n/** The overlay shows the Lab's screen and the Workshop's together: the stronger of each field. */\nfunction mergeScreens(lab: ScreenState, workshop: ScreenState | undefined): ScreenState {\n if (!workshop) return lab\n const merged = { ...lab }\n for (const key of Object.keys(lab) as (keyof ScreenState)[]) merged[key] = Math.max(lab[key], workshop[key])\n return merged\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\n/** Draws a `VfxWorld`: the Lab's shaders, debris, shock, lights, marks and the screen overlay, and plays effects asked of it by id (`EffectSink`). */\nexport function createVfxRenderer(THREE: ThreeLib, options: VfxRendererOptions): VfxRenderer {\n const reducedMotion = options.reducedMotion ?? prefersReducedMotion()\n const requested = options.vfx\n const world = isWorld(requested) ? requested : createVfx({ profile: options.quality ?? 'medium', reducedMotion, ...requested })\n const pools = world.pools()\n // The probes of the last warm-up keep their materials until the next one: a program is destroyed when the last material that uses it is disposed (every solid particle disposes its own),\n // and a material that does not use lights keeps the program of the lights it was first drawn with, so each warm-up needs materials of its own.\n let anchors: { readonly meshes: THREE_NS.Mesh[]; readonly group: THREE_NS.Group } | undefined\n const releaseAnchors = (): void => {\n if (!anchors) return\n anchors.meshes[0]?.geometry.dispose()\n for (const mesh of anchors.meshes) (mesh.material as THREE_NS.Material).dispose()\n anchors = undefined\n }\n const root = markKitOrigin(new THREE.Group(), { owner: 'game-vfx-three', kind: 'effect' })\n options.scene.add(root)\n\n const direction = new THREE.Vector3(...(options.lightDirection ?? LAB_LIGHT_DIRECTION)).normalize()\n const sky = hexToLinearRgb(SKY_COLOR)\n const ground = hexToLinearRgb(GROUND_COLOR)\n const uniforms: PuffUniforms = {\n uLight: { value: direction },\n uSky: { value: new THREE.Vector3(sky[0] * 0.55, sky[1] * 0.55, sky[2] * 0.55) },\n uGround: { value: new THREE.Vector3(ground[0] * 0.6, ground[1] * 0.6, ground[2] * 0.6) },\n uGlowPos: { value: new THREE.Vector3() },\n uGlowCol: { value: new THREE.Vector3(1, 0.5, 0.2) },\n uGlowI: { value: 0 },\n uTime: { value: 0 },\n }\n const puffs = createPuffLayer(THREE, pools.puffs, uniforms)\n const sparks = createSparkLayer(THREE, pools.sparks)\n const glows = createGlowLayer(THREE, pools.glows)\n const rockGeometry = new THREE.DodecahedronGeometry(0.5, 0)\n const plateGeometry = new THREE.BoxGeometry(1, 1, 1)\n const chunks = createChunkLayer(THREE, pools.chunks, { rock: rockGeometry, plate: plateGeometry }, colorOfChunk)\n const shocks = createShockLayer(THREE, pools.shocks)\n const sprites = createSpriteLayer(THREE, world.sprites(), options.pointScale ?? 700)\n const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI)\n const marks = createMarkLayer(THREE, { ground: pools.ground, createCanvas: options.createCanvas, rockGeometry, plateGeometry })\n root.add(puffs.mesh, sparks.mesh, glows.mesh, chunks.rocks, chunks.plates, shocks.group, lights.group, sprites.additive, sprites.normal, marks.group)\n const stopMarks = world.onMarks((event) => marks.handle(event))\n const overlay = options.overlay ? createScreenOverlay(options.overlay) : undefined\n let drawCalls = 0\n let workshopLayers: WorkshopLayers | undefined\n let workshopEngine: WorkshopEngine | undefined\n const layerOn = new Map<string, boolean>()\n const layerObjects = (): Record<string, THREE_NS.Object3D[]> => ({\n puffs: [puffs.mesh],\n sparks: [sparks.mesh],\n glows: [glows.mesh],\n debris: [chunks.rocks, chunks.plates],\n shock: [shocks.group],\n sprites: [sprites.additive, sprites.normal, ...(workshopLayers ? [workshopLayers.group] : [])],\n })\n const applyLayers = (): void => {\n for (const [id, objects] of Object.entries(layerObjects())) for (const object of objects) object.visible = layerOn.get(id) !== false\n }\n const screenNow = (): ScreenState => mergeScreens(world.screen(), world.peekWorkshop()?.screen)\n let clock = 0\n const lastDrawn = { puffs: 0, sparks: 0, glows: 0, chunks: 0, shocks: 0, sprites: 0 }\n\n function followCamera(): void {\n const position = options.camera.position\n world.setCamera([position.x, position.y, position.z])\n }\n\n function syncAll(): void {\n lastDrawn.puffs = puffs.sync()\n lastDrawn.sparks = sparks.sync()\n lastDrawn.glows = glows.sync()\n lastDrawn.chunks = chunks.sync()\n lastDrawn.shocks = shocks.sync()\n lastDrawn.sprites = sprites.sync()\n lights.sync()\n const engine = world.peekWorkshop()\n if (engine && engine !== workshopEngine) {\n workshopLayers?.dispose()\n if (workshopLayers) root.remove(workshopLayers.group)\n workshopEngine = engine\n workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1)\n root.add(workshopLayers.group)\n applyLayers()\n }\n const workshopCalls = workshopLayers?.sync() ?? 0\n const glow = pools.lights.glow\n uniforms.uGlowPos.value.set(glow.x, glow.y, glow.z)\n uniforms.uGlowCol.value.set(glow.color[0], glow.color[1], glow.color[2])\n uniforms.uGlowI.value = glow.intensity\n drawCalls = Number(lastDrawn.puffs > 0) + Number(lastDrawn.sparks > 0) + Number(lastDrawn.glows > 0) + Number(chunks.rocks.count > 0) + Number(chunks.plates.count > 0) + Number(sprites.additive.geometry.drawRange.count > 0) + Number(sprites.normal.geometry.drawRange.count > 0) + lastDrawn.shocks * 2 + marks.count() + workshopCalls\n }\n\n return {\n world,\n play(request) {\n followCamera()\n const explosion = world.explosion(request.effect, request.point, {\n ...(request.direction ? { direction: request.direction } : {}),\n ...(request.seed !== undefined ? { seed: request.seed } : {}),\n ...(request.scale !== undefined ? { scale: request.scale } : {}),\n })\n if (explosion !== null) return explosion\n return world.play(request.effect, request.point, {\n ...(request.direction ? { direction: request.direction } : {}),\n ...(request.normal ? { normal: request.normal } : {}),\n ...(request.orientation ? { orientation: request.orientation } : {}),\n ...(request.seed !== undefined ? { seed: request.seed } : {}),\n ...(request.param !== undefined ? { param: request.param } : {}),\n ...(request.values ? { values: request.values } : {}),\n })\n },\n stop: (handle) => world.stop(handle),\n configure(settings: Readonly<Record<string, ControlValue>>) {\n const band = settings.lod_band\n if (typeof band === 'string' && band in LOD_BANDS) world.forceLod(LOD_BANDS[band] ?? null)\n const quality = settings.quality\n if (typeof quality === 'string' && quality in QUALITY_LEVELS) world.workshop().setQuality(QUALITY_LEVELS[quality] ?? 0)\n let layersChanged = false\n for (const [key, value] of Object.entries(settings)) {\n if (!key.startsWith(LAYER_PREFIX) || typeof value !== 'boolean') continue\n layerOn.set(key.slice(LAYER_PREFIX.length), value)\n layersChanged = true\n }\n if (layersChanged) applyLayers()\n },\n catalog: () => [...world.catalog(), ...world.effectIds()],\n update(dt) {\n clock += dt\n uniforms.uTime.value = clock\n followCamera()\n world.update(dt)\n marks.update(dt)\n syncAll()\n overlay?.update(screenNow())\n },\n warmUpProbes() {\n releaseAnchors()\n const meshes = createMeshLayerProbes(THREE)\n for (const mesh of meshes) mesh.frustumCulled = false\n const group = new THREE.Group()\n group.add(...meshes)\n anchors = { meshes, group }\n return { group, dispose: () => {} }\n },\n applyCamera() {\n const shake = screenNow().shake\n if (reducedMotion || !(shake > SHAKE_FLOOR)) return () => {}\n const camera = options.camera as THREE_NS.Camera\n const base = camera.position.clone()\n const reach = shake * SHAKE_REACH\n camera.position.x += Math.sin(clock * 71) * reach\n camera.position.y += Math.sin(clock * 53 + 1) * reach * 0.7\n camera.position.z += Math.sin(clock * 67 + 2) * reach\n return () => camera.position.copy(base)\n },\n stats() {\n const { lastBlast, ...counters } = world.stats()\n return { ...counters, last_puffs: lastBlast.puffs, last_sparks: lastBlast.sparks, last_chunks: lastBlast.chunks, last_lights: lastBlast.lights, drawCalls }\n },\n screen: screenNow,\n dispose() {\n releaseAnchors()\n stopMarks()\n overlay?.dispose()\n workshopLayers?.dispose()\n for (const layer of [puffs, sparks, glows, chunks, shocks, lights, marks, sprites]) layer.dispose()\n rockGeometry.dispose()\n plateGeometry.dispose()\n options.scene.remove(root)\n },\n }\n}\n","/** The additive halo (Lab L297-304), verbatim except for the r160 colour-space chunk. */\nexport const GLOW_VERTEX = `attribute vec4 aP;attribute vec4 aC;varying vec2 vU;varying vec4 vC;\nvoid main(){vec3 R=vec3(viewMatrix[0][0],viewMatrix[1][0],viewMatrix[2][0]);vec3 Up=vec3(viewMatrix[0][1],viewMatrix[1][1],viewMatrix[2][1]);\nvec3 wp=aP.xyz+(R*position.x+Up*position.y)*aP.w;vU=position.xy;vC=aC;gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.);}`\n\nexport const GLOW_FRAGMENT = `varying vec2 vU;varying vec4 vC;void main(){float r=dot(vU,vU);if(r>1.)discard;float f=exp(-r*4.2)-.015;gl_FragColor=vec4(vC.rgb*vC.a*max(f,0.),1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","/** The value noise the puff shader builds its dissolve from (Lab L116-122), verbatim. */\nexport const GL_NOISE = `\nfloat h3(vec3 p){p=fract(p*.3183099+.1);p*=17.0;return fract(p.x*p.y*p.z*(p.x+p.y+p.z));}\nfloat vn(vec3 x){vec3 i=floor(x),f=fract(x);f=f*f*(3.-2.*f);\n return mix(mix(mix(h3(i),h3(i+vec3(1,0,0)),f.x),mix(h3(i+vec3(0,1,0)),h3(i+vec3(1,1,0)),f.x),f.y),\n mix(mix(h3(i+vec3(0,0,1)),h3(i+vec3(1,0,1)),f.x),mix(h3(i+vec3(0,1,1)),h3(i+vec3(1,1,1)),f.x),f.y),f.z);}\n`\n","import { GL_NOISE } from './noise'\n\n/**\n * The puff shader of the Lab (L130-192), verbatim: a faceted icosahedron per puff, a five-band posterised heat ramp, a noise dissolve and banded light.\n * The only change is the r160 colour-space chunk: `encodings_fragment` (r128) is `colorspace_fragment` now.\n */\nexport const PUFF_VERTEX = `${GL_NOISE}\nattribute vec4 aP;attribute vec4 aD;attribute vec3 aC;\nvarying vec3 vWP;varying vec3 vL;varying vec4 vD;varying vec3 vC;\nvoid main(){\n vec3 p=position;\n float s=aD.z;\n float n=vn(p*1.6+vec3(s*11.0,s*7.0,s*3.0));\n p*=0.78+0.5*n;\n float a=s*6.2831;float c=cos(a),si=sin(a);p.xz=mat2(c,-si,si,c)*p.xz;\n vL=p;\n vec3 wp=aP.xyz+p*aP.w;\n vWP=wp;vD=aD;vC=aC;\n gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.0);\n}`\n\nexport const PUFF_FRAGMENT = `${GL_NOISE}\nuniform vec3 uLight;uniform vec3 uSky;uniform vec3 uGround;uniform vec3 uGlowPos;uniform vec3 uGlowCol;uniform float uGlowI;\nvarying vec3 vWP;varying vec3 vL;varying vec4 vD;varying vec3 vC;\nvec3 L(vec3 c){return pow(c,vec3(2.2));}\nvec3 ramp(float h){\n vec3 c0=L(vec3(.36,.07,.03)),c1=L(vec3(.76,.21,.1)),c2=L(vec3(1.,.54,.16)),c3=L(vec3(1.,.83,.42)),c4=L(vec3(1.,.96,.84));\n if(h<.25)return mix(c0,c1,h/.25);\n if(h<.5)return mix(c1,c2,(h-.25)/.25);\n if(h<.8)return mix(c2,c3,(h-.5)/.3);\n return mix(c3,c4,clamp((h-.8)/.4,0.,1.));\n}\nvoid main(){\n vec3 N=normalize(cross(dFdx(vWP),dFdy(vWP)));\n float age=vD.x,heat=vD.y,kind=vD.w;\n float n=vn(vL*2.4+vD.z*13.0);\n float diss=smoothstep(.5,1.,age);\n if(n<diss*1.08-.04)discard;\n float lam=max(dot(N,uLight),0.);\n float band=lam>.55?1.:lam>.15?.68:.42;\n vec3 col=vC*(vec3(.5,.56,.7)*band*1.05+vec3(.2,.19,.18)+uGround*(.4-.4*N.y));\n vec3 tg=uGlowPos-vWP;float dg=length(tg)+.001;\n float gi=uGlowI/(1.+dg*dg*.05)*(.3+.7*max(dot(N,tg/dg),0.));\n col+=uGlowCol*gi*vC*1.6;\n float h=heat*(.72+.56*n)+heat*(-N.y)*.18;\n if(h>.05){\n float hq=floor(h*5.+.5)/5.;\n vec3 fc=ramp(clamp(hq,0.,1.2))*(1.1+3.1*hq);\n col=mix(col,fc,smoothstep(.04,.2,h));\n }\n if(kind>2.5&&kind<3.5){col+=vec3(.02,.025,.03);}\n gl_FragColor=vec4(col,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","/** The streak shader of shrapnel, sparks and embers (Lab L255-275), verbatim except for the r160 colour-space chunk. */\nexport const SPARK_VERTEX = `\nattribute vec3 aPos;attribute vec3 aVel;attribute vec4 aE;varying vec2 vU;varying vec4 vE;\nvoid main(){\n float sp=length(aVel)+1e-4;vec3 d=aVel/sp;\n vec3 tc=normalize(cameraPosition-aPos);\n vec3 sd=normalize(cross(d,tc)+vec3(1e-5));\n float len=max(aE.y*2.5,min(sp*aE.z,2.2));\n vec3 wp=aPos+sd*position.x*aE.y-d*position.y*len;\n vU=position.xy;vE=aE;\n gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.);\n}`\n\nexport const SPARK_FRAGMENT = `\nvarying vec2 vU;varying vec4 vE;\nvoid main(){\n float age=vE.x,k=vE.w;\n float w=1.-abs(vU.x)*2.;w=w*w;\n float tail=1.-vU.y;\n vec3 c;\n if(k<.5){c=mix(vec3(4.,3.3,2.2),vec3(2.4,.7,.12),smoothstep(0.,.55,age));c=mix(c,vec3(.5,.06,.02),smoothstep(.55,1.,age));}\n else if(k<1.5){c=mix(vec3(1.6,1.6,1.6),vec3(.35,.35,.36),smoothstep(0.,.4,age));}\n else if(k<2.5){c=mix(vec3(5.,5.,6.),vec3(1.,1.3,2.),smoothstep(0.,.5,age));}\n else if(k<3.5){c=vec3(.9,1.2,1.4)*(1.-age);}\n else {c=mix(vec3(3.2,1.4,.3),vec3(1.2,.25,.05),age);}\n float a=w*(.35+.65*tail)*(1.-smoothstep(.75,1.,age));\n gl_FragColor=vec4(c*a,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","import type * as THREE_NS from 'three'\nimport type { Chunk, Glow, OrderedPool, Puff, Spark } from '@adatechnology/game-vfx'\nimport { GLOW_FRAGMENT, GLOW_VERTEX } from './shaders/glow'\nimport { PUFF_FRAGMENT, PUFF_VERTEX } from './shaders/puff'\nimport { SPARK_FRAGMENT, SPARK_VERTEX } from './shaders/spark'\nimport type { ThreeLib } from './types'\n\nexport interface DrawnLayer {\n readonly mesh: THREE_NS.Mesh\n /** Copies the pool into the instance buffers and answers how many are drawn. */\n sync(): number\n dispose(): void\n}\n\ntype Attribute = THREE_NS.InstancedBufferAttribute\n\nfunction dynamic(THREE: ThreeLib, array: Float32Array, size: number): Attribute {\n return new THREE.InstancedBufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n}\n\nexport interface PuffUniforms {\n uLight: { value: THREE_NS.Vector3 }\n uSky: { value: THREE_NS.Vector3 }\n uGround: { value: THREE_NS.Vector3 }\n uGlowPos: { value: THREE_NS.Vector3 }\n uGlowCol: { value: THREE_NS.Vector3 }\n uGlowI: { value: number }\n uTime: { value: number }\n}\n\nexport function createPuffLayer(THREE: ThreeLib, pool: OrderedPool<Puff>, uniforms: PuffUniforms): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.IcosahedronGeometry(1, 1).getAttribute('position'))\n const a = new Float32Array(capacity * 4)\n const d = new Float32Array(capacity * 4)\n const c = new Float32Array(capacity * 3)\n const attributes = [dynamic(THREE, a, 4), dynamic(THREE, d, 4), dynamic(THREE, c, 3)] as const\n geometry.setAttribute('aP', attributes[0])\n geometry.setAttribute('aD', attributes[1])\n geometry.setAttribute('aC', attributes[2])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ uniforms: uniforms as never, vertexShader: PUFF_VERTEX, fragmentShader: PUFF_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-puffs'\n mesh.frustumCulled = false\n return {\n mesh,\n sync() {\n let n = 0\n for (const p of pool.items) {\n a[n * 4] = p.x\n a[n * 4 + 1] = p.y\n a[n * 4 + 2] = p.z\n a[n * 4 + 3] = p.size\n d[n * 4] = p.age\n d[n * 4 + 1] = p.heat\n d[n * 4 + 2] = p.seed\n d[n * 4 + 3] = p.kind\n c[n * 3] = p.color[0]\n c[n * 3 + 1] = p.color[1]\n c[n * 3 + 2] = p.color[2]\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport function createSparkLayer(THREE: ThreeLib, pool: OrderedPool<Spark>): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute([-0.5, 0, 0, 0.5, 0, 0, 0.5, 1, 0, -0.5, 1, 0], 3))\n geometry.setIndex([0, 1, 2, 0, 2, 3])\n const position = new Float32Array(capacity * 3)\n const velocity = new Float32Array(capacity * 3)\n const extra = new Float32Array(capacity * 4)\n const attributes = [dynamic(THREE, position, 3), dynamic(THREE, velocity, 3), dynamic(THREE, extra, 4)] as const\n geometry.setAttribute('aPos', attributes[0])\n geometry.setAttribute('aVel', attributes[1])\n geometry.setAttribute('aE', attributes[2])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: SPARK_VERTEX, fragmentShader: SPARK_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-sparks'\n mesh.frustumCulled = false\n mesh.renderOrder = 5\n return {\n mesh,\n sync() {\n let n = 0\n for (const s of pool.items) {\n position[n * 3] = s.x\n position[n * 3 + 1] = s.y\n position[n * 3 + 2] = s.z\n velocity[n * 3] = s.vx\n velocity[n * 3 + 1] = s.vy\n velocity[n * 3 + 2] = s.vz\n extra[n * 4] = s.age\n extra[n * 4 + 1] = s.w\n extra[n * 4 + 2] = s.st\n extra[n * 4 + 3] = s.kind\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport function createGlowLayer(THREE: ThreeLib, pool: OrderedPool<Glow>): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0], 3))\n geometry.setIndex([0, 1, 2, 0, 2, 3])\n const where = new Float32Array(capacity * 4)\n const color = new Float32Array(capacity * 4)\n const attributes = [dynamic(THREE, where, 4), dynamic(THREE, color, 4)] as const\n geometry.setAttribute('aP', attributes[0])\n geometry.setAttribute('aC', attributes[1])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: GLOW_VERTEX, fragmentShader: GLOW_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-glows'\n mesh.frustumCulled = false\n mesh.renderOrder = 6\n return {\n mesh,\n sync() {\n let n = 0\n for (const g of pool.items) {\n where[n * 4] = g.outX\n where[n * 4 + 1] = g.outY\n where[n * 4 + 2] = g.outZ\n where[n * 4 + 3] = g.outSize\n color[n * 4] = g.color[0]\n color[n * 4 + 1] = g.color[1]\n color[n * 4 + 2] = g.color[2]\n color[n * 4 + 3] = g.outIntensity\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport interface ChunkLayer {\n readonly rocks: THREE_NS.InstancedMesh\n readonly plates: THREE_NS.InstancedMesh\n sync(): number\n dispose(): void\n}\n\nexport function createChunkLayer(THREE: ThreeLib, pool: OrderedPool<Chunk>, shapes: { rock: THREE_NS.BufferGeometry; plate: THREE_NS.BufferGeometry }, colorOf: (chunk: Chunk) => readonly [number, number, number]): ChunkLayer {\n const capacity = pool.capacity\n const rockMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.85, flatShading: true })\n const plateMaterial = rockMaterial.clone()\n const make = (geometry: THREE_NS.BufferGeometry, material: THREE_NS.Material): THREE_NS.InstancedMesh => {\n const mesh = new THREE.InstancedMesh(geometry, material, capacity)\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.castShadow = true\n mesh.receiveShadow = true\n mesh.frustumCulled = false\n mesh.count = 0\n mesh.setColorAt(0, new THREE.Color(1, 1, 1))\n return mesh\n }\n const rocks = make(shapes.rock, rockMaterial)\n const plates = make(shapes.plate, plateMaterial)\n const matrix = new THREE.Matrix4()\n const quaternion = new THREE.Quaternion()\n const euler = new THREE.Euler()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n return {\n rocks,\n plates,\n sync() {\n let rockCount = 0\n let plateCount = 0\n for (const chunk of pool.items) {\n euler.set(chunk.rx, chunk.ry, chunk.rz)\n quaternion.setFromEuler(euler)\n matrix.compose(position.set(chunk.x, chunk.y, chunk.z), quaternion, scale.set(chunk.sx, chunk.sy, chunk.sz))\n const mesh = chunk.plate ? plates : rocks\n const index = chunk.plate ? plateCount++ : rockCount++\n mesh.setMatrixAt(index, matrix)\n const color = colorOf(chunk)\n const colors = mesh.instanceColor!.array as Float32Array\n colors[index * 3] = color[0]\n colors[index * 3 + 1] = color[1]\n colors[index * 3 + 2] = color[2]\n }\n rocks.count = rockCount\n plates.count = plateCount\n for (const mesh of [rocks, plates]) {\n mesh.instanceMatrix.needsUpdate = true\n mesh.instanceColor!.needsUpdate = true\n }\n return rockCount + plateCount\n },\n dispose() {\n rockMaterial.dispose()\n plateMaterial.dispose()\n rocks.dispose()\n plates.dispose()\n },\n }\n}\n","import type * as THREE_NS from 'three'\nimport type { LightPool } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nexport interface LightLayer {\n readonly group: THREE_NS.Group\n /** Moves and lights the 4 blast lights and 2 fire lights from the pool; answers how many are lit. */\n sync(): number\n dispose(): void\n}\n\n/** The Lab's light pool as real point lights (L349-365). Colours are the raw numbers the Lab used, not converted from sRGB. */\nexport function createLightLayer(THREE: ThreeLib, pool: LightPool, scale: number): LightLayer {\n const group = new THREE.Group()\n const blast = pool.blast.map(() => {\n const light = new THREE.PointLight(0xffa050, 0, 30, 2)\n light.position.set(0, -50, 0)\n group.add(light)\n return light\n })\n const fire = pool.fire.map(() => {\n const light = new THREE.PointLight(0xff7a2a, 0, 16, 2)\n light.position.set(0, -50, 0)\n group.add(light)\n return light\n })\n return {\n group,\n sync() {\n let lit = 0\n pool.blast.forEach((entry, index) => {\n const light = blast[index]!\n light.position.set(entry.x, entry.y, entry.z)\n light.distance = entry.distance\n light.color.setRGB(entry.color[0], entry.color[1], entry.color[2], THREE.LinearSRGBColorSpace)\n light.intensity = entry.intensity * scale\n if (entry.intensity > 0.05) lit++\n })\n pool.fire.forEach((entry, index) => {\n const light = fire[index]!\n light.position.set(entry.x, entry.y, entry.z)\n light.distance = entry.distance\n light.intensity = entry.intensity * scale\n if (entry.intensity > 0.05) lit++\n })\n return lit\n },\n dispose() {\n for (const light of [...blast, ...fire]) light.dispose()\n },\n }\n}\n","import { lehmer } from '@adatechnology/game-vfx'\nimport type { RandomStream } from '@adatechnology/game-vfx'\nimport type { CanvasContextLike, CanvasLike, ThreeLib } from './types'\nimport type * as THREE_NS from 'three'\n\nconst SCORCH_SEED = 5\nconst TEXTURE_SIZE = 256\nconst FULL_TURN = Math.PI * 2\n\n/** Where a texture draws its randomness: the Lab seeded the page with 5 before it made the marks, so the textures do not touch the effect's own stream. */\nexport function createTextureStream(): RandomStream {\n return lehmer(SCORCH_SEED)\n}\n\n/** Without a DOM (a server, a test in Node) there is nothing to draw on: the textures stay blank and the marks still lay down their geometry. */\nfunction blankCanvas(): CanvasLike {\n return { width: 0, height: 0, getContext: () => null }\n}\n\nfunction defaultCanvas(): CanvasLike {\n if (typeof document === 'undefined') return blankCanvas()\n return document.createElement('canvas') as unknown as CanvasLike\n}\n\nfunction paint(createCanvas: () => CanvasLike, draw: (context: CanvasContextLike, size: number) => void): CanvasLike {\n const canvas = createCanvas()\n canvas.width = TEXTURE_SIZE\n canvas.height = TEXTURE_SIZE\n const context = canvas.getContext('2d')\n if (context) draw(context, TEXTURE_SIZE)\n return canvas\n}\n\nfunction drawScorch(context: CanvasContextLike, size: number, random: RandomStream): void {\n context.clearRect(0, 0, size, size)\n const center = size / 2\n for (let ray = 0; ray < 60; ray++) {\n const angle = random.next() * FULL_TURN\n const length = center * (0.55 + random.next() * 0.42)\n context.strokeStyle = `rgba(8,6,5,${0.25 + random.next() * 0.35})`\n context.lineWidth = 2 + random.next() * 6\n context.beginPath()\n context.moveTo(center, center)\n context.lineTo(center + Math.cos(angle) * length, center + Math.sin(angle) * length)\n context.stroke()\n }\n const gradient = context.createRadialGradient(center, center, 0, center, center, center * 0.72)\n gradient.addColorStop(0, 'rgba(4,3,3,.96)')\n gradient.addColorStop(0.55, 'rgba(10,8,7,.85)')\n gradient.addColorStop(1, 'rgba(14,11,9,0)')\n context.fillStyle = gradient\n context.fillRect(0, 0, size, size)\n for (let spot = 0; spot < 26; spot++) {\n context.fillStyle = `rgba(60,40,28,${0.15 + random.next() * 0.2})`\n context.beginPath()\n context.arc(center + random.between(-0.4, 0.4) * center, center + random.between(-0.4, 0.4) * center, 2 + random.next() * 7, 0, 7)\n context.fill()\n }\n}\n\nfunction drawDirt(context: CanvasContextLike, size: number, random: RandomStream): void {\n const center = size / 2\n context.clearRect(0, 0, size, size)\n const gradient = context.createRadialGradient(center, center, 0, center, center, center)\n gradient.addColorStop(0, 'rgba(92,72,52,1)')\n gradient.addColorStop(0.6, 'rgba(118,92,64,1)')\n gradient.addColorStop(0.82, 'rgba(80,64,50,.8)')\n gradient.addColorStop(1, 'rgba(40,36,34,0)')\n context.fillStyle = gradient\n context.fillRect(0, 0, size, size)\n for (let speck = 0; speck < 420; speck++) {\n const angle = random.next() * FULL_TURN\n const distance = Math.sqrt(random.next()) * center * 0.8\n context.fillStyle = random.next() < 0.5 ? 'rgba(40,30,22,.5)' : 'rgba(160,132,96,.5)'\n context.beginPath()\n context.arc(center + Math.cos(angle) * distance, center + Math.sin(angle) * distance, 1 + random.next() * 3.5, 0, 7)\n context.fill()\n }\n}\n\nexport interface MarkTextures {\n readonly scorch: readonly THREE_NS.CanvasTexture[]\n readonly dirt: THREE_NS.CanvasTexture\n}\n\n/** The three scorch textures and the dirt one (L443-457), drawn once from a stream seeded like the page's. */\nexport function createMarkTextures(THREE: ThreeLib, createCanvas: (() => CanvasLike) | undefined): MarkTextures {\n const make = createCanvas ?? defaultCanvas\n const random = createTextureStream()\n const texture = (canvas: CanvasLike): THREE_NS.CanvasTexture => {\n const result = new THREE.CanvasTexture(canvas as unknown as HTMLCanvasElement)\n result.colorSpace = THREE.SRGBColorSpace\n result.anisotropy = 4\n return result\n }\n const scorch = [0, 1, 2].map(() => texture(paint(make, (context, size) => drawScorch(context, size, random))))\n const dirt = texture(paint(make, (context, size) => drawDirt(context, size, random)))\n return { scorch, dirt }\n}\n","import type * as THREE_NS from 'three'\nimport type { BloodMark, DirtMark, GroundField, Mark, MarkEvent, RockMark, ScorchMark } from '@adatechnology/game-vfx'\nimport { createMarkTextures } from './canvas'\nimport type { MarkTextures } from './canvas'\nimport type { CanvasLike, ThreeLib } from './types'\n\nconst MAX_CONFORM_STEPS = 48\nconst MIN_CONFORM_STEPS = 16\nconst BLOOD_GROW_RATE = 1.2\n\ninterface BloodDrawn {\n readonly mesh: THREE_NS.Mesh\n readonly scaleX: number\n readonly scaleZ: number\n age: number\n}\n\nexport interface MarkLayer {\n readonly group: THREE_NS.Group\n /** The shared rock and plate shapes, so the debris and the rim rocks use the same geometry. */\n handle(event: MarkEvent): void\n update(dt: number): void\n /** The meshes in the group right now. */\n count(): number\n dispose(): void\n}\n\nexport interface MarkLayerOptions {\n readonly ground: GroundField | undefined\n readonly createCanvas: (() => CanvasLike) | undefined\n readonly rockGeometry: THREE_NS.BufferGeometry\n readonly plateGeometry: THREE_NS.BufferGeometry\n}\n\n/**\n * The scorch, dirt, rim rocks and blood of the Lab as meshes (L443-476). A scorch or dirt mesh follows the ground as it was the moment the mark was\n * made (`conform`), so the renderer builds it from the mark event, not later.\n */\nexport function createMarkLayer(THREE: ThreeLib, options: MarkLayerOptions): MarkLayer {\n const group = new THREE.Group()\n const textures: MarkTextures = createMarkTextures(THREE, options.createCanvas)\n const owned: { dispose(): void }[] = [...textures.scorch, textures.dirt]\n const scorchMaterials = textures.scorch.map((map) => {\n const material = new THREE.MeshStandardMaterial({ map, transparent: true, depthWrite: false, roughness: 1, polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -2 })\n owned.push(material)\n return material\n })\n const dirtMaterial = new THREE.MeshStandardMaterial({\n map: textures.dirt, transparent: true, depthWrite: false, roughness: 1, flatShading: true, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: -1,\n })\n owned.push(dirtMaterial)\n const bloodMaterial = new THREE.MeshStandardMaterial({ color: 0x5c0a0a, roughness: 0.15, metalness: 0.1, polygonOffset: true, polygonOffsetFactor: -3, polygonOffsetUnits: -3 })\n const bloodGeometry = new THREE.CircleGeometry(0.5, 9).rotateX(-Math.PI / 2)\n owned.push(bloodMaterial, bloodGeometry)\n const rockMaterials = new Map<number, THREE_NS.MeshStandardMaterial>()\n const blood: BloodDrawn[] = []\n let meshCount = 0\n\n function rockMaterial(color: number): THREE_NS.MeshStandardMaterial {\n let material = rockMaterials.get(color)\n if (!material) {\n material = new THREE.MeshStandardMaterial({ color, roughness: 0.9, metalness: 0, flatShading: true })\n rockMaterials.set(color, material)\n owned.push(material)\n }\n return material\n }\n\n function conform(mark: ScorchMark | DirtMark, material: THREE_NS.Material): THREE_NS.Mesh {\n const radius = mark.radius\n const steps = Math.max(MIN_CONFORM_STEPS, Math.min(MAX_CONFORM_STEPS, Math.round(radius * 8)))\n const geometry = new THREE.PlaneGeometry(2, 2, steps, steps).rotateX(-Math.PI / 2)\n const position = geometry.attributes.position!\n const cos = Math.cos(mark.rotation)\n const sin = Math.sin(mark.rotation)\n for (let index = 0; index < position.count; index++) {\n const localX = position.getX(index) * radius\n const localZ = position.getZ(index) * radius\n const worldX = mark.x + localX * cos - localZ * sin\n const worldZ = mark.z + localX * sin + localZ * cos\n position.setXYZ(index, worldX, (options.ground?.heightAt(worldX, worldZ) ?? 0) + mark.lift, worldZ)\n }\n geometry.computeVertexNormals()\n const mesh = new THREE.Mesh(geometry, material as THREE_NS.MeshStandardMaterial)\n mesh.receiveShadow = true\n return mesh\n }\n\n function addRock(mark: RockMark): THREE_NS.Mesh {\n const mesh = new THREE.Mesh(mark.plate ? options.plateGeometry : options.rockGeometry, rockMaterial(mark.color))\n mesh.position.set(mark.x, mark.y, mark.z)\n mesh.scale.set(mark.scale[0], mark.scale[1], mark.scale[2])\n mesh.rotation.set(mark.rotation[0], mark.rotation[1], mark.rotation[2])\n mesh.castShadow = true\n mesh.receiveShadow = true\n return mesh\n }\n\n function addBlood(mark: BloodMark): THREE_NS.Mesh {\n const mesh = new THREE.Mesh(bloodGeometry, bloodMaterial)\n mesh.position.set(mark.x, mark.y, mark.z)\n mesh.scale.set(mark.scaleX, 1, mark.scaleZ)\n mesh.rotation.y = mark.rotation\n mesh.receiveShadow = true\n mesh.scale.multiplyScalar(0.05)\n blood.push({ mesh, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 })\n return mesh\n }\n\n function build(mark: Mark): THREE_NS.Mesh {\n if (mark.kind === 'scorch') return conform(mark, scorchMaterials[mark.variant]!)\n if (mark.kind === 'dirt') return conform(mark, dirtMaterial)\n if (mark.kind === 'rock') return addRock(mark)\n return addBlood(mark)\n }\n\n function clearMeshes(): void {\n for (const child of [...group.children]) {\n group.remove(child)\n const geometry = (child as THREE_NS.Mesh).geometry\n if (geometry !== options.rockGeometry && geometry !== options.plateGeometry && geometry !== bloodGeometry) geometry.dispose()\n }\n blood.length = 0\n meshCount = 0\n }\n\n return {\n group,\n handle(event) {\n if (event.type === 'clear') {\n clearMeshes()\n return\n }\n group.add(build(event.mark))\n meshCount++\n },\n update(dt) {\n for (const drawn of blood) {\n if (drawn.age > 1) continue\n drawn.age += dt * BLOOD_GROW_RATE\n const ease = 1 - Math.pow(1 - Math.min(1, drawn.age), 2.5)\n drawn.mesh.scale.set(drawn.scaleX * Math.max(0.05, ease), 1, drawn.scaleZ * Math.max(0.05, ease))\n }\n },\n count: () => meshCount,\n dispose() {\n clearMeshes()\n for (const item of owned) item.dispose()\n },\n }\n}\n","import type * as THREE_NS from 'three'\nimport type { MeshParticle, MeshPool } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nconst SPHERE_DEFAULT_WIDTH = 8\nconst SPHERE_DEFAULT_HEIGHT = 6\n\nexport interface MeshLayer {\n readonly group: THREE_NS.Group\n /** Puts a mesh on every live solid particle and takes it off the ones that ended; answers how many are drawn. */\n sync(): number\n dispose(): void\n}\n\nfunction geometryOf(THREE: ThreeLib, particle: MeshParticle): THREE_NS.BufferGeometry {\n switch (particle.shape) {\n case 'cone': return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || undefined, particle.segments2 || 1, false)\n case 'cone_open': return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || undefined, particle.segments2 || 1, true)\n case 'sphere': return new THREE.SphereGeometry(particle.radius, particle.segments || SPHERE_DEFAULT_WIDTH, particle.segments2 || SPHERE_DEFAULT_HEIGHT)\n case 'icosahedron': return new THREE.IcosahedronGeometry(particle.radius, particle.segments)\n }\n}\n\n/** The materials the gallery gives these: a flat, translucent colour (added to what is behind it for a flash), or a rough grey that the scene's lights shade (smoke). */\nfunction materialOf(THREE: ThreeLib, particle: Pick<MeshParticle, 'lit' | 'color' | 'opacity' | 'additive'>): THREE_NS.Material {\n if (particle.lit) return new THREE.MeshStandardMaterial({ color: particle.color, roughness: 1, metalness: 0, transparent: true, opacity: particle.opacity, depthWrite: false })\n return new THREE.MeshBasicMaterial({ color: particle.color, transparent: true, opacity: particle.opacity, depthWrite: false, ...(particle.additive ? { blending: THREE.AdditiveBlending } : {}) })\n}\n\n/** One throwaway mesh per material the layer draws with (lit smoke, flat, additive flash), for a host to compile their shader programs before the first effect needs them. */\nexport function createMeshLayerProbes(THREE: ThreeLib): THREE_NS.Mesh[] {\n const geometry = new THREE.BoxGeometry(0.001, 0.001, 0.001)\n return [{ lit: true, additive: false }, { lit: false, additive: false }, { lit: false, additive: true }].map(\n (kind) => new THREE.Mesh(geometry, materialOf(THREE, { ...kind, color: 0x808080, opacity: 0.5 })),\n )\n}\n\n/**\n * The Workshop's solid particles (`MeshPool`) as three.js meshes, one each, like the gallery: the geometry and the material belong to the mesh and go with it. A mesh sits at\n * the group's point plus the group's turn applied to the piece's place times the scale, turned by the group's turn and then by the piece's own Euler angles.\n */\nexport function createMeshLayer(THREE: ThreeLib, pool: MeshPool): MeshLayer {\n const group = new THREE.Group()\n group.name = 'workshop-meshes'\n const drawn = new Map<number, THREE_NS.Mesh>()\n const frame = new THREE.Quaternion()\n const euler = new THREE.Euler()\n const turn = new THREE.Quaternion()\n const offset = new THREE.Vector3()\n\n function release(mesh: THREE_NS.Mesh): void {\n mesh.removeFromParent()\n mesh.geometry.dispose()\n ;(mesh.material as THREE_NS.Material).dispose()\n }\n\n return {\n group,\n sync() {\n const live = new Set<number>()\n for (const particle of pool.particles) {\n live.add(particle.id)\n let mesh = drawn.get(particle.id)\n if (!mesh) {\n mesh = new THREE.Mesh(geometryOf(THREE, particle), materialOf(THREE, particle))\n mesh.frustumCulled = false\n mesh.renderOrder = particle.additive ? 5 : 3\n drawn.set(particle.id, mesh)\n group.add(mesh)\n }\n frame.set(particle.frame[0], particle.frame[1], particle.frame[2], particle.frame[3])\n offset.set(particle.at[0], particle.at[1], particle.at[2]).multiplyScalar(particle.scale).applyQuaternion(frame)\n mesh.position.set(particle.x + offset.x, particle.y + offset.y, particle.z + offset.z)\n turn.setFromEuler(euler.set(particle.rx, particle.ry, particle.rz))\n mesh.quaternion.copy(frame).multiply(turn)\n mesh.scale.setScalar(particle.scale)\n ;(mesh.material as THREE_NS.Material).opacity = particle.opacity\n }\n for (const [id, mesh] of drawn) {\n if (live.has(id)) continue\n release(mesh)\n drawn.delete(id)\n }\n return pool.count\n },\n dispose() {\n for (const mesh of drawn.values()) release(mesh)\n drawn.clear()\n group.removeFromParent()\n },\n }\n}\n","import type { ScreenState } from '@adatechnology/game-vfx'\n\nexport interface ScreenOverlay {\n update(state: Readonly<ScreenState>): void\n dispose(): void\n}\n\nconst clamp = (value: number, min: number, max: number): number => (value < min ? min : value > max ? max : value)\n\nfunction layer(container: HTMLElement, name: string, blend?: string): HTMLDivElement {\n const element = container.ownerDocument.createElement('div')\n element.dataset.vfxOverlay = name\n Object.assign(element.style, { position: 'absolute', inset: '0', pointerEvents: 'none', opacity: '0' })\n if (blend) element.style.mixBlendMode = blend\n container.appendChild(element)\n return element\n}\n\n/**\n * The screen effects as overlays inside the host's container: the Lab's white flash (L1087, `mix-blend-mode: screen`) and the Workshop's white,\n * red edge, the two sides and the gas tint (W356-366), with the same colours. Nothing is drawn while the state is at rest.\n */\nexport function createScreenOverlay(container: HTMLElement): ScreenOverlay {\n const flash = layer(container, 'flash', 'screen')\n flash.style.background = '#fff'\n const white = layer(container, 'white')\n const red = layer(container, 'red')\n const sides = layer(container, 'sides')\n const gas = layer(container, 'gas')\n const elements = [flash, white, red, sides, gas]\n return {\n update(state) {\n flash.style.opacity = clamp(state.flash, 0, 1).toFixed(3)\n white.style.opacity = '1'\n white.style.background = `rgba(235,240,255,${clamp(state.white, 0, 1).toFixed(2)})`\n red.style.opacity = '1'\n red.style.background = `radial-gradient(ellipse at center, transparent 40%, rgba(170,16,12,${(clamp(state.red, 0, 1) * 0.85).toFixed(2)}) 100%)`\n sides.style.opacity = '1'\n sides.style.background = `linear-gradient(90deg, rgba(190,20,14,${(state.directionLeft * 0.8).toFixed(2)}) 0%, transparent 35%, transparent 65%, rgba(190,20,14,${(state.directionRight * 0.8).toFixed(2)}) 100%)`\n gas.style.opacity = '1'\n gas.style.background = state.gas > 0.01 ? `rgba(90,130,40,${(state.gas * 0.55).toFixed(2)})` : 'transparent'\n },\n dispose() {\n for (const element of elements) element.remove()\n },\n }\n}\n","/** The shock shell (fresnel edge, Lab L322-325) and the dust ring on the ground (L326-333), verbatim except for the r160 colour-space chunk. */\nexport const SHELL_VERTEX = `varying vec3 vN;varying vec3 vV;void main(){vec4 wp=modelMatrix*vec4(position,1.);vN=normalize(mat3(modelMatrix)*normal);vV=normalize(cameraPosition-wp.xyz);gl_Position=projectionMatrix*viewMatrix*wp;}`\n\nexport const SHELL_FRAGMENT = `uniform float uA;varying vec3 vN;varying vec3 vV;void main(){float f=1.-abs(dot(vN,vV));f=pow(f,5.);gl_FragColor=vec4(vec3(1.,.93,.82)*f*uA*.45,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n\nexport const RING_VERTEX = `varying vec2 vU;void main(){vU=position.xz;gl_Position=projectionMatrix*viewMatrix*modelMatrix*vec4(position,1.);}`\n\nexport const RING_FRAGMENT = `uniform float uA;uniform float uW;uniform vec3 uC;varying vec2 vU;\n float h(vec2 p){return fract(sin(dot(p,vec2(12.9898,78.233)))*43758.5453);}\n void main(){float r=length(vU);float b=smoothstep(1.,1.-uW,r)*smoothstep(1.-uW*3.5,1.-uW,r);float a=atan(vU.y,vU.x);float n=.7+.3*h(vec2(floor(a*14.),1.));gl_FragColor=vec4(uC,b*uA*n);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","import type * as THREE_NS from 'three'\nimport type { OrderedPool, Shock } from '@adatechnology/game-vfx'\nimport { RING_FRAGMENT, RING_VERTEX, SHELL_FRAGMENT, SHELL_VERTEX } from './shaders/shock'\nimport type { ThreeLib } from './types'\n\ninterface Pair {\n readonly shell: THREE_NS.Mesh\n readonly ring: THREE_NS.Mesh\n readonly shellAlpha: { value: number }\n readonly ringAlpha: { value: number }\n}\n\nconst RING_HEIGHT = 0.05\n\nexport interface ShockLayer {\n readonly group: THREE_NS.Group\n sync(): number\n dispose(): void\n}\n\n/** The shock shell and ground ring of each live shock (L319-348): one pair of meshes per slot, shown while the slot has a shock. */\nexport function createShockLayer(THREE: ThreeLib, pool: OrderedPool<Shock>): ShockLayer {\n const group = new THREE.Group()\n const shellGeometry = new THREE.SphereGeometry(1, 28, 18)\n const ringGeometry = new THREE.PlaneGeometry(2, 2).rotateX(-Math.PI / 2)\n const pairs: Pair[] = []\n\n function makePair(): Pair {\n const shellAlpha = { value: 0 }\n const ringAlpha = { value: 0 }\n const shellMaterial = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, uniforms: { uA: shellAlpha }, vertexShader: SHELL_VERTEX, fragmentShader: SHELL_FRAGMENT })\n const ringMaterial = new THREE.ShaderMaterial({\n transparent: true, depthWrite: false, uniforms: { uA: ringAlpha, uW: { value: 0.12 }, uC: { value: new THREE.Color(0.55, 0.5, 0.44) } }, vertexShader: RING_VERTEX, fragmentShader: RING_FRAGMENT,\n })\n const shell = new THREE.Mesh(shellGeometry, shellMaterial)\n shell.renderOrder = 4\n const ring = new THREE.Mesh(ringGeometry, ringMaterial)\n ring.renderOrder = 3\n group.add(shell, ring)\n return { shell, ring, shellAlpha, ringAlpha }\n }\n\n return {\n group,\n sync() {\n const shocks = pool.items\n for (let index = 0; index < shocks.length; index++) {\n const pair = (pairs[index] ??= makePair())\n const shock = shocks[index]!\n pair.shell.visible = pair.ring.visible = true\n pair.shell.position.set(shock.x, shock.y, shock.z)\n pair.shell.scale.setScalar(shock.shellScale)\n pair.shellAlpha.value = shock.shellAlpha\n pair.ring.position.set(shock.x, RING_HEIGHT, shock.z)\n pair.ring.scale.setScalar(shock.ringScale)\n pair.ringAlpha.value = shock.ringAlpha\n }\n for (let index = shocks.length; index < pairs.length; index++) pairs[index]!.shell.visible = pairs[index]!.ring.visible = false\n return shocks.length\n },\n dispose() {\n for (const pair of pairs) {\n ;(pair.shell.material as THREE_NS.Material).dispose()\n ;(pair.ring.material as THREE_NS.Material).dispose()\n }\n shellGeometry.dispose()\n ringGeometry.dispose()\n },\n }\n}\n","/** The soft round point sprite of the game's sprite kinds (moved verbatim from the destruction renderer's particles). */\nexport const SPRITE_VERTEX = `\nuniform float uScale;\nattribute float size;\nattribute float alpha;\nattribute vec3 pcolor;\nvarying float vAlpha;\nvarying vec3 vColor;\nvoid main() {\n vAlpha = alpha;\n vColor = pcolor;\n vec4 mv = modelViewMatrix * vec4(position, 1.0);\n gl_PointSize = min(size * uScale / max(0.1, -mv.z), 256.0);\n gl_Position = projectionMatrix * mv;\n}`\n\nexport const SPRITE_FRAGMENT = `\nvarying float vAlpha;\nvarying vec3 vColor;\nvoid main() {\n float d = length(gl_PointCoord - vec2(0.5)) * 2.0;\n float a = (1.0 - smoothstep(0.35, 1.0, d)) * vAlpha;\n if (a < 0.004) discard;\n gl_FragColor = vec4(vColor, a);\n}`\n","import type * as THREE_NS from 'three'\nimport type { SpriteKindPool, SpriteKindSystem } from '@adatechnology/game-vfx'\nimport { SPRITE_FRAGMENT, SPRITE_VERTEX } from './shaders/sprite'\nimport type { ThreeLib } from './types'\n\nexport interface SpriteLayer {\n readonly additive: THREE_NS.Points\n readonly normal: THREE_NS.Points\n /** Tells the GPU what changed and answers how many sprites are drawn. */\n sync(): number\n dispose(): void\n}\n\ninterface Drawn {\n readonly points: THREE_NS.Points\n sync(): number\n dispose(): void\n}\n\nfunction drawPool(THREE: ThreeLib, pool: SpriteKindPool, additive: boolean, pointScale: number): Drawn {\n const geometry = new THREE.BufferGeometry()\n const attributes: [string, Float32Array, number][] = [['position', pool.position, 3], ['pcolor', pool.color, 3], ['alpha', pool.alpha, 1], ['size', pool.size, 1]]\n const buffers = attributes.map(([name, array, size]) => {\n const attribute = new THREE.BufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute(name, attribute)\n return attribute\n })\n geometry.setDrawRange(0, 0)\n const material = new THREE.ShaderMaterial({\n uniforms: { uScale: { value: pointScale } },\n vertexShader: SPRITE_VERTEX,\n fragmentShader: SPRITE_FRAGMENT,\n transparent: true,\n depthWrite: false,\n blending: additive ? THREE.AdditiveBlending : THREE.NormalBlending,\n })\n const points = new THREE.Points(geometry, material)\n points.frustumCulled = false\n points.name = additive ? 'vfx-sprites-additive' : 'vfx-sprites'\n points.renderOrder = additive ? 11 : 10\n return {\n points,\n sync() {\n geometry.setDrawRange(0, pool.drawCount)\n for (const buffer of buffers) buffer.needsUpdate = true\n return pool.drawCount\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** Draws the game's sprite kinds (debris, sparks, smoke, steam, drips...) as two soft point layers, additive and normal. */\nexport function createSpriteLayer(THREE: ThreeLib, system: SpriteKindSystem, pointScale: number): SpriteLayer {\n const additive = drawPool(THREE, system.additive, true, pointScale)\n const normal = drawPool(THREE, system.normal, false, pointScale)\n return {\n additive: additive.points,\n normal: normal.points,\n sync: () => additive.sync() + normal.sync(),\n dispose() {\n additive.dispose()\n normal.dispose()\n },\n }\n}\n","/** The Workshop's soft point sprite (W168-171): the size is in metres, clamped to 1..512 px; `uSoft` is 1 for the soft (normal blend) pool. */\nexport const WORKSHOP_SPRITE_VERTEX = `attribute float size;attribute float alpha;attribute vec3 pcol;varying vec3 vC;varying float vA;uniform float uScale;\nvoid main(){vC=pcol;vA=alpha;vec4 mv=modelViewMatrix*vec4(position,1.);gl_PointSize=clamp(size*uScale/-mv.z,1.,512.);gl_Position=projectionMatrix*mv;}`\n\nexport const WORKSHOP_SPRITE_FRAGMENT = `uniform float uSoft;varying vec3 vC;varying float vA;\nvoid main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a=mix(smoothstep(1.,.78,r),pow(1.-r,1.5),uSoft);gl_FragColor=vec4(vC,vA*a);}`\n","import type * as THREE_NS from 'three'\nimport type { Decal, WorkshopEngine } from '@adatechnology/game-vfx'\nimport { createMeshLayer } from './mesh-layer'\nimport { WORKSHOP_SPRITE_FRAGMENT, WORKSHOP_SPRITE_VERTEX } from './shaders/workshop-sprite'\nimport type { ThreeLib } from './types'\n\nconst DEBRIS_CAPACITY = 500\nconst DECAL_CAPACITY = 400\nconst RING_CAPACITY = 120\nconst RIPPLE_SEGMENTS = 12\nconst FADE_SECONDS = 0.5\nconst FIRE_LIGHT_COLOR = 0xff7a2a\nconst FIRE_LIGHT_DISTANCE = 14\nconst GLOSS_DRIED_AT = 0.85\nconst BROWN = 0x2a1610\nconst GROUND_COLOR = 0x888888\nconst FUEL_DRIED = 0x888888\n\nexport interface WorkshopLayers {\n readonly group: THREE_NS.Group\n /** Copies the pools into the draw buffers; answers how many draw calls have something to draw. */\n sync(): number\n dispose(): void\n}\n\ninterface Drawn {\n readonly object: THREE_NS.Object3D\n sync(): boolean\n dispose(): void\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => (v < lo ? lo : v > hi ? hi : v)\n\nfunction spriteLayer(THREE: ThreeLib, pool: WorkshopEngine['add'], additive: boolean, soft: number, scale: number): Drawn {\n const geometry = new THREE.BufferGeometry()\n const arrays: [string, Float32Array, number][] = [['position', pool.position, 3], ['pcol', pool.color, 3], ['size', pool.size, 1], ['alpha', pool.alpha, 1]]\n const buffers = arrays.map(([name, array, size]) => {\n const attribute = new THREE.BufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute(name, attribute)\n return attribute\n })\n geometry.setDrawRange(0, 0)\n const material = new THREE.ShaderMaterial({\n uniforms: { uScale: { value: scale }, uSoft: { value: soft } },\n vertexShader: WORKSHOP_SPRITE_VERTEX,\n fragmentShader: WORKSHOP_SPRITE_FRAGMENT,\n transparent: true,\n depthWrite: false,\n blending: additive ? THREE.AdditiveBlending : THREE.NormalBlending,\n })\n const points = new THREE.Points(geometry, material)\n points.frustumCulled = false\n points.renderOrder = additive ? 3 : 2\n points.name = additive ? 'workshop-add' : 'workshop-normal'\n return {\n object: points,\n sync() {\n geometry.setDrawRange(0, pool.count)\n for (const buffer of buffers) buffer.needsUpdate = true\n return pool.count > 0\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nfunction streakLayer(THREE: ThreeLib, pool: WorkshopEngine['streaks']): Drawn {\n const geometry = new THREE.BufferGeometry()\n const position = new THREE.BufferAttribute(pool.segment, 3).setUsage(THREE.DynamicDrawUsage)\n const color = new THREE.BufferAttribute(pool.segmentColor, 3).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute('position', position)\n geometry.setAttribute('color', color)\n geometry.setDrawRange(0, 0)\n const material = new THREE.LineBasicMaterial({ vertexColors: true, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false })\n const lines = new THREE.LineSegments(geometry, material)\n lines.frustumCulled = false\n lines.renderOrder = 4\n lines.name = 'workshop-streaks'\n return {\n object: lines,\n sync() {\n geometry.setDrawRange(0, pool.count * 2)\n position.needsUpdate = color.needsUpdate = true\n return pool.count > 0\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** The Workshop's rain (W317-320): one line segment per streak, pale blue, 35% opaque. */\nfunction rainLayer(THREE: ThreeLib, rain: WorkshopEngine['rain']): Drawn {\n const geometry = new THREE.BufferGeometry()\n const position = new THREE.BufferAttribute(rain.positions, 3).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute('position', position)\n geometry.setDrawRange(0, 0)\n const material = new THREE.LineBasicMaterial({ color: 0x9fb3cf, transparent: true, opacity: 0.35, depthWrite: false })\n const lines = new THREE.LineSegments(geometry, material)\n lines.frustumCulled = false\n lines.name = 'workshop-rain'\n return {\n object: lines,\n sync() {\n const drawn = rain.on && rain.count > 0\n lines.visible = drawn\n geometry.setDrawRange(0, drawn ? rain.count * 2 : 0)\n position.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nfunction debrisLayer(THREE: ThreeLib, pool: WorkshopEngine['debris']): Drawn {\n const geometry = new THREE.BoxGeometry(1, 1, 1)\n const material = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.45, metalness: 0.25, flatShading: true })\n const mesh = new THREE.InstancedMesh(geometry, material, DEBRIS_CAPACITY)\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.frustumCulled = false\n mesh.name = 'workshop-debris'\n const euler = new THREE.Euler()\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n const colour = new THREE.Color()\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n for (let index = 0; index < DEBRIS_CAPACITY; index++) mesh.setMatrixAt(index, hidden)\n mesh.setColorAt(0, colour.setHex(0xffffff))\n return {\n object: mesh,\n sync() {\n let drawn = false\n for (let index = 0; index < DEBRIS_CAPACITY; index++) {\n const piece = pool.pieces[index]!\n if (!piece.on) {\n mesh.setMatrixAt(index, hidden)\n continue\n }\n drawn = true\n const shrink = Math.min(1, piece.life / FADE_SECONDS)\n euler.set(piece.rx, piece.ry, piece.rz)\n quaternion.setFromEuler(euler)\n matrix.compose(position.set(piece.x, piece.y, piece.z), quaternion, scale.set(piece.sx * shrink, piece.sy * shrink, piece.sz * shrink))\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour.setHex(piece.color))\n }\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** A decal's current look from its fields (W276-306): it grows, a wet one creeps, dries towards its dry colour or evaporates. */\nfunction decalLook(decal: Decal, colour: THREE_NS.Color, dryColour: THREE_NS.Color, brown: THREE_NS.Color, ground: THREE_NS.Color, index: number): { sx: number; sy: number; dried: boolean } | null {\n const grown = decal.grow > 0 ? 1 - Math.pow(1 - Math.min(1, decal.t / decal.grow), 2.4) : 1\n let sx = decal.sx * grown\n let sy = decal.sy * grown\n colour.setHex(decal.color)\n let dried = false\n const fluid = decal.fluid\n if (fluid) {\n const creep = fluid === 'oil' ? 0.5 : fluid === 'fuel' ? 0.7 : fluid === 'bile' ? 0.25 : fluid === 'water' ? 0.2 : 0.3\n const age = decal.t\n if (decal.dryTime > 0) {\n const k = clamp((age - decal.dryAt) / decal.dryTime, 0, 1)\n if (decal.dryColor >= 0) dryColour.setHex(decal.dryColor)\n else dryColour.copy(colour).multiplyScalar(0.45).lerp(brown, 0.45)\n dried = k > GLOSS_DRIED_AT\n const spread = dried ? 1 + creep : 1 + creep * (1 - Math.exp(-age / 6))\n sx *= dried ? spread : spread * (1 + 0.04 * Math.sin(age * 1.9 + index))\n sy *= dried ? spread : spread * (1 + 0.04 * Math.cos(age * 1.5 + index * 0.7))\n colour.lerp(dryColour, k)\n } else {\n const spread = 1 + creep * (1 - Math.exp(-age / 6))\n sx *= spread * (1 + 0.04 * Math.sin(age * 1.9 + index))\n sy *= spread * (1 + 0.04 * Math.cos(age * 1.5 + index * 0.7))\n if (fluid === 'fuel' || fluid === 'water') {\n const [wait, span] = fluid === 'fuel' ? [6, 5] : [40, 20]\n const gone = clamp((age - wait) / span, 0, 1)\n sx *= 1 - gone * 0.85\n sy *= 1 - gone * 0.85\n colour.lerp(ground.setHex(fluid === 'fuel' ? FUEL_DRIED : GROUND_COLOR), gone * 0.8)\n if (gone >= 1) return null\n }\n }\n }\n return { sx, sy, dried }\n}\n\nfunction decalLayer(THREE: ThreeLib, pool: WorkshopEngine['decals']): Drawn {\n const geometry = new THREE.CircleGeometry(0.5, RIPPLE_SEGMENTS)\n const positions = geometry.getAttribute('position')\n // a blob, not a disc: each rim vertex is pulled in by a fixed amount between .72 and 1.12\n for (let index = 1; index < positions.count; index++) {\n const k = 0.72 + (((index * 2654435761) >>> 0) / 4294967296) * 0.4\n positions.setXY(index, positions.getX(index) * k, positions.getY(index) * k)\n }\n const wet = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.1, metalness: 0.3, polygonOffset: true, polygonOffsetFactor: -4, polygonOffsetUnits: -4 })\n const dry = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 1, metalness: 0, flatShading: true, polygonOffset: true, polygonOffsetFactor: -4, polygonOffsetUnits: -4 })\n const wetMesh = new THREE.InstancedMesh(geometry, wet, DECAL_CAPACITY)\n const dryMesh = new THREE.InstancedMesh(geometry, dry, DECAL_CAPACITY)\n const group = new THREE.Group()\n group.name = 'workshop-decals'\n for (const mesh of [wetMesh, dryMesh]) {\n mesh.frustumCulled = false\n mesh.renderOrder = 1\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n group.add(mesh)\n }\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n const colour = new THREE.Color()\n const dryColour = new THREE.Color()\n const brown = new THREE.Color(BROWN)\n const ground = new THREE.Color()\n const normal = new THREE.Vector3()\n const forward = new THREE.Vector3(0, 0, 1)\n const turn = new THREE.Quaternion()\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n wetMesh.setColorAt(0, colour.setHex(0))\n dryMesh.setColorAt(0, colour.setHex(0))\n for (let index = 0; index < DECAL_CAPACITY; index++) {\n wetMesh.setMatrixAt(index, hidden)\n dryMesh.setMatrixAt(index, hidden)\n }\n return {\n object: group,\n sync() {\n let drawn = false\n for (let index = 0; index < DECAL_CAPACITY; index++) {\n const decal = pool.decals[index]!\n wetMesh.setMatrixAt(index, hidden)\n dryMesh.setMatrixAt(index, hidden)\n if (!decal.on || decal.t < 0) continue\n const look = decalLook(decal, colour, dryColour, brown, ground, index)\n if (!look) continue\n drawn = true\n normal.set(decal.normal[0], decal.normal[1], decal.normal[2])\n quaternion.setFromUnitVectors(forward, normal)\n quaternion.multiply(turn.setFromAxisAngle(forward, index * 2.399963))\n const offset = 0.004 + (index % 40) * 0.0004\n matrix.compose(position.set(decal.x + normal.x * offset, decal.y + normal.y * offset, decal.z + normal.z * offset), quaternion, scale.set(look.sx, look.sy, 1))\n const mesh = look.dried ? dryMesh : wetMesh\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour)\n }\n for (const mesh of [wetMesh, dryMesh]) {\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n }\n return drawn\n },\n dispose() {\n geometry.dispose()\n wet.dispose()\n dry.dispose()\n },\n }\n}\n\nfunction ringLayer(THREE: ThreeLib, pool: WorkshopEngine['rings']): Drawn {\n const geometry = new THREE.RingGeometry(0.86, 1, 40)\n const material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide })\n const mesh = new THREE.InstancedMesh(geometry, material, RING_CAPACITY)\n mesh.frustumCulled = false\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.name = 'workshop-rings'\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n const colour = new THREE.Color()\n const normal = new THREE.Vector3()\n const forward = new THREE.Vector3(0, 0, 1)\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n mesh.setColorAt(0, colour.setHex(0))\n for (let index = 0; index < RING_CAPACITY; index++) mesh.setMatrixAt(index, hidden)\n return {\n object: mesh,\n sync() {\n let drawn = false\n for (let index = 0; index < RING_CAPACITY; index++) {\n const ring = pool.rings[index]!\n if (!ring.on) {\n mesh.setMatrixAt(index, hidden)\n continue\n }\n drawn = true\n const k = Math.min(1, ring.t / ring.duration)\n const radius = ring.from + (ring.to - ring.from) * (1 - Math.pow(1 - k, 2))\n quaternion.setFromUnitVectors(forward, normal.set(ring.normal[0], ring.normal[1], ring.normal[2]))\n matrix.compose(position.set(ring.point[0], ring.point[1], ring.point[2]), quaternion, scale.set(radius, radius, 1))\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour.setHex(ring.color).multiplyScalar(ring.hold ? ring.hold : 1 - k))\n }\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/**\n * Draws the pools of the world's Workshop engine (what `world.play` fills): the two sprite systems, the streaks, the physics debris, the decals, the\n * expanding rings and the flash and fire lights, with the page's shaders and materials.\n */\nexport function createWorkshopLayers(THREE: ThreeLib, engine: WorkshopEngine, pointScale: number, lightScale: number): WorkshopLayers {\n const group = new THREE.Group()\n group.name = 'workshop'\n const layers: Drawn[] = [\n spriteLayer(THREE, engine.add, true, 1, pointScale),\n spriteLayer(THREE, engine.normal, false, 0.55, pointScale),\n streakLayer(THREE, engine.streaks),\n rainLayer(THREE, engine.rain),\n debrisLayer(THREE, engine.debris),\n decalLayer(THREE, engine.decals),\n ringLayer(THREE, engine.rings),\n ]\n for (const layer of layers) group.add(layer.object)\n const meshes = createMeshLayer(THREE, engine.meshes)\n group.add(meshes.group)\n const flashLights = engine.lights.lights.map(() => new THREE.PointLight(0xffc070, 0, 14))\n const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE))\n for (const light of [...flashLights, ...fireLights]) group.add(light)\n return {\n group,\n sync() {\n let drawCalls = 0\n for (const layer of layers) if (layer.sync()) drawCalls++\n drawCalls += meshes.sync()\n engine.lights.lights.forEach((source, index) => {\n const light = flashLights[index]!\n light.position.set(source.x, source.y, source.z)\n light.color.setHex(source.color)\n light.distance = source.distance\n light.intensity = source.intensity * lightScale\n })\n engine.lights.fire.forEach((source, index) => {\n const light = fireLights[index]!\n light.position.set(source.x, source.y, source.z)\n light.intensity = source.intensity * lightScale\n })\n return drawCalls\n },\n dispose() {\n for (const layer of layers) layer.dispose()\n meshes.dispose()\n group.clear()\n },\n }\n}\n","import type * as THREE_NS from \"three\";\nimport type {\n BenchChange,\n BenchSheet,\n ChoiceOption,\n EffectHandle,\n EffectSink,\n ModuleControl,\n ModuleHost,\n ModuleLayer,\n ModuleMetric,\n TestableModule,\n} from \"@adatechnology/game-contracts\";\nimport {\n EVENT_BUDGET,\n EXPLOSIONS,\n GAME_EFFECTS,\n estimateCost,\n resolveStrings,\n} from \"@adatechnology/game-vfx\";\nimport type { EffectDef, ExplosionDef } from \"@adatechnology/game-vfx\";\nimport { createVfxRenderer, VFX_LAYERS } from \"../renderer\";\nimport type { ThreeLib, VfxRenderer } from \"../types\";\nimport { benchText } from \"./text\";\n\nexport interface VfxTestModuleOptions {\n readonly locale?: string;\n /** The recipes the bench lists (default `GAME_EFFECTS`) and the explosions (default `EXPLOSIONS`). */\n readonly effects?: Readonly<Record<string, EffectDef>>;\n readonly explosions?: Readonly<Record<string, ExplosionDef>>;\n /** Seconds between two replays while `auto_repeat` is on. */\n readonly repeatSeconds?: number;\n}\n\nconst DEFAULT_EFFECT = \"m67\";\n/** The profile the Lab falls back to for an unknown explosive: not something to pick. */\nconst FALLBACK_EXPLOSION = \"generic\";\nconst NO_VARIANT = \"none\";\nconst BLAST_POINT: readonly [number, number, number] = [0, 0.1, 0];\nconst DEFAULT_DISTANCE = 14;\nconst DEFAULT_REPEAT_SECONDS = 4;\nconst LIGHT_BUDGET = EVENT_BUDGET.blastLights + EVENT_BUDGET.fireLights;\nconst SEGMENT_COLORS = [\"#ffb347\", \"#ff7a2a\", \"#8a8f98\", \"#5c6370\"] as const;\n\nconst TEAMS = [\n \"creatures\",\n \"weapons\",\n \"destruction\",\n \"world\",\n \"vehicles\",\n \"screen\",\n] as const;\nconst LAYER_ID = \"show_\";\n\nconst humanize = (id: string): string => id.replace(/_/g, \" \");\n\n/** Where the bench stands for a distance (m): a three-quarter view that keeps the blast in frame. */\nconst eyeFor = (distance: number): [number, number, number] => [\n distance * 0.6,\n distance * 0.35 + 1.4,\n distance * 0.8,\n];\n\n/** The tick marks and segments of a sheet's timeline: an explosion's flash, fireball and smoke, or a recipe's time. */\nfunction timelineOf(\n explosion: ExplosionDef | undefined,\n recipe: EffectDef | undefined,\n metric: string,\n): NonNullable<BenchSheet[\"timeline\"]> {\n if (explosion) {\n const flash = explosion.flash.life ?? 0.2;\n const smoke = Math.max(explosion.smoke.life, 1);\n return {\n segments: [\n { name: \"flash\", start: 0, end: flash, color: SEGMENT_COLORS[0] },\n {\n name: \"fireball\",\n start: 0,\n end: Math.min(smoke, 2.4),\n color: SEGMENT_COLORS[1],\n },\n { name: \"smoke\", start: 0.4, end: smoke, color: SEGMENT_COLORS[2] },\n ],\n ticks: Array.from({ length: Math.ceil(smoke) }, (_, index) => index + 1),\n metric,\n };\n }\n const span = recipe?.loop && recipe.loop > 0 ? recipe.loop : 4;\n return {\n segments: [\n { name: recipe?.id ?? \"\", start: 0, end: span, color: SEGMENT_COLORS[1] },\n ],\n ticks: Array.from({ length: Math.floor(span) }, (_, index) => index + 1),\n metric,\n };\n}\n\n/**\n * The effects bench: pick an explosion or a recipe (listed by team), its variant, the distance, the quality and the layers, replay it or let it repeat,\n * and watch the particle and light counters against the budget. It plays through `host.effects` (the room's world) and, in a host without one, draws\n * into a renderer of its own.\n */\nexport function createVfxTestModule(\n options: VfxTestModuleOptions = {},\n): TestableModule {\n const locale = options.locale ?? \"en\";\n const recipes = options.effects ?? GAME_EFFECTS;\n const explosions = options.explosions ?? EXPLOSIONS;\n const text = benchText(locale);\n const strings = resolveStrings(locale);\n\n const effectOptions = (): ChoiceOption[] => [\n ...Object.keys(explosions)\n .filter((id) => id !== FALLBACK_EXPLOSION)\n .map((id) => ({\n id,\n name: humanize(id),\n group: strings.groups.explosions ?? text.sheet.explosion,\n })),\n // an id the explosions already use is the explosion's: the sink tries the explosions first, so the recipe of the same name could not be reached\n ...TEAMS.flatMap((team) =>\n Object.values(recipes)\n .filter((def) => def.team === team && !(def.id in explosions))\n .map((def) => ({\n id: def.id,\n name: strings.effects[def.id]?.name ?? humanize(def.id),\n group: strings.groups[def.team] ?? def.team,\n })),\n ),\n ];\n\n const sheetFor = (id: string): BenchSheet => {\n const explosion = explosions[id];\n if (explosion) {\n return {\n kicker: strings.groups.explosions ?? text.sheet.explosion,\n title: humanize(id),\n facts: [\n { label: text.sheet.lethal, value: `${explosion.lethal} m` },\n { label: text.sheet.injury, value: `${explosion.injury} m` },\n { label: text.sheet.radius, value: `${explosion.visualRadius} m` },\n { label: text.sheet.fireballs, value: String(explosion.fireballs) },\n {\n label: text.sheet.particles,\n value: `${estimateCost(explosion)} / ${EVENT_BUDGET.particles}`,\n },\n ],\n timeline: timelineOf(explosion, undefined, \"blast_time\"),\n };\n }\n const recipe = recipes[id];\n const words = strings.effects[id];\n const labels = strings.sheet;\n return {\n kicker: recipe ? (strings.groups[recipe.team] ?? recipe.team) : undefined,\n title: words?.name ?? humanize(id),\n ...(words ? { body: words.short } : {}),\n facts: words\n ? [{ label: labels.budget, value: `${words.cost} · ${words.costNote}` }]\n : [],\n steps: words\n ? [\n { at: labels.when, text: words.when },\n { at: labels.look, text: words.look },\n { at: labels.budget, text: words.budget },\n { at: labels.network, text: words.network },\n ]\n : [],\n timeline: timelineOf(undefined, recipe, \"phase\"),\n };\n };\n\n const controls = (): ModuleControl[] => [\n {\n kind: \"choice\",\n id: \"effect\",\n name: text.controls.effect,\n options: effectOptions(),\n default:\n DEFAULT_EFFECT in explosions ? DEFAULT_EFFECT : effectOptions()[0]!.id,\n },\n {\n kind: \"choice\",\n id: \"variant\",\n name: text.controls.variant,\n options: [{ id: NO_VARIANT, name: text.none }],\n default: NO_VARIANT,\n hidden: true,\n },\n { kind: \"action\", id: \"replay\", name: text.controls.replay },\n {\n kind: \"boolean\",\n id: \"auto_repeat\",\n name: text.controls.auto_repeat,\n default: false,\n },\n {\n kind: \"number\",\n id: \"distance\",\n name: text.controls.distance,\n min: 4,\n max: 120,\n step: 1,\n unit: \"m\",\n default: DEFAULT_DISTANCE,\n },\n {\n kind: \"choice\",\n id: \"lod_band\",\n name: text.controls.lod_band,\n options: ([\"auto\", \"near\", \"middle\", \"far\"] as const).map((id) => ({\n id,\n name: text.lod[id],\n })),\n default: \"auto\",\n },\n {\n kind: \"choice\",\n id: \"quality\",\n name: text.controls.quality,\n options: ([\"high\", \"medium\", \"low\"] as const).map((id) => ({\n id,\n name: text.quality[id],\n })),\n default: \"high\",\n },\n ];\n\n const layers = (): ModuleLayer[] =>\n VFX_LAYERS.map((id) => ({ id: `${LAYER_ID}${id}`, name: text.layers[id] }));\n\n /** The live counters: shared by `metrics` and filled by `attach` (a module without a host reads zeros). */\n let read: () => {\n stats: Readonly<Record<string, number>>;\n phase: number;\n budget: number;\n } = () => ({ stats: {}, phase: 0, budget: 0 });\n\n const metrics = (): ModuleMetric[] => [\n {\n id: \"puffs\",\n name: text.metrics.puffs,\n digits: 0,\n read: () => read().stats.puffs ?? 0,\n },\n {\n id: \"sparks\",\n name: text.metrics.sparks,\n digits: 0,\n read: () => read().stats.sparks ?? 0,\n },\n {\n id: \"debris\",\n name: text.metrics.debris,\n digits: 0,\n max: EVENT_BUDGET.debris,\n read: () => read().stats.chunks ?? 0,\n },\n {\n id: \"lights\",\n name: text.metrics.lights,\n digits: 0,\n max: LIGHT_BUDGET,\n read: () =>\n (read().stats.blastLights ?? 0) + (read().stats.fireLights ?? 0),\n },\n {\n id: \"budget_particles\",\n name: text.metrics.budget_particles,\n digits: 0,\n max: EVENT_BUDGET.particles,\n read: () => read().budget,\n },\n {\n id: \"lod\",\n name: text.metrics.lod,\n digits: 2,\n read: () => read().stats.lod ?? 1,\n },\n {\n id: \"phase\",\n name: text.metrics.phase,\n unit: \"s\",\n digits: 2,\n read: () => read().phase,\n },\n {\n id: \"blast_time\",\n name: text.metrics.blast_time,\n unit: \"s\",\n digits: 2,\n read: () => Math.max(0, read().stats.blastTime ?? 0),\n },\n ];\n\n return {\n id: \"vfx\",\n name: text.module,\n group: \"effects\",\n items: () => [],\n controls,\n layers,\n metrics,\n // opening the effects area puts the camera at the bench view (the initial distance does not move it: that would take the player's view on load)\n area: () => ({\n placements: [],\n view: { eye: eyeFor(DEFAULT_DISTANCE), target: [0, 1.2, 0] },\n }),\n attach(host: ModuleHost) {\n const bench = host.bench;\n let own: VfxRenderer | undefined;\n let sink: EffectSink | undefined = host.effects;\n if (!sink) {\n own = createVfxRenderer(host.THREE as ThreeLib, {\n scene: host.scene as THREE_NS.Scene,\n camera: host.camera as THREE_NS.PerspectiveCamera,\n });\n sink = own;\n }\n const effects = sink;\n let effect = \"m67\";\n let variant = NO_VARIANT;\n let distance = DEFAULT_DISTANCE;\n let auto = false;\n let phase = 0;\n let handle: EffectHandle | null = null;\n let sinceRepeat = 0;\n // The room hands a module its initial and restored values right after attach (`sendInitial`), in the same tick: those set the state\n // (effect, variant, sheet) but must not play. Playing starts with the first frame, i.e. with what the user does afterwards.\n let live = false;\n\n read = () => {\n const def = explosions[effect];\n const recipe = recipes[effect];\n const budget = def\n ? estimateCost(def)\n : (recipe?.budget.particles ?? 0);\n return { stats: effects.stats?.() ?? {}, phase, budget };\n };\n\n function replay(): void {\n if (handle !== null) effects.stop(handle);\n phase = 0;\n sinceRepeat = 0;\n handle = effects.play({\n effect,\n point: [BLAST_POINT[0], BLAST_POINT[1], BLAST_POINT[2]],\n direction: [1, 0.2, 0.4],\n normal: [0, 1, 0],\n ...(variant !== NO_VARIANT &&\n recipes[effect]?.params?.options.includes(variant)\n ? { param: variant }\n : {}),\n });\n }\n\n function choose(id: string): void {\n effect = id;\n const params = recipes[id]?.params;\n variant = params\n ? (params.options[params.default] ?? params.options[0] ?? NO_VARIANT)\n : NO_VARIANT;\n bench?.patch(\n \"variant\",\n params\n ? {\n hidden: false,\n options: params.options.map((option) => ({\n id: option,\n name: option,\n })),\n value: variant,\n }\n : {\n hidden: true,\n options: [{ id: NO_VARIANT, name: text.none }],\n value: NO_VARIANT,\n },\n );\n bench?.sheet?.(sheetFor(id));\n if (live) replay();\n }\n\n function look(): void {\n const eye = eyeFor(distance);\n bench?.look(eye, [0, 1.2, 0]);\n }\n\n const apply = (change: BenchChange): void => {\n if (change.kind === \"layer\")\n effects.configure?.({\n [`layer_${change.id.slice(LAYER_ID.length)}`]: change.on,\n });\n else if (change.kind === \"action\") {\n if (change.id === \"replay\") replay();\n } else if (change.id === \"effect\" && typeof change.value === \"string\")\n choose(change.value);\n else if (change.id === \"variant\" && typeof change.value === \"string\") {\n variant = change.value;\n if (live && recipes[effect]?.params) replay();\n } else if (change.id === \"auto_repeat\") auto = change.value === true;\n else if (change.id === \"distance\" && typeof change.value === \"number\") {\n distance = change.value;\n look();\n } else if (change.id === \"lod_band\" || change.id === \"quality\")\n effects.configure?.({ [change.id]: change.value });\n };\n const offChange = bench?.onChange(apply);\n const offFrame = host.onFrame((dt) => {\n live = true;\n phase += dt;\n sinceRepeat += dt;\n own?.update(dt);\n if (\n auto &&\n sinceRepeat >= (options.repeatSeconds ?? DEFAULT_REPEAT_SECONDS)\n )\n replay();\n });\n return () => {\n offChange?.();\n offFrame();\n if (handle !== null) effects.stop(handle);\n bench?.sheet?.(null);\n own?.dispose();\n read = () => ({ stats: {}, phase: 0, budget: 0 });\n };\n },\n };\n}\n","/** The words of the effects bench, per locale (the effects' own texts live in `@adatechnology/game-vfx`). */\nexport interface BenchText {\n readonly module: string\n readonly controls: Readonly<Record<'effect' | 'variant' | 'replay' | 'auto_repeat' | 'distance' | 'lod_band' | 'quality', string>>\n readonly lod: Readonly<Record<'auto' | 'near' | 'middle' | 'far', string>>\n readonly quality: Readonly<Record<'high' | 'medium' | 'low', string>>\n readonly layers: Readonly<Record<'puffs' | 'sparks' | 'glows' | 'debris' | 'shock' | 'sprites', string>>\n readonly metrics: Readonly<Record<'puffs' | 'sparks' | 'debris' | 'lights' | 'budget_particles' | 'lod' | 'phase' | 'blast_time', string>>\n readonly sheet: Readonly<Record<'explosion' | 'lethal' | 'injury' | 'radius' | 'fireballs' | 'particles' | 'scale', string>>\n readonly none: string\n}\n\nexport const benchTexts: Readonly<Record<string, BenchText>> = {\n en: {\n module: 'Effects',\n controls: { effect: 'Effect', variant: 'Variant', replay: 'Replay', auto_repeat: 'Auto replay', distance: 'Distance', lod_band: 'LOD band', quality: 'Quality' },\n lod: { auto: 'Auto', near: 'Near', middle: 'Middle', far: 'Far' },\n quality: { high: 'High', medium: 'Medium', low: 'Low' },\n layers: { puffs: 'Smoke and fire', sparks: 'Sparks', glows: 'Glows', debris: 'Debris', shock: 'Shock wave', sprites: 'Droplets and recipes' },\n metrics: { puffs: 'Puffs', sparks: 'Sparks', debris: 'Debris', lights: 'Lights', budget_particles: 'Particles of the effect', lod: 'LOD scale', phase: 'Time since replay', blast_time: 'Time since the blast' },\n sheet: { explosion: 'Explosion', lethal: 'Lethal radius', injury: 'Injury radius', radius: 'Fireball', fireballs: 'Fireballs', particles: 'Particles', scale: 'Scale' },\n none: 'None',\n },\n 'pt-BR': {\n module: 'Efeitos',\n controls: { effect: 'Efeito', variant: 'Variante', replay: 'Repetir', auto_repeat: 'Repetição automática', distance: 'Distância', lod_band: 'Faixa de LOD', quality: 'Qualidade' },\n lod: { auto: 'Automático', near: 'Perto', middle: 'Meio', far: 'Longe' },\n quality: { high: 'Alta', medium: 'Média', low: 'Baixa' },\n layers: { puffs: 'Fumaça e fogo', sparks: 'Faíscas', glows: 'Brilhos', debris: 'Destroços', shock: 'Onda de choque', sprites: 'Gotas e receitas' },\n metrics: { puffs: 'Nuvens', sparks: 'Faíscas', debris: 'Destroços', lights: 'Luzes', budget_particles: 'Partículas do efeito', lod: 'Escala de LOD', phase: 'Tempo desde a repetição', blast_time: 'Tempo desde a explosão' },\n sheet: { explosion: 'Explosão', lethal: 'Raio letal', injury: 'Raio de ferimento', radius: 'Bola de fogo', fireballs: 'Bolas de fogo', particles: 'Partículas', scale: 'Escala' },\n none: 'Nenhuma',\n },\n}\n\nexport const benchText = (locale: string): BenchText => benchTexts[locale] ?? benchTexts.en!\n","import type * as THREE_NS from 'three'\nimport type { GroundField } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nexport interface GroundPatchOptions {\n /** The height field the craters dig; the mesh follows it. */\n readonly field: GroundField\n /** What the patch is made of (default a plain flat-shaded grey standard material). */\n readonly material?: THREE_NS.Material\n /** Texture coordinates repeat every this many metres (the Lab's 17). */\n readonly textureMetres?: number\n}\n\nexport interface GroundPatch {\n readonly mesh: THREE_NS.Mesh\n /** Redraws the vertices when the field changed since the last call. Returns whether it did. */\n sync(): boolean\n dispose(): void\n}\n\nconst DEFAULT_TEXTURE_METRES = 17\n\n/** The Lab's 60 m deformable patch with 33 cm cells (L60-83), as a mesh that follows a `GroundField`. */\nexport function createGroundPatch(THREE: ThreeLib, options: GroundPatchOptions): GroundPatch {\n const field = options.field\n const metres = options.textureMetres ?? DEFAULT_TEXTURE_METRES\n const geometry = new THREE.PlaneGeometry(field.size, field.size, field.segments, field.segments).rotateX(-Math.PI / 2)\n const position = geometry.attributes.position!\n const uv = geometry.attributes.uv!\n for (let index = 0; index < position.count; index++) uv.setXY(index, position.getX(index) / metres, position.getZ(index) / metres)\n const material = options.material ?? new THREE.MeshStandardMaterial({ color: 0x2b2c2f, roughness: 0.93, flatShading: true })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.receiveShadow = true\n let version = -1\n\n function sync(): boolean {\n if (field.version === version) return false\n version = field.version\n for (let index = 0; index < position.count; index++) position.setY(index, field.heights[index]!)\n position.needsUpdate = true\n geometry.computeBoundingSphere()\n return true\n }\n\n return {\n mesh,\n sync,\n dispose() {\n geometry.dispose()\n if (!options.material) material.dispose()\n },\n }\n}\n"],"mappings":"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","names":["clamp","layer","GROUND_COLOR","layer"]}
1
+ {"version":3,"sources":["../src/renderer.ts","../src/shaders/glow.ts","../src/shaders/noise.ts","../src/shaders/puff.ts","../src/shaders/spark.ts","../src/instanced.ts","../src/lights.ts","../src/canvas.ts","../src/marks.ts","../src/mesh-layer.ts","../src/screen-overlay.ts","../src/shaders/shock.ts","../src/shocks.ts","../src/shaders/sprite.ts","../src/sprites.ts","../src/shaders/workshop-sprite.ts","../src/workshop-layers.ts","../src/bench/module.ts","../src/bench/text.ts","../src/ground-patch.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport type { ControlValue } from '@adatechnology/game-contracts'\nimport { markKitOrigin } from '@adatechnology/game-contracts'\nimport { colorOfChunk, createVfx, hexToLinearRgb } from '@adatechnology/game-vfx'\nimport type { ScreenState, VfxWorld, WorkshopEngine } from '@adatechnology/game-vfx'\nimport { createChunkLayer, createGlowLayer, createPuffLayer, createSparkLayer } from './instanced'\nimport type { PuffUniforms } from './instanced'\nimport { createLightLayer } from './lights'\nimport { createMarkLayer } from './marks'\nimport { createMeshLayerProbes } from './mesh-layer'\nimport { createScreenOverlay } from './screen-overlay'\nimport { createShockLayer } from './shocks'\nimport { createSpriteLayer } from './sprites'\nimport type { ThreeLib, VfxRenderer, VfxRendererOptions } from './types'\nimport { createWorkshopLayers } from './workshop-layers'\nimport type { WorkshopLayers } from './workshop-layers'\n\nconst LAB_LIGHT_DIRECTION = [-14, 26, 12] as const\nconst SKY_COLOR = 0x6f7c92\nconst GROUND_COLOR = 0x2a241f\nconst LOD_BANDS: Readonly<Record<string, number | null>> = { auto: null, near: 1, middle: 0.5, far: 0.2 }\n/** The quality names the bench offers, as the Workshop's levels (0 keeps every particle). */\nconst QUALITY_LEVELS: Readonly<Record<string, number>> = { high: 0, medium: 1, low: 2 }\n/** `configure({ layer_<id>: false })` hides a layer of the renderer: `puffs`, `sparks`, `glows`, `debris`, `shock`, `sprites`. */\nexport const VFX_LAYERS = ['puffs', 'sparks', 'glows', 'debris', 'shock', 'sprites'] as const\nconst LAYER_PREFIX = 'layer_'\nconst SHAKE_REACH = 0.18\nconst SHAKE_FLOOR = 0.001\n\nfunction isWorld(value: unknown): value is VfxWorld {\n return typeof value === 'object' && value !== null && 'explosion' in value && typeof (value as VfxWorld).explosion === 'function'\n}\n\n/** The overlay shows the Lab's screen and the Workshop's together: the stronger of each field. */\nfunction mergeScreens(lab: ScreenState, workshop: ScreenState | undefined): ScreenState {\n if (!workshop) return lab\n const merged = { ...lab }\n for (const key of Object.keys(lab) as (keyof ScreenState)[]) merged[key] = Math.max(lab[key], workshop[key])\n return merged\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches\n}\n\n/** Draws a `VfxWorld`: the Lab's shaders, debris, shock, lights, marks and the screen overlay, and plays effects asked of it by id (`EffectSink`). */\nexport function createVfxRenderer(THREE: ThreeLib, options: VfxRendererOptions): VfxRenderer {\n const reducedMotion = options.reducedMotion ?? prefersReducedMotion()\n const requested = options.vfx\n const world = isWorld(requested) ? requested : createVfx({ profile: options.quality ?? 'medium', reducedMotion, ...requested })\n const pools = world.pools()\n // The probes of the last warm-up keep their materials until the next one: a program is destroyed when the last material that uses it is disposed (every solid particle disposes its own),\n // and a material that does not use lights keeps the program of the lights it was first drawn with, so each warm-up needs materials of its own.\n let anchors: { readonly meshes: THREE_NS.Mesh[]; readonly group: THREE_NS.Group } | undefined\n const releaseAnchors = (): void => {\n if (!anchors) return\n anchors.meshes[0]?.geometry.dispose()\n for (const mesh of anchors.meshes) (mesh.material as THREE_NS.Material).dispose()\n anchors = undefined\n }\n const root = markKitOrigin(new THREE.Group(), { owner: 'game-vfx-three', kind: 'effect' })\n options.scene.add(root)\n\n const direction = new THREE.Vector3(...(options.lightDirection ?? LAB_LIGHT_DIRECTION)).normalize()\n const sky = hexToLinearRgb(SKY_COLOR)\n const ground = hexToLinearRgb(GROUND_COLOR)\n const uniforms: PuffUniforms = {\n uLight: { value: direction },\n uSky: { value: new THREE.Vector3(sky[0] * 0.55, sky[1] * 0.55, sky[2] * 0.55) },\n uGround: { value: new THREE.Vector3(ground[0] * 0.6, ground[1] * 0.6, ground[2] * 0.6) },\n uGlowPos: { value: new THREE.Vector3() },\n uGlowCol: { value: new THREE.Vector3(1, 0.5, 0.2) },\n uGlowI: { value: 0 },\n uTime: { value: 0 },\n }\n const puffs = createPuffLayer(THREE, pools.puffs, uniforms)\n const sparks = createSparkLayer(THREE, pools.sparks)\n const glows = createGlowLayer(THREE, pools.glows)\n const rockGeometry = new THREE.DodecahedronGeometry(0.5, 0)\n const plateGeometry = new THREE.BoxGeometry(1, 1, 1)\n const chunks = createChunkLayer(THREE, pools.chunks, { rock: rockGeometry, plate: plateGeometry }, colorOfChunk)\n const shocks = createShockLayer(THREE, pools.shocks)\n const sprites = createSpriteLayer(THREE, world.sprites(), options.pointScale ?? 700)\n const lights = createLightLayer(THREE, pools.lights, options.lightScale ?? Math.PI)\n const marks = createMarkLayer(THREE, { ground: pools.ground, createCanvas: options.createCanvas, rockGeometry, plateGeometry })\n root.add(puffs.mesh, sparks.mesh, glows.mesh, chunks.rocks, chunks.plates, shocks.group, lights.group, sprites.additive, sprites.normal, marks.group)\n const stopMarks = world.onMarks((event) => marks.handle(event))\n const overlay = options.overlay ? createScreenOverlay(options.overlay) : undefined\n let drawCalls = 0\n let workshopLayers: WorkshopLayers | undefined\n let workshopEngine: WorkshopEngine | undefined\n const layerOn = new Map<string, boolean>()\n const layerObjects = (): Record<string, THREE_NS.Object3D[]> => ({\n puffs: [puffs.mesh],\n sparks: [sparks.mesh],\n glows: [glows.mesh],\n debris: [chunks.rocks, chunks.plates],\n shock: [shocks.group],\n sprites: [sprites.additive, sprites.normal, ...(workshopLayers ? [workshopLayers.group] : [])],\n })\n const applyLayers = (): void => {\n for (const [id, objects] of Object.entries(layerObjects())) for (const object of objects) object.visible = layerOn.get(id) !== false\n }\n const screenNow = (): ScreenState => mergeScreens(world.screen(), world.peekWorkshop()?.screen)\n let clock = 0\n const lastDrawn = { puffs: 0, sparks: 0, glows: 0, chunks: 0, shocks: 0, sprites: 0 }\n\n function followCamera(): void {\n const position = options.camera.position\n world.setCamera([position.x, position.y, position.z])\n }\n\n function syncAll(): void {\n lastDrawn.puffs = puffs.sync()\n lastDrawn.sparks = sparks.sync()\n lastDrawn.glows = glows.sync()\n lastDrawn.chunks = chunks.sync()\n lastDrawn.shocks = shocks.sync()\n lastDrawn.sprites = sprites.sync()\n lights.sync()\n const engine = world.peekWorkshop()\n if (engine && engine !== workshopEngine) {\n workshopLayers?.dispose()\n if (workshopLayers) root.remove(workshopLayers.group)\n workshopEngine = engine\n workshopLayers = createWorkshopLayers(THREE, engine, options.pointScale ?? 700, 1)\n root.add(workshopLayers.group)\n applyLayers()\n }\n const workshopCalls = workshopLayers?.sync() ?? 0\n const glow = pools.lights.glow\n uniforms.uGlowPos.value.set(glow.x, glow.y, glow.z)\n uniforms.uGlowCol.value.set(glow.color[0], glow.color[1], glow.color[2])\n uniforms.uGlowI.value = glow.intensity\n drawCalls = Number(lastDrawn.puffs > 0) + Number(lastDrawn.sparks > 0) + Number(lastDrawn.glows > 0) + Number(chunks.rocks.count > 0) + Number(chunks.plates.count > 0) + Number(sprites.additive.geometry.drawRange.count > 0) + Number(sprites.normal.geometry.drawRange.count > 0) + lastDrawn.shocks * 2 + marks.count() + workshopCalls\n }\n\n return {\n world,\n play(request) {\n followCamera()\n const explosion = world.explosion(request.effect, request.point, {\n ...(request.direction ? { direction: request.direction } : {}),\n ...(request.seed !== undefined ? { seed: request.seed } : {}),\n ...(request.scale !== undefined ? { scale: request.scale } : {}),\n })\n if (explosion !== null) return explosion\n return world.play(request.effect, request.point, {\n ...(request.direction ? { direction: request.direction } : {}),\n ...(request.normal ? { normal: request.normal } : {}),\n ...(request.orientation ? { orientation: request.orientation } : {}),\n ...(request.seed !== undefined ? { seed: request.seed } : {}),\n ...(request.param !== undefined ? { param: request.param } : {}),\n ...(request.values ? { values: request.values } : {}),\n })\n },\n stop: (handle) => world.stop(handle),\n configure(settings: Readonly<Record<string, ControlValue>>) {\n const band = settings.lod_band\n if (typeof band === 'string' && band in LOD_BANDS) world.forceLod(LOD_BANDS[band] ?? null)\n const quality = settings.quality\n if (typeof quality === 'string' && quality in QUALITY_LEVELS) world.workshop().setQuality(QUALITY_LEVELS[quality] ?? 0)\n let layersChanged = false\n for (const [key, value] of Object.entries(settings)) {\n if (!key.startsWith(LAYER_PREFIX) || typeof value !== 'boolean') continue\n layerOn.set(key.slice(LAYER_PREFIX.length), value)\n layersChanged = true\n }\n if (layersChanged) applyLayers()\n },\n catalog: () => [...world.catalog(), ...world.effectIds()],\n update(dt) {\n clock += dt\n uniforms.uTime.value = clock\n followCamera()\n world.update(dt)\n marks.update(dt)\n syncAll()\n overlay?.update(screenNow())\n },\n warmUpProbes() {\n releaseAnchors()\n const meshes = createMeshLayerProbes(THREE)\n for (const mesh of meshes) mesh.frustumCulled = false\n const group = new THREE.Group()\n group.add(...meshes)\n anchors = { meshes, group }\n return { group, dispose: () => {} }\n },\n applyCamera() {\n const shake = screenNow().shake\n if (reducedMotion || !(shake > SHAKE_FLOOR)) return () => {}\n const camera = options.camera as THREE_NS.Camera\n const base = camera.position.clone()\n const reach = shake * SHAKE_REACH\n camera.position.x += Math.sin(clock * 71) * reach\n camera.position.y += Math.sin(clock * 53 + 1) * reach * 0.7\n camera.position.z += Math.sin(clock * 67 + 2) * reach\n return () => camera.position.copy(base)\n },\n stats() {\n const { lastBlast, ...counters } = world.stats()\n return { ...counters, last_puffs: lastBlast.puffs, last_sparks: lastBlast.sparks, last_chunks: lastBlast.chunks, last_lights: lastBlast.lights, drawCalls }\n },\n screen: screenNow,\n dispose() {\n releaseAnchors()\n stopMarks()\n overlay?.dispose()\n workshopLayers?.dispose()\n for (const layer of [puffs, sparks, glows, chunks, shocks, lights, marks, sprites]) layer.dispose()\n rockGeometry.dispose()\n plateGeometry.dispose()\n options.scene.remove(root)\n },\n }\n}\n","/** The additive halo (Lab L297-304), verbatim except for the r160 colour-space chunk. */\nexport const GLOW_VERTEX = `attribute vec4 aP;attribute vec4 aC;varying vec2 vU;varying vec4 vC;\nvoid main(){vec3 R=vec3(viewMatrix[0][0],viewMatrix[1][0],viewMatrix[2][0]);vec3 Up=vec3(viewMatrix[0][1],viewMatrix[1][1],viewMatrix[2][1]);\nvec3 wp=aP.xyz+(R*position.x+Up*position.y)*aP.w;vU=position.xy;vC=aC;gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.);}`\n\nexport const GLOW_FRAGMENT = `varying vec2 vU;varying vec4 vC;void main(){float r=dot(vU,vU);if(r>1.)discard;float f=exp(-r*4.2)-.015;gl_FragColor=vec4(vC.rgb*vC.a*max(f,0.),1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","/** The value noise the puff shader builds its dissolve from (Lab L116-122), verbatim. */\nexport const GL_NOISE = `\nfloat h3(vec3 p){p=fract(p*.3183099+.1);p*=17.0;return fract(p.x*p.y*p.z*(p.x+p.y+p.z));}\nfloat vn(vec3 x){vec3 i=floor(x),f=fract(x);f=f*f*(3.-2.*f);\n return mix(mix(mix(h3(i),h3(i+vec3(1,0,0)),f.x),mix(h3(i+vec3(0,1,0)),h3(i+vec3(1,1,0)),f.x),f.y),\n mix(mix(h3(i+vec3(0,0,1)),h3(i+vec3(1,0,1)),f.x),mix(h3(i+vec3(0,1,1)),h3(i+vec3(1,1,1)),f.x),f.y),f.z);}\n`\n","import { GL_NOISE } from './noise'\n\n/**\n * The puff shader of the Lab (L130-192), verbatim: a faceted icosahedron per puff, a five-band posterised heat ramp, a noise dissolve and banded light.\n * The only change is the r160 colour-space chunk: `encodings_fragment` (r128) is `colorspace_fragment` now.\n */\nexport const PUFF_VERTEX = `${GL_NOISE}\nattribute vec4 aP;attribute vec4 aD;attribute vec3 aC;\nvarying vec3 vWP;varying vec3 vL;varying vec4 vD;varying vec3 vC;\nvoid main(){\n vec3 p=position;\n float s=aD.z;\n float n=vn(p*1.6+vec3(s*11.0,s*7.0,s*3.0));\n p*=0.78+0.5*n;\n float a=s*6.2831;float c=cos(a),si=sin(a);p.xz=mat2(c,-si,si,c)*p.xz;\n vL=p;\n vec3 wp=aP.xyz+p*aP.w;\n vWP=wp;vD=aD;vC=aC;\n gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.0);\n}`\n\nexport const PUFF_FRAGMENT = `${GL_NOISE}\nuniform vec3 uLight;uniform vec3 uSky;uniform vec3 uGround;uniform vec3 uGlowPos;uniform vec3 uGlowCol;uniform float uGlowI;\nvarying vec3 vWP;varying vec3 vL;varying vec4 vD;varying vec3 vC;\nvec3 L(vec3 c){return pow(c,vec3(2.2));}\nvec3 ramp(float h){\n vec3 c0=L(vec3(.36,.07,.03)),c1=L(vec3(.76,.21,.1)),c2=L(vec3(1.,.54,.16)),c3=L(vec3(1.,.83,.42)),c4=L(vec3(1.,.96,.84));\n if(h<.25)return mix(c0,c1,h/.25);\n if(h<.5)return mix(c1,c2,(h-.25)/.25);\n if(h<.8)return mix(c2,c3,(h-.5)/.3);\n return mix(c3,c4,clamp((h-.8)/.4,0.,1.));\n}\nvoid main(){\n vec3 N=normalize(cross(dFdx(vWP),dFdy(vWP)));\n float age=vD.x,heat=vD.y,kind=vD.w;\n float n=vn(vL*2.4+vD.z*13.0);\n float diss=smoothstep(.5,1.,age);\n if(n<diss*1.08-.04)discard;\n float lam=max(dot(N,uLight),0.);\n float band=lam>.55?1.:lam>.15?.68:.42;\n vec3 col=vC*(vec3(.5,.56,.7)*band*1.05+vec3(.2,.19,.18)+uGround*(.4-.4*N.y));\n vec3 tg=uGlowPos-vWP;float dg=length(tg)+.001;\n float gi=uGlowI/(1.+dg*dg*.05)*(.3+.7*max(dot(N,tg/dg),0.));\n col+=uGlowCol*gi*vC*1.6;\n float h=heat*(.72+.56*n)+heat*(-N.y)*.18;\n if(h>.05){\n float hq=floor(h*5.+.5)/5.;\n vec3 fc=ramp(clamp(hq,0.,1.2))*(1.1+3.1*hq);\n col=mix(col,fc,smoothstep(.04,.2,h));\n }\n if(kind>2.5&&kind<3.5){col+=vec3(.02,.025,.03);}\n gl_FragColor=vec4(col,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","/** The streak shader of shrapnel, sparks and embers (Lab L255-275), verbatim except for the r160 colour-space chunk. */\nexport const SPARK_VERTEX = `\nattribute vec3 aPos;attribute vec3 aVel;attribute vec4 aE;varying vec2 vU;varying vec4 vE;\nvoid main(){\n float sp=length(aVel)+1e-4;vec3 d=aVel/sp;\n vec3 tc=normalize(cameraPosition-aPos);\n vec3 sd=normalize(cross(d,tc)+vec3(1e-5));\n float len=max(aE.y*2.5,min(sp*aE.z,2.2));\n vec3 wp=aPos+sd*position.x*aE.y-d*position.y*len;\n vU=position.xy;vE=aE;\n gl_Position=projectionMatrix*viewMatrix*vec4(wp,1.);\n}`\n\nexport const SPARK_FRAGMENT = `\nvarying vec2 vU;varying vec4 vE;\nvoid main(){\n float age=vE.x,k=vE.w;\n float w=1.-abs(vU.x)*2.;w=w*w;\n float tail=1.-vU.y;\n vec3 c;\n if(k<.5){c=mix(vec3(4.,3.3,2.2),vec3(2.4,.7,.12),smoothstep(0.,.55,age));c=mix(c,vec3(.5,.06,.02),smoothstep(.55,1.,age));}\n else if(k<1.5){c=mix(vec3(1.6,1.6,1.6),vec3(.35,.35,.36),smoothstep(0.,.4,age));}\n else if(k<2.5){c=mix(vec3(5.,5.,6.),vec3(1.,1.3,2.),smoothstep(0.,.5,age));}\n else if(k<3.5){c=vec3(.9,1.2,1.4)*(1.-age);}\n else {c=mix(vec3(3.2,1.4,.3),vec3(1.2,.25,.05),age);}\n float a=w*(.35+.65*tail)*(1.-smoothstep(.75,1.,age));\n gl_FragColor=vec4(c*a,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","import type * as THREE_NS from 'three'\nimport type { Chunk, Glow, OrderedPool, Puff, Spark } from '@adatechnology/game-vfx'\nimport { GLOW_FRAGMENT, GLOW_VERTEX } from './shaders/glow'\nimport { PUFF_FRAGMENT, PUFF_VERTEX } from './shaders/puff'\nimport { SPARK_FRAGMENT, SPARK_VERTEX } from './shaders/spark'\nimport type { ThreeLib } from './types'\n\nexport interface DrawnLayer {\n readonly mesh: THREE_NS.Mesh\n /** Copies the pool into the instance buffers and answers how many are drawn. */\n sync(): number\n dispose(): void\n}\n\ntype Attribute = THREE_NS.InstancedBufferAttribute\n\nfunction dynamic(THREE: ThreeLib, array: Float32Array, size: number): Attribute {\n return new THREE.InstancedBufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n}\n\nexport interface PuffUniforms {\n uLight: { value: THREE_NS.Vector3 }\n uSky: { value: THREE_NS.Vector3 }\n uGround: { value: THREE_NS.Vector3 }\n uGlowPos: { value: THREE_NS.Vector3 }\n uGlowCol: { value: THREE_NS.Vector3 }\n uGlowI: { value: number }\n uTime: { value: number }\n}\n\nexport function createPuffLayer(THREE: ThreeLib, pool: OrderedPool<Puff>, uniforms: PuffUniforms): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.IcosahedronGeometry(1, 1).getAttribute('position'))\n const a = new Float32Array(capacity * 4)\n const d = new Float32Array(capacity * 4)\n const c = new Float32Array(capacity * 3)\n const attributes = [dynamic(THREE, a, 4), dynamic(THREE, d, 4), dynamic(THREE, c, 3)] as const\n geometry.setAttribute('aP', attributes[0])\n geometry.setAttribute('aD', attributes[1])\n geometry.setAttribute('aC', attributes[2])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ uniforms: uniforms as never, vertexShader: PUFF_VERTEX, fragmentShader: PUFF_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-puffs'\n mesh.frustumCulled = false\n return {\n mesh,\n sync() {\n let n = 0\n for (const p of pool.items) {\n a[n * 4] = p.x\n a[n * 4 + 1] = p.y\n a[n * 4 + 2] = p.z\n a[n * 4 + 3] = p.size\n d[n * 4] = p.age\n d[n * 4 + 1] = p.heat\n d[n * 4 + 2] = p.seed\n d[n * 4 + 3] = p.kind\n c[n * 3] = p.color[0]\n c[n * 3 + 1] = p.color[1]\n c[n * 3 + 2] = p.color[2]\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport function createSparkLayer(THREE: ThreeLib, pool: OrderedPool<Spark>): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute([-0.5, 0, 0, 0.5, 0, 0, 0.5, 1, 0, -0.5, 1, 0], 3))\n geometry.setIndex([0, 1, 2, 0, 2, 3])\n const position = new Float32Array(capacity * 3)\n const velocity = new Float32Array(capacity * 3)\n const extra = new Float32Array(capacity * 4)\n const attributes = [dynamic(THREE, position, 3), dynamic(THREE, velocity, 3), dynamic(THREE, extra, 4)] as const\n geometry.setAttribute('aPos', attributes[0])\n geometry.setAttribute('aVel', attributes[1])\n geometry.setAttribute('aE', attributes[2])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: SPARK_VERTEX, fragmentShader: SPARK_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-sparks'\n mesh.frustumCulled = false\n mesh.renderOrder = 5\n return {\n mesh,\n sync() {\n let n = 0\n for (const s of pool.items) {\n position[n * 3] = s.x\n position[n * 3 + 1] = s.y\n position[n * 3 + 2] = s.z\n velocity[n * 3] = s.vx\n velocity[n * 3 + 1] = s.vy\n velocity[n * 3 + 2] = s.vz\n extra[n * 4] = s.age\n extra[n * 4 + 1] = s.w\n extra[n * 4 + 2] = s.st\n extra[n * 4 + 3] = s.kind\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport function createGlowLayer(THREE: ThreeLib, pool: OrderedPool<Glow>): DrawnLayer {\n const capacity = pool.capacity\n const geometry = new THREE.InstancedBufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0], 3))\n geometry.setIndex([0, 1, 2, 0, 2, 3])\n const where = new Float32Array(capacity * 4)\n const color = new Float32Array(capacity * 4)\n const attributes = [dynamic(THREE, where, 4), dynamic(THREE, color, 4)] as const\n geometry.setAttribute('aP', attributes[0])\n geometry.setAttribute('aC', attributes[1])\n geometry.instanceCount = 0\n const material = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, vertexShader: GLOW_VERTEX, fragmentShader: GLOW_FRAGMENT })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.name = 'vfx-glows'\n mesh.frustumCulled = false\n mesh.renderOrder = 6\n return {\n mesh,\n sync() {\n let n = 0\n for (const g of pool.items) {\n where[n * 4] = g.outX\n where[n * 4 + 1] = g.outY\n where[n * 4 + 2] = g.outZ\n where[n * 4 + 3] = g.outSize\n color[n * 4] = g.color[0]\n color[n * 4 + 1] = g.color[1]\n color[n * 4 + 2] = g.color[2]\n color[n * 4 + 3] = g.outIntensity\n n++\n }\n geometry.instanceCount = n\n for (const attribute of attributes) attribute.needsUpdate = true\n return n\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nexport interface ChunkLayer {\n readonly rocks: THREE_NS.InstancedMesh\n readonly plates: THREE_NS.InstancedMesh\n sync(): number\n dispose(): void\n}\n\nexport function createChunkLayer(THREE: ThreeLib, pool: OrderedPool<Chunk>, shapes: { rock: THREE_NS.BufferGeometry; plate: THREE_NS.BufferGeometry }, colorOf: (chunk: Chunk) => readonly [number, number, number]): ChunkLayer {\n const capacity = pool.capacity\n const rockMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.85, flatShading: true })\n const plateMaterial = rockMaterial.clone()\n const make = (geometry: THREE_NS.BufferGeometry, material: THREE_NS.Material): THREE_NS.InstancedMesh => {\n const mesh = new THREE.InstancedMesh(geometry, material, capacity)\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.castShadow = true\n mesh.receiveShadow = true\n mesh.frustumCulled = false\n mesh.count = 0\n mesh.setColorAt(0, new THREE.Color(1, 1, 1))\n return mesh\n }\n const rocks = make(shapes.rock, rockMaterial)\n const plates = make(shapes.plate, plateMaterial)\n const matrix = new THREE.Matrix4()\n const quaternion = new THREE.Quaternion()\n const euler = new THREE.Euler()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n return {\n rocks,\n plates,\n sync() {\n let rockCount = 0\n let plateCount = 0\n for (const chunk of pool.items) {\n euler.set(chunk.rx, chunk.ry, chunk.rz)\n quaternion.setFromEuler(euler)\n matrix.compose(position.set(chunk.x, chunk.y, chunk.z), quaternion, scale.set(chunk.sx, chunk.sy, chunk.sz))\n const mesh = chunk.plate ? plates : rocks\n const index = chunk.plate ? plateCount++ : rockCount++\n mesh.setMatrixAt(index, matrix)\n const color = colorOf(chunk)\n const colors = mesh.instanceColor!.array as Float32Array\n colors[index * 3] = color[0]\n colors[index * 3 + 1] = color[1]\n colors[index * 3 + 2] = color[2]\n }\n rocks.count = rockCount\n plates.count = plateCount\n for (const mesh of [rocks, plates]) {\n mesh.instanceMatrix.needsUpdate = true\n mesh.instanceColor!.needsUpdate = true\n }\n return rockCount + plateCount\n },\n dispose() {\n rockMaterial.dispose()\n plateMaterial.dispose()\n rocks.dispose()\n plates.dispose()\n },\n }\n}\n","import type * as THREE_NS from 'three'\nimport type { LightPool } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nexport interface LightLayer {\n readonly group: THREE_NS.Group\n /** Moves and lights the 4 blast lights and 2 fire lights from the pool; answers how many are lit. */\n sync(): number\n dispose(): void\n}\n\n/** The Lab's light pool as real point lights (L349-365). Colours are the raw numbers the Lab used, not converted from sRGB. */\nexport function createLightLayer(THREE: ThreeLib, pool: LightPool, scale: number): LightLayer {\n const group = new THREE.Group()\n const blast = pool.blast.map(() => {\n const light = new THREE.PointLight(0xffa050, 0, 30, 2)\n light.position.set(0, -50, 0)\n group.add(light)\n return light\n })\n const fire = pool.fire.map(() => {\n const light = new THREE.PointLight(0xff7a2a, 0, 16, 2)\n light.position.set(0, -50, 0)\n group.add(light)\n return light\n })\n return {\n group,\n sync() {\n let lit = 0\n pool.blast.forEach((entry, index) => {\n const light = blast[index]!\n light.position.set(entry.x, entry.y, entry.z)\n light.distance = entry.distance\n light.color.setRGB(entry.color[0], entry.color[1], entry.color[2], THREE.LinearSRGBColorSpace)\n light.intensity = entry.intensity * scale\n if (entry.intensity > 0.05) lit++\n })\n pool.fire.forEach((entry, index) => {\n const light = fire[index]!\n light.position.set(entry.x, entry.y, entry.z)\n light.distance = entry.distance\n light.intensity = entry.intensity * scale\n if (entry.intensity > 0.05) lit++\n })\n return lit\n },\n dispose() {\n for (const light of [...blast, ...fire]) light.dispose()\n },\n }\n}\n","import { lehmer } from '@adatechnology/game-vfx'\nimport type { RandomStream } from '@adatechnology/game-vfx'\nimport type { CanvasContextLike, CanvasLike, ThreeLib } from './types'\nimport type * as THREE_NS from 'three'\n\nconst SCORCH_SEED = 5\nconst TEXTURE_SIZE = 256\nconst FULL_TURN = Math.PI * 2\n\n/** Where a texture draws its randomness: the Lab seeded the page with 5 before it made the marks, so the textures do not touch the effect's own stream. */\nexport function createTextureStream(): RandomStream {\n return lehmer(SCORCH_SEED)\n}\n\n/** Without a DOM (a server, a test in Node) there is nothing to draw on: the textures stay blank and the marks still lay down their geometry. */\nfunction blankCanvas(): CanvasLike {\n return { width: 0, height: 0, getContext: () => null }\n}\n\nfunction defaultCanvas(): CanvasLike {\n if (typeof document === 'undefined') return blankCanvas()\n return document.createElement('canvas') as unknown as CanvasLike\n}\n\nfunction paint(createCanvas: () => CanvasLike, draw: (context: CanvasContextLike, size: number) => void): CanvasLike {\n const canvas = createCanvas()\n canvas.width = TEXTURE_SIZE\n canvas.height = TEXTURE_SIZE\n const context = canvas.getContext('2d')\n if (context) draw(context, TEXTURE_SIZE)\n return canvas\n}\n\nfunction drawScorch(context: CanvasContextLike, size: number, random: RandomStream): void {\n context.clearRect(0, 0, size, size)\n const center = size / 2\n for (let ray = 0; ray < 60; ray++) {\n const angle = random.next() * FULL_TURN\n const length = center * (0.55 + random.next() * 0.42)\n context.strokeStyle = `rgba(8,6,5,${0.25 + random.next() * 0.35})`\n context.lineWidth = 2 + random.next() * 6\n context.beginPath()\n context.moveTo(center, center)\n context.lineTo(center + Math.cos(angle) * length, center + Math.sin(angle) * length)\n context.stroke()\n }\n const gradient = context.createRadialGradient(center, center, 0, center, center, center * 0.72)\n gradient.addColorStop(0, 'rgba(4,3,3,.96)')\n gradient.addColorStop(0.55, 'rgba(10,8,7,.85)')\n gradient.addColorStop(1, 'rgba(14,11,9,0)')\n context.fillStyle = gradient\n context.fillRect(0, 0, size, size)\n for (let spot = 0; spot < 26; spot++) {\n context.fillStyle = `rgba(60,40,28,${0.15 + random.next() * 0.2})`\n context.beginPath()\n context.arc(center + random.between(-0.4, 0.4) * center, center + random.between(-0.4, 0.4) * center, 2 + random.next() * 7, 0, 7)\n context.fill()\n }\n}\n\nfunction drawDirt(context: CanvasContextLike, size: number, random: RandomStream): void {\n const center = size / 2\n context.clearRect(0, 0, size, size)\n const gradient = context.createRadialGradient(center, center, 0, center, center, center)\n gradient.addColorStop(0, 'rgba(92,72,52,1)')\n gradient.addColorStop(0.6, 'rgba(118,92,64,1)')\n gradient.addColorStop(0.82, 'rgba(80,64,50,.8)')\n gradient.addColorStop(1, 'rgba(40,36,34,0)')\n context.fillStyle = gradient\n context.fillRect(0, 0, size, size)\n for (let speck = 0; speck < 420; speck++) {\n const angle = random.next() * FULL_TURN\n const distance = Math.sqrt(random.next()) * center * 0.8\n context.fillStyle = random.next() < 0.5 ? 'rgba(40,30,22,.5)' : 'rgba(160,132,96,.5)'\n context.beginPath()\n context.arc(center + Math.cos(angle) * distance, center + Math.sin(angle) * distance, 1 + random.next() * 3.5, 0, 7)\n context.fill()\n }\n}\n\nexport interface MarkTextures {\n readonly scorch: readonly THREE_NS.CanvasTexture[]\n readonly dirt: THREE_NS.CanvasTexture\n}\n\n/** The three scorch textures and the dirt one (L443-457), drawn once from a stream seeded like the page's. */\nexport function createMarkTextures(THREE: ThreeLib, createCanvas: (() => CanvasLike) | undefined): MarkTextures {\n const make = createCanvas ?? defaultCanvas\n const random = createTextureStream()\n const texture = (canvas: CanvasLike): THREE_NS.CanvasTexture => {\n const result = new THREE.CanvasTexture(canvas as unknown as HTMLCanvasElement)\n result.colorSpace = THREE.SRGBColorSpace\n result.anisotropy = 4\n return result\n }\n const scorch = [0, 1, 2].map(() => texture(paint(make, (context, size) => drawScorch(context, size, random))))\n const dirt = texture(paint(make, (context, size) => drawDirt(context, size, random)))\n return { scorch, dirt }\n}\n","import type * as THREE_NS from 'three'\nimport type { BloodMark, DirtMark, GroundField, Mark, MarkEvent, RockMark, ScorchMark } from '@adatechnology/game-vfx'\nimport { createMarkTextures } from './canvas'\nimport type { MarkTextures } from './canvas'\nimport type { CanvasLike, ThreeLib } from './types'\n\nconst MAX_CONFORM_STEPS = 48\nconst MIN_CONFORM_STEPS = 16\nconst BLOOD_GROW_RATE = 1.2\n\ninterface BloodDrawn {\n readonly mesh: THREE_NS.Mesh\n readonly scaleX: number\n readonly scaleZ: number\n age: number\n}\n\nexport interface MarkLayer {\n readonly group: THREE_NS.Group\n /** The shared rock and plate shapes, so the debris and the rim rocks use the same geometry. */\n handle(event: MarkEvent): void\n update(dt: number): void\n /** The meshes in the group right now. */\n count(): number\n dispose(): void\n}\n\nexport interface MarkLayerOptions {\n readonly ground: GroundField | undefined\n readonly createCanvas: (() => CanvasLike) | undefined\n readonly rockGeometry: THREE_NS.BufferGeometry\n readonly plateGeometry: THREE_NS.BufferGeometry\n}\n\n/**\n * The scorch, dirt, rim rocks and blood of the Lab as meshes (L443-476). A scorch or dirt mesh follows the ground as it was the moment the mark was\n * made (`conform`), so the renderer builds it from the mark event, not later.\n */\nexport function createMarkLayer(THREE: ThreeLib, options: MarkLayerOptions): MarkLayer {\n const group = new THREE.Group()\n const textures: MarkTextures = createMarkTextures(THREE, options.createCanvas)\n const owned: { dispose(): void }[] = [...textures.scorch, textures.dirt]\n const scorchMaterials = textures.scorch.map((map) => {\n const material = new THREE.MeshStandardMaterial({ map, transparent: true, depthWrite: false, roughness: 1, polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -2 })\n owned.push(material)\n return material\n })\n const dirtMaterial = new THREE.MeshStandardMaterial({\n map: textures.dirt, transparent: true, depthWrite: false, roughness: 1, flatShading: true, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: -1,\n })\n owned.push(dirtMaterial)\n const bloodMaterial = new THREE.MeshStandardMaterial({ color: 0x5c0a0a, roughness: 0.15, metalness: 0.1, polygonOffset: true, polygonOffsetFactor: -3, polygonOffsetUnits: -3 })\n const bloodGeometry = new THREE.CircleGeometry(0.5, 9).rotateX(-Math.PI / 2)\n owned.push(bloodMaterial, bloodGeometry)\n const rockMaterials = new Map<number, THREE_NS.MeshStandardMaterial>()\n const blood: BloodDrawn[] = []\n let meshCount = 0\n\n function rockMaterial(color: number): THREE_NS.MeshStandardMaterial {\n let material = rockMaterials.get(color)\n if (!material) {\n material = new THREE.MeshStandardMaterial({ color, roughness: 0.9, metalness: 0, flatShading: true })\n rockMaterials.set(color, material)\n owned.push(material)\n }\n return material\n }\n\n function conform(mark: ScorchMark | DirtMark, material: THREE_NS.Material): THREE_NS.Mesh {\n const radius = mark.radius\n const steps = Math.max(MIN_CONFORM_STEPS, Math.min(MAX_CONFORM_STEPS, Math.round(radius * 8)))\n const geometry = new THREE.PlaneGeometry(2, 2, steps, steps).rotateX(-Math.PI / 2)\n const position = geometry.attributes.position!\n const cos = Math.cos(mark.rotation)\n const sin = Math.sin(mark.rotation)\n for (let index = 0; index < position.count; index++) {\n const localX = position.getX(index) * radius\n const localZ = position.getZ(index) * radius\n const worldX = mark.x + localX * cos - localZ * sin\n const worldZ = mark.z + localX * sin + localZ * cos\n position.setXYZ(index, worldX, (options.ground?.heightAt(worldX, worldZ) ?? 0) + mark.lift, worldZ)\n }\n geometry.computeVertexNormals()\n const mesh = new THREE.Mesh(geometry, material as THREE_NS.MeshStandardMaterial)\n mesh.receiveShadow = true\n return mesh\n }\n\n function addRock(mark: RockMark): THREE_NS.Mesh {\n const mesh = new THREE.Mesh(mark.plate ? options.plateGeometry : options.rockGeometry, rockMaterial(mark.color))\n mesh.position.set(mark.x, mark.y, mark.z)\n mesh.scale.set(mark.scale[0], mark.scale[1], mark.scale[2])\n mesh.rotation.set(mark.rotation[0], mark.rotation[1], mark.rotation[2])\n mesh.castShadow = true\n mesh.receiveShadow = true\n return mesh\n }\n\n function addBlood(mark: BloodMark): THREE_NS.Mesh {\n const mesh = new THREE.Mesh(bloodGeometry, bloodMaterial)\n mesh.position.set(mark.x, mark.y, mark.z)\n mesh.scale.set(mark.scaleX, 1, mark.scaleZ)\n mesh.rotation.y = mark.rotation\n mesh.receiveShadow = true\n mesh.scale.multiplyScalar(0.05)\n blood.push({ mesh, scaleX: mark.scaleX, scaleZ: mark.scaleZ, age: 0 })\n return mesh\n }\n\n function build(mark: Mark): THREE_NS.Mesh {\n if (mark.kind === 'scorch') return conform(mark, scorchMaterials[mark.variant]!)\n if (mark.kind === 'dirt') return conform(mark, dirtMaterial)\n if (mark.kind === 'rock') return addRock(mark)\n return addBlood(mark)\n }\n\n function clearMeshes(): void {\n for (const child of [...group.children]) {\n group.remove(child)\n const geometry = (child as THREE_NS.Mesh).geometry\n if (geometry !== options.rockGeometry && geometry !== options.plateGeometry && geometry !== bloodGeometry) geometry.dispose()\n }\n blood.length = 0\n meshCount = 0\n }\n\n return {\n group,\n handle(event) {\n if (event.type === 'clear') {\n clearMeshes()\n return\n }\n group.add(build(event.mark))\n meshCount++\n },\n update(dt) {\n for (const drawn of blood) {\n if (drawn.age > 1) continue\n drawn.age += dt * BLOOD_GROW_RATE\n const ease = 1 - Math.pow(1 - Math.min(1, drawn.age), 2.5)\n drawn.mesh.scale.set(drawn.scaleX * Math.max(0.05, ease), 1, drawn.scaleZ * Math.max(0.05, ease))\n }\n },\n count: () => meshCount,\n dispose() {\n clearMeshes()\n for (const item of owned) item.dispose()\n },\n }\n}\n","import type * as THREE_NS from 'three'\nimport type { MeshParticle, MeshPool } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nconst SPHERE_DEFAULT_WIDTH = 8\nconst SPHERE_DEFAULT_HEIGHT = 6\n\nexport interface MeshLayer {\n readonly group: THREE_NS.Group\n /** Puts a mesh on every live solid particle and takes it off the ones that ended; answers how many are drawn. */\n sync(): number\n dispose(): void\n}\n\nfunction geometryOf(THREE: ThreeLib, particle: MeshParticle): THREE_NS.BufferGeometry {\n switch (particle.shape) {\n case 'cone': return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || undefined, particle.segments2 || 1, false)\n case 'cone_open': return new THREE.ConeGeometry(particle.radius, particle.height, particle.segments || undefined, particle.segments2 || 1, true)\n case 'sphere': return new THREE.SphereGeometry(particle.radius, particle.segments || SPHERE_DEFAULT_WIDTH, particle.segments2 || SPHERE_DEFAULT_HEIGHT)\n case 'icosahedron': return new THREE.IcosahedronGeometry(particle.radius, particle.segments)\n }\n}\n\n/** The materials the gallery gives these: a flat, translucent colour (added to what is behind it for a flash), or a rough grey that the scene's lights shade (smoke). */\nfunction materialOf(THREE: ThreeLib, particle: Pick<MeshParticle, 'lit' | 'color' | 'opacity' | 'additive'>): THREE_NS.Material {\n if (particle.lit) return new THREE.MeshStandardMaterial({ color: particle.color, roughness: 1, metalness: 0, transparent: true, opacity: particle.opacity, depthWrite: false })\n return new THREE.MeshBasicMaterial({ color: particle.color, transparent: true, opacity: particle.opacity, depthWrite: false, ...(particle.additive ? { blending: THREE.AdditiveBlending } : {}) })\n}\n\n/** One throwaway mesh per material the layer draws with (lit smoke, flat, additive flash), for a host to compile their shader programs before the first effect needs them. */\nexport function createMeshLayerProbes(THREE: ThreeLib): THREE_NS.Mesh[] {\n const geometry = new THREE.BoxGeometry(0.001, 0.001, 0.001)\n return [{ lit: true, additive: false }, { lit: false, additive: false }, { lit: false, additive: true }].map(\n (kind) => new THREE.Mesh(geometry, materialOf(THREE, { ...kind, color: 0x808080, opacity: 0.5 })),\n )\n}\n\n/**\n * The Workshop's solid particles (`MeshPool`) as three.js meshes, one each, like the gallery: the geometry and the material belong to the mesh and go with it. A mesh sits at\n * the group's point plus the group's turn applied to the piece's place times the scale, turned by the group's turn and then by the piece's own Euler angles.\n */\nexport function createMeshLayer(THREE: ThreeLib, pool: MeshPool): MeshLayer {\n const group = new THREE.Group()\n group.name = 'workshop-meshes'\n const drawn = new Map<number, THREE_NS.Mesh>()\n const frame = new THREE.Quaternion()\n const euler = new THREE.Euler()\n const turn = new THREE.Quaternion()\n const offset = new THREE.Vector3()\n\n function release(mesh: THREE_NS.Mesh): void {\n mesh.removeFromParent()\n mesh.geometry.dispose()\n ;(mesh.material as THREE_NS.Material).dispose()\n }\n\n return {\n group,\n sync() {\n const live = new Set<number>()\n for (const particle of pool.particles) {\n live.add(particle.id)\n let mesh = drawn.get(particle.id)\n if (!mesh) {\n mesh = new THREE.Mesh(geometryOf(THREE, particle), materialOf(THREE, particle))\n mesh.frustumCulled = false\n mesh.renderOrder = particle.additive ? 5 : 3\n drawn.set(particle.id, mesh)\n group.add(mesh)\n }\n frame.set(particle.frame[0], particle.frame[1], particle.frame[2], particle.frame[3])\n offset.set(particle.at[0], particle.at[1], particle.at[2]).multiplyScalar(particle.scale).applyQuaternion(frame)\n mesh.position.set(particle.x + offset.x, particle.y + offset.y, particle.z + offset.z)\n turn.setFromEuler(euler.set(particle.rx, particle.ry, particle.rz))\n mesh.quaternion.copy(frame).multiply(turn)\n mesh.scale.setScalar(particle.scale)\n ;(mesh.material as THREE_NS.Material).opacity = particle.opacity\n }\n for (const [id, mesh] of drawn) {\n if (live.has(id)) continue\n release(mesh)\n drawn.delete(id)\n }\n return pool.count\n },\n dispose() {\n for (const mesh of drawn.values()) release(mesh)\n drawn.clear()\n group.removeFromParent()\n },\n }\n}\n","import type { ScreenState } from '@adatechnology/game-vfx'\n\nexport interface ScreenOverlay {\n update(state: Readonly<ScreenState>): void\n dispose(): void\n}\n\nconst clamp = (value: number, min: number, max: number): number => (value < min ? min : value > max ? max : value)\n\nfunction layer(container: HTMLElement, name: string, blend?: string): HTMLDivElement {\n const element = container.ownerDocument.createElement('div')\n element.dataset.vfxOverlay = name\n Object.assign(element.style, { position: 'absolute', inset: '0', pointerEvents: 'none', opacity: '0' })\n if (blend) element.style.mixBlendMode = blend\n container.appendChild(element)\n return element\n}\n\n/**\n * The screen effects as overlays inside the host's container: the Lab's white flash (L1087, `mix-blend-mode: screen`) and the Workshop's white,\n * red edge, the two sides and the gas tint (W356-366), with the same colours. Nothing is drawn while the state is at rest.\n */\nexport function createScreenOverlay(container: HTMLElement): ScreenOverlay {\n const flash = layer(container, 'flash', 'screen')\n flash.style.background = '#fff'\n const white = layer(container, 'white')\n const red = layer(container, 'red')\n const sides = layer(container, 'sides')\n const gas = layer(container, 'gas')\n const elements = [flash, white, red, sides, gas]\n return {\n update(state) {\n flash.style.opacity = clamp(state.flash, 0, 1).toFixed(3)\n white.style.opacity = '1'\n white.style.background = `rgba(235,240,255,${clamp(state.white, 0, 1).toFixed(2)})`\n red.style.opacity = '1'\n red.style.background = `radial-gradient(ellipse at center, transparent 40%, rgba(170,16,12,${(clamp(state.red, 0, 1) * 0.85).toFixed(2)}) 100%)`\n sides.style.opacity = '1'\n sides.style.background = `linear-gradient(90deg, rgba(190,20,14,${(state.directionLeft * 0.8).toFixed(2)}) 0%, transparent 35%, transparent 65%, rgba(190,20,14,${(state.directionRight * 0.8).toFixed(2)}) 100%)`\n gas.style.opacity = '1'\n gas.style.background = state.gas > 0.01 ? `rgba(90,130,40,${(state.gas * 0.55).toFixed(2)})` : 'transparent'\n },\n dispose() {\n for (const element of elements) element.remove()\n },\n }\n}\n","/** The shock shell (fresnel edge, Lab L322-325) and the dust ring on the ground (L326-333), verbatim except for the r160 colour-space chunk. */\nexport const SHELL_VERTEX = `varying vec3 vN;varying vec3 vV;void main(){vec4 wp=modelMatrix*vec4(position,1.);vN=normalize(mat3(modelMatrix)*normal);vV=normalize(cameraPosition-wp.xyz);gl_Position=projectionMatrix*viewMatrix*wp;}`\n\nexport const SHELL_FRAGMENT = `uniform float uA;varying vec3 vN;varying vec3 vV;void main(){float f=1.-abs(dot(vN,vV));f=pow(f,5.);gl_FragColor=vec4(vec3(1.,.93,.82)*f*uA*.45,1.);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n\nexport const RING_VERTEX = `varying vec2 vU;void main(){vU=position.xz;gl_Position=projectionMatrix*viewMatrix*modelMatrix*vec4(position,1.);}`\n\nexport const RING_FRAGMENT = `uniform float uA;uniform float uW;uniform vec3 uC;varying vec2 vU;\n float h(vec2 p){return fract(sin(dot(p,vec2(12.9898,78.233)))*43758.5453);}\n void main(){float r=length(vU);float b=smoothstep(1.,1.-uW,r)*smoothstep(1.-uW*3.5,1.-uW,r);float a=atan(vU.y,vU.x);float n=.7+.3*h(vec2(floor(a*14.),1.));gl_FragColor=vec4(uC,b*uA*n);\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n}`\n","import type * as THREE_NS from 'three'\nimport type { OrderedPool, Shock } from '@adatechnology/game-vfx'\nimport { RING_FRAGMENT, RING_VERTEX, SHELL_FRAGMENT, SHELL_VERTEX } from './shaders/shock'\nimport type { ThreeLib } from './types'\n\ninterface Pair {\n readonly shell: THREE_NS.Mesh\n readonly ring: THREE_NS.Mesh\n readonly shellAlpha: { value: number }\n readonly ringAlpha: { value: number }\n}\n\nconst RING_HEIGHT = 0.05\n\nexport interface ShockLayer {\n readonly group: THREE_NS.Group\n sync(): number\n dispose(): void\n}\n\n/** The shock shell and ground ring of each live shock (L319-348): one pair of meshes per slot, shown while the slot has a shock. */\nexport function createShockLayer(THREE: ThreeLib, pool: OrderedPool<Shock>): ShockLayer {\n const group = new THREE.Group()\n const shellGeometry = new THREE.SphereGeometry(1, 28, 18)\n const ringGeometry = new THREE.PlaneGeometry(2, 2).rotateX(-Math.PI / 2)\n const pairs: Pair[] = []\n\n function makePair(): Pair {\n const shellAlpha = { value: 0 }\n const ringAlpha = { value: 0 }\n const shellMaterial = new THREE.ShaderMaterial({ transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, uniforms: { uA: shellAlpha }, vertexShader: SHELL_VERTEX, fragmentShader: SHELL_FRAGMENT })\n const ringMaterial = new THREE.ShaderMaterial({\n transparent: true, depthWrite: false, uniforms: { uA: ringAlpha, uW: { value: 0.12 }, uC: { value: new THREE.Color(0.55, 0.5, 0.44) } }, vertexShader: RING_VERTEX, fragmentShader: RING_FRAGMENT,\n })\n const shell = new THREE.Mesh(shellGeometry, shellMaterial)\n shell.renderOrder = 4\n const ring = new THREE.Mesh(ringGeometry, ringMaterial)\n ring.renderOrder = 3\n group.add(shell, ring)\n return { shell, ring, shellAlpha, ringAlpha }\n }\n\n return {\n group,\n sync() {\n const shocks = pool.items\n for (let index = 0; index < shocks.length; index++) {\n const pair = (pairs[index] ??= makePair())\n const shock = shocks[index]!\n pair.shell.visible = pair.ring.visible = true\n pair.shell.position.set(shock.x, shock.y, shock.z)\n pair.shell.scale.setScalar(shock.shellScale)\n pair.shellAlpha.value = shock.shellAlpha\n pair.ring.position.set(shock.x, RING_HEIGHT, shock.z)\n pair.ring.scale.setScalar(shock.ringScale)\n pair.ringAlpha.value = shock.ringAlpha\n }\n for (let index = shocks.length; index < pairs.length; index++) pairs[index]!.shell.visible = pairs[index]!.ring.visible = false\n return shocks.length\n },\n dispose() {\n for (const pair of pairs) {\n ;(pair.shell.material as THREE_NS.Material).dispose()\n ;(pair.ring.material as THREE_NS.Material).dispose()\n }\n shellGeometry.dispose()\n ringGeometry.dispose()\n },\n }\n}\n","/** The soft round point sprite of the game's sprite kinds (moved verbatim from the destruction renderer's particles). */\nexport const SPRITE_VERTEX = `\nuniform float uScale;\nattribute float size;\nattribute float alpha;\nattribute vec3 pcolor;\nvarying float vAlpha;\nvarying vec3 vColor;\nvoid main() {\n vAlpha = alpha;\n vColor = pcolor;\n vec4 mv = modelViewMatrix * vec4(position, 1.0);\n gl_PointSize = min(size * uScale / max(0.1, -mv.z), 256.0);\n gl_Position = projectionMatrix * mv;\n}`\n\nexport const SPRITE_FRAGMENT = `\nvarying float vAlpha;\nvarying vec3 vColor;\nvoid main() {\n float d = length(gl_PointCoord - vec2(0.5)) * 2.0;\n float a = (1.0 - smoothstep(0.35, 1.0, d)) * vAlpha;\n if (a < 0.004) discard;\n gl_FragColor = vec4(vColor, a);\n}`\n","import type * as THREE_NS from 'three'\nimport type { SpriteKindPool, SpriteKindSystem } from '@adatechnology/game-vfx'\nimport { SPRITE_FRAGMENT, SPRITE_VERTEX } from './shaders/sprite'\nimport type { ThreeLib } from './types'\n\nexport interface SpriteLayer {\n readonly additive: THREE_NS.Points\n readonly normal: THREE_NS.Points\n /** Tells the GPU what changed and answers how many sprites are drawn. */\n sync(): number\n dispose(): void\n}\n\ninterface Drawn {\n readonly points: THREE_NS.Points\n sync(): number\n dispose(): void\n}\n\nfunction drawPool(THREE: ThreeLib, pool: SpriteKindPool, additive: boolean, pointScale: number): Drawn {\n const geometry = new THREE.BufferGeometry()\n const attributes: [string, Float32Array, number][] = [['position', pool.position, 3], ['pcolor', pool.color, 3], ['alpha', pool.alpha, 1], ['size', pool.size, 1]]\n const buffers = attributes.map(([name, array, size]) => {\n const attribute = new THREE.BufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute(name, attribute)\n return attribute\n })\n geometry.setDrawRange(0, 0)\n const material = new THREE.ShaderMaterial({\n uniforms: { uScale: { value: pointScale } },\n vertexShader: SPRITE_VERTEX,\n fragmentShader: SPRITE_FRAGMENT,\n transparent: true,\n depthWrite: false,\n blending: additive ? THREE.AdditiveBlending : THREE.NormalBlending,\n })\n const points = new THREE.Points(geometry, material)\n points.frustumCulled = false\n points.name = additive ? 'vfx-sprites-additive' : 'vfx-sprites'\n points.renderOrder = additive ? 11 : 10\n return {\n points,\n sync() {\n geometry.setDrawRange(0, pool.drawCount)\n for (const buffer of buffers) buffer.needsUpdate = true\n return pool.drawCount\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** Draws the game's sprite kinds (debris, sparks, smoke, steam, drips...) as two soft point layers, additive and normal. */\nexport function createSpriteLayer(THREE: ThreeLib, system: SpriteKindSystem, pointScale: number): SpriteLayer {\n const additive = drawPool(THREE, system.additive, true, pointScale)\n const normal = drawPool(THREE, system.normal, false, pointScale)\n return {\n additive: additive.points,\n normal: normal.points,\n sync: () => additive.sync() + normal.sync(),\n dispose() {\n additive.dispose()\n normal.dispose()\n },\n }\n}\n","/** The Workshop's soft point sprite (W168-171): the size is in metres, clamped to 1..512 px; `uSoft` is 1 for the soft (normal blend) pool. */\nexport const WORKSHOP_SPRITE_VERTEX = `attribute float size;attribute float alpha;attribute vec3 pcol;varying vec3 vC;varying float vA;uniform float uScale;\nvoid main(){vC=pcol;vA=alpha;vec4 mv=modelViewMatrix*vec4(position,1.);gl_PointSize=clamp(size*uScale/-mv.z,1.,512.);gl_Position=projectionMatrix*mv;}`\n\nexport const WORKSHOP_SPRITE_FRAGMENT = `uniform float uSoft;varying vec3 vC;varying float vA;\nvoid main(){vec2 d=gl_PointCoord-.5;float r=length(d)*2.;if(r>1.)discard;float a=mix(smoothstep(1.,.78,r),pow(1.-r,1.5),uSoft);gl_FragColor=vec4(vC,vA*a);}`\n","import type * as THREE_NS from 'three'\nimport type { Decal, WorkshopEngine } from '@adatechnology/game-vfx'\nimport { createMeshLayer } from './mesh-layer'\nimport { WORKSHOP_SPRITE_FRAGMENT, WORKSHOP_SPRITE_VERTEX } from './shaders/workshop-sprite'\nimport type { ThreeLib } from './types'\n\nconst DEBRIS_CAPACITY = 500\nconst DECAL_CAPACITY = 400\nconst RING_CAPACITY = 120\nconst RIPPLE_SEGMENTS = 12\nconst FADE_SECONDS = 0.5\nconst FIRE_LIGHT_COLOR = 0xff7a2a\nconst FIRE_LIGHT_DISTANCE = 14\nconst GLOSS_DRIED_AT = 0.85\nconst BROWN = 0x2a1610\nconst GROUND_COLOR = 0x888888\nconst FUEL_DRIED = 0x888888\n\nexport interface WorkshopLayers {\n readonly group: THREE_NS.Group\n /** Copies the pools into the draw buffers; answers how many draw calls have something to draw. */\n sync(): number\n dispose(): void\n}\n\ninterface Drawn {\n readonly object: THREE_NS.Object3D\n sync(): boolean\n dispose(): void\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => (v < lo ? lo : v > hi ? hi : v)\n\nfunction spriteLayer(THREE: ThreeLib, pool: WorkshopEngine['add'], additive: boolean, soft: number, scale: number): Drawn {\n const geometry = new THREE.BufferGeometry()\n const arrays: [string, Float32Array, number][] = [['position', pool.position, 3], ['pcol', pool.color, 3], ['size', pool.size, 1], ['alpha', pool.alpha, 1]]\n const buffers = arrays.map(([name, array, size]) => {\n const attribute = new THREE.BufferAttribute(array, size).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute(name, attribute)\n return attribute\n })\n geometry.setDrawRange(0, 0)\n const material = new THREE.ShaderMaterial({\n uniforms: { uScale: { value: scale }, uSoft: { value: soft } },\n vertexShader: WORKSHOP_SPRITE_VERTEX,\n fragmentShader: WORKSHOP_SPRITE_FRAGMENT,\n transparent: true,\n depthWrite: false,\n blending: additive ? THREE.AdditiveBlending : THREE.NormalBlending,\n })\n const points = new THREE.Points(geometry, material)\n points.frustumCulled = false\n points.renderOrder = additive ? 3 : 2\n points.name = additive ? 'workshop-add' : 'workshop-normal'\n return {\n object: points,\n sync() {\n geometry.setDrawRange(0, pool.count)\n for (const buffer of buffers) buffer.needsUpdate = true\n return pool.count > 0\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nfunction streakLayer(THREE: ThreeLib, pool: WorkshopEngine['streaks']): Drawn {\n const geometry = new THREE.BufferGeometry()\n const position = new THREE.BufferAttribute(pool.segment, 3).setUsage(THREE.DynamicDrawUsage)\n const color = new THREE.BufferAttribute(pool.segmentColor, 3).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute('position', position)\n geometry.setAttribute('color', color)\n geometry.setDrawRange(0, 0)\n const material = new THREE.LineBasicMaterial({ vertexColors: true, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false })\n const lines = new THREE.LineSegments(geometry, material)\n lines.frustumCulled = false\n lines.renderOrder = 4\n lines.name = 'workshop-streaks'\n return {\n object: lines,\n sync() {\n geometry.setDrawRange(0, pool.count * 2)\n position.needsUpdate = color.needsUpdate = true\n return pool.count > 0\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** The Workshop's rain (W317-320): one line segment per streak, pale blue, 35% opaque. */\nfunction rainLayer(THREE: ThreeLib, rain: WorkshopEngine['rain']): Drawn {\n const geometry = new THREE.BufferGeometry()\n const position = new THREE.BufferAttribute(rain.positions, 3).setUsage(THREE.DynamicDrawUsage)\n geometry.setAttribute('position', position)\n geometry.setDrawRange(0, 0)\n const material = new THREE.LineBasicMaterial({ color: 0x9fb3cf, transparent: true, opacity: 0.35, depthWrite: false })\n const lines = new THREE.LineSegments(geometry, material)\n lines.frustumCulled = false\n lines.name = 'workshop-rain'\n return {\n object: lines,\n sync() {\n const drawn = rain.on && rain.count > 0\n lines.visible = drawn\n geometry.setDrawRange(0, drawn ? rain.count * 2 : 0)\n position.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\nfunction debrisLayer(THREE: ThreeLib, pool: WorkshopEngine['debris']): Drawn {\n const geometry = new THREE.BoxGeometry(1, 1, 1)\n const material = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.45, metalness: 0.25, flatShading: true })\n const mesh = new THREE.InstancedMesh(geometry, material, DEBRIS_CAPACITY)\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.frustumCulled = false\n mesh.name = 'workshop-debris'\n const euler = new THREE.Euler()\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n const colour = new THREE.Color()\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n for (let index = 0; index < DEBRIS_CAPACITY; index++) mesh.setMatrixAt(index, hidden)\n mesh.setColorAt(0, colour.setHex(0xffffff))\n return {\n object: mesh,\n sync() {\n let drawn = false\n for (let index = 0; index < DEBRIS_CAPACITY; index++) {\n const piece = pool.pieces[index]!\n if (!piece.on) {\n mesh.setMatrixAt(index, hidden)\n continue\n }\n drawn = true\n const shrink = Math.min(1, piece.life / FADE_SECONDS)\n euler.set(piece.rx, piece.ry, piece.rz)\n quaternion.setFromEuler(euler)\n matrix.compose(position.set(piece.x, piece.y, piece.z), quaternion, scale.set(piece.sx * shrink, piece.sy * shrink, piece.sz * shrink))\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour.setHex(piece.color))\n }\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/** A decal's current look from its fields (W276-306): it grows, a wet one creeps, dries towards its dry colour or evaporates. */\nfunction decalLook(decal: Decal, colour: THREE_NS.Color, dryColour: THREE_NS.Color, brown: THREE_NS.Color, ground: THREE_NS.Color, index: number): { sx: number; sy: number; dried: boolean } | null {\n const grown = decal.grow > 0 ? 1 - Math.pow(1 - Math.min(1, decal.t / decal.grow), 2.4) : 1\n let sx = decal.sx * grown\n let sy = decal.sy * grown\n colour.setHex(decal.color)\n let dried = false\n const fluid = decal.fluid\n if (fluid) {\n const creep = fluid === 'oil' ? 0.5 : fluid === 'fuel' ? 0.7 : fluid === 'bile' ? 0.25 : fluid === 'water' ? 0.2 : 0.3\n const age = decal.t\n if (decal.dryTime > 0) {\n const k = clamp((age - decal.dryAt) / decal.dryTime, 0, 1)\n if (decal.dryColor >= 0) dryColour.setHex(decal.dryColor)\n else dryColour.copy(colour).multiplyScalar(0.45).lerp(brown, 0.45)\n dried = k > GLOSS_DRIED_AT\n const spread = dried ? 1 + creep : 1 + creep * (1 - Math.exp(-age / 6))\n sx *= dried ? spread : spread * (1 + 0.04 * Math.sin(age * 1.9 + index))\n sy *= dried ? spread : spread * (1 + 0.04 * Math.cos(age * 1.5 + index * 0.7))\n colour.lerp(dryColour, k)\n } else {\n const spread = 1 + creep * (1 - Math.exp(-age / 6))\n sx *= spread * (1 + 0.04 * Math.sin(age * 1.9 + index))\n sy *= spread * (1 + 0.04 * Math.cos(age * 1.5 + index * 0.7))\n if (fluid === 'fuel' || fluid === 'water') {\n const [wait, span] = fluid === 'fuel' ? [6, 5] : [40, 20]\n const gone = clamp((age - wait) / span, 0, 1)\n sx *= 1 - gone * 0.85\n sy *= 1 - gone * 0.85\n colour.lerp(ground.setHex(fluid === 'fuel' ? FUEL_DRIED : GROUND_COLOR), gone * 0.8)\n if (gone >= 1) return null\n }\n }\n }\n return { sx, sy, dried }\n}\n\nfunction decalLayer(THREE: ThreeLib, pool: WorkshopEngine['decals']): Drawn {\n const geometry = new THREE.CircleGeometry(0.5, RIPPLE_SEGMENTS)\n const positions = geometry.getAttribute('position')\n // a blob, not a disc: each rim vertex is pulled in by a fixed amount between .72 and 1.12\n for (let index = 1; index < positions.count; index++) {\n const k = 0.72 + (((index * 2654435761) >>> 0) / 4294967296) * 0.4\n positions.setXY(index, positions.getX(index) * k, positions.getY(index) * k)\n }\n const wet = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 0.1, metalness: 0.3, polygonOffset: true, polygonOffsetFactor: -4, polygonOffsetUnits: -4 })\n const dry = new THREE.MeshStandardMaterial({ color: 0xffffff, roughness: 1, metalness: 0, flatShading: true, polygonOffset: true, polygonOffsetFactor: -4, polygonOffsetUnits: -4 })\n const wetMesh = new THREE.InstancedMesh(geometry, wet, DECAL_CAPACITY)\n const dryMesh = new THREE.InstancedMesh(geometry, dry, DECAL_CAPACITY)\n const group = new THREE.Group()\n group.name = 'workshop-decals'\n for (const mesh of [wetMesh, dryMesh]) {\n mesh.frustumCulled = false\n mesh.renderOrder = 1\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n group.add(mesh)\n }\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n const colour = new THREE.Color()\n const dryColour = new THREE.Color()\n const brown = new THREE.Color(BROWN)\n const ground = new THREE.Color()\n const normal = new THREE.Vector3()\n const forward = new THREE.Vector3(0, 0, 1)\n const turn = new THREE.Quaternion()\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n wetMesh.setColorAt(0, colour.setHex(0))\n dryMesh.setColorAt(0, colour.setHex(0))\n for (let index = 0; index < DECAL_CAPACITY; index++) {\n wetMesh.setMatrixAt(index, hidden)\n dryMesh.setMatrixAt(index, hidden)\n }\n return {\n object: group,\n sync() {\n let drawn = false\n for (let index = 0; index < DECAL_CAPACITY; index++) {\n const decal = pool.decals[index]!\n wetMesh.setMatrixAt(index, hidden)\n dryMesh.setMatrixAt(index, hidden)\n if (!decal.on || decal.t < 0) continue\n const look = decalLook(decal, colour, dryColour, brown, ground, index)\n if (!look) continue\n drawn = true\n normal.set(decal.normal[0], decal.normal[1], decal.normal[2])\n quaternion.setFromUnitVectors(forward, normal)\n quaternion.multiply(turn.setFromAxisAngle(forward, index * 2.399963))\n const offset = 0.004 + (index % 40) * 0.0004\n matrix.compose(position.set(decal.x + normal.x * offset, decal.y + normal.y * offset, decal.z + normal.z * offset), quaternion, scale.set(look.sx, look.sy, 1))\n const mesh = look.dried ? dryMesh : wetMesh\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour)\n }\n for (const mesh of [wetMesh, dryMesh]) {\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n }\n return drawn\n },\n dispose() {\n geometry.dispose()\n wet.dispose()\n dry.dispose()\n },\n }\n}\n\nfunction ringLayer(THREE: ThreeLib, pool: WorkshopEngine['rings']): Drawn {\n const geometry = new THREE.RingGeometry(0.86, 1, 40)\n const material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide })\n const mesh = new THREE.InstancedMesh(geometry, material, RING_CAPACITY)\n mesh.frustumCulled = false\n mesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)\n mesh.name = 'workshop-rings'\n const hidden = new THREE.Matrix4().makeScale(0, 0, 0)\n const colour = new THREE.Color()\n const normal = new THREE.Vector3()\n const forward = new THREE.Vector3(0, 0, 1)\n const quaternion = new THREE.Quaternion()\n const position = new THREE.Vector3()\n const scale = new THREE.Vector3()\n const matrix = new THREE.Matrix4()\n mesh.setColorAt(0, colour.setHex(0))\n for (let index = 0; index < RING_CAPACITY; index++) mesh.setMatrixAt(index, hidden)\n return {\n object: mesh,\n sync() {\n let drawn = false\n for (let index = 0; index < RING_CAPACITY; index++) {\n const ring = pool.rings[index]!\n if (!ring.on) {\n mesh.setMatrixAt(index, hidden)\n continue\n }\n drawn = true\n const k = Math.min(1, ring.t / ring.duration)\n const radius = ring.from + (ring.to - ring.from) * (1 - Math.pow(1 - k, 2))\n quaternion.setFromUnitVectors(forward, normal.set(ring.normal[0], ring.normal[1], ring.normal[2]))\n matrix.compose(position.set(ring.point[0], ring.point[1], ring.point[2]), quaternion, scale.set(radius, radius, 1))\n mesh.setMatrixAt(index, matrix)\n mesh.setColorAt(index, colour.setHex(ring.color).multiplyScalar(ring.hold ? ring.hold : 1 - k))\n }\n mesh.instanceMatrix.needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n return drawn\n },\n dispose() {\n geometry.dispose()\n material.dispose()\n },\n }\n}\n\n/**\n * Draws the pools of the world's Workshop engine (what `world.play` fills): the two sprite systems, the streaks, the physics debris, the decals, the\n * expanding rings and the flash and fire lights, with the page's shaders and materials.\n */\nexport function createWorkshopLayers(THREE: ThreeLib, engine: WorkshopEngine, pointScale: number, lightScale: number): WorkshopLayers {\n const group = new THREE.Group()\n group.name = 'workshop'\n const layers: Drawn[] = [\n spriteLayer(THREE, engine.add, true, 1, pointScale),\n spriteLayer(THREE, engine.normal, false, 0.55, pointScale),\n streakLayer(THREE, engine.streaks),\n rainLayer(THREE, engine.rain),\n debrisLayer(THREE, engine.debris),\n decalLayer(THREE, engine.decals),\n ringLayer(THREE, engine.rings),\n ]\n for (const layer of layers) group.add(layer.object)\n const meshes = createMeshLayer(THREE, engine.meshes)\n group.add(meshes.group)\n const flashLights = engine.lights.lights.map(() => new THREE.PointLight(0xffc070, 0, 14))\n const fireLights = engine.lights.fire.map(() => new THREE.PointLight(FIRE_LIGHT_COLOR, 0, FIRE_LIGHT_DISTANCE))\n for (const light of [...flashLights, ...fireLights]) group.add(light)\n return {\n group,\n sync() {\n let drawCalls = 0\n for (const layer of layers) if (layer.sync()) drawCalls++\n drawCalls += meshes.sync()\n engine.lights.lights.forEach((source, index) => {\n const light = flashLights[index]!\n light.position.set(source.x, source.y, source.z)\n light.color.setHex(source.color)\n light.distance = source.distance\n light.intensity = source.intensity * lightScale\n })\n engine.lights.fire.forEach((source, index) => {\n const light = fireLights[index]!\n light.position.set(source.x, source.y, source.z)\n light.intensity = source.intensity * lightScale\n })\n return drawCalls\n },\n dispose() {\n for (const layer of layers) layer.dispose()\n meshes.dispose()\n group.clear()\n },\n }\n}\n","import type * as THREE_NS from \"three\";\nimport type {\n BenchChange,\n BenchSheet,\n ChoiceOption,\n EffectHandle,\n EffectSink,\n ModuleControl,\n ModuleHost,\n ModuleLayer,\n ModuleMetric,\n TestableModule,\n} from \"@adatechnology/game-contracts\";\nimport {\n EVENT_BUDGET,\n EXPLOSIONS,\n GAME_EFFECTS,\n estimateCost,\n resolveStrings,\n} from \"@adatechnology/game-vfx\";\nimport type { EffectDef, ExplosionDef } from \"@adatechnology/game-vfx\";\nimport { createVfxRenderer, VFX_LAYERS } from \"../renderer\";\nimport type { ThreeLib, VfxRenderer } from \"../types\";\nimport { benchText } from \"./text\";\n\nexport interface VfxTestModuleOptions {\n readonly locale?: string;\n /** The recipes the bench lists (default `GAME_EFFECTS`) and the explosions (default `EXPLOSIONS`). */\n readonly effects?: Readonly<Record<string, EffectDef>>;\n readonly explosions?: Readonly<Record<string, ExplosionDef>>;\n /** Seconds between two replays while `auto_repeat` is on. */\n readonly repeatSeconds?: number;\n}\n\nconst DEFAULT_EFFECT = \"m67\";\n/** The profile the Lab falls back to for an unknown explosive: not something to pick. */\nconst FALLBACK_EXPLOSION = \"generic\";\nconst NO_VARIANT = \"none\";\nconst BLAST_POINT: readonly [number, number, number] = [0, 0.1, 0];\nconst DEFAULT_DISTANCE = 14;\nconst DEFAULT_REPEAT_SECONDS = 4;\nconst LIGHT_BUDGET = EVENT_BUDGET.blastLights + EVENT_BUDGET.fireLights;\nconst SEGMENT_COLORS = [\"#ffb347\", \"#ff7a2a\", \"#8a8f98\", \"#5c6370\"] as const;\n\nconst TEAMS = [\n \"creatures\",\n \"weapons\",\n \"destruction\",\n \"world\",\n \"vehicles\",\n \"screen\",\n] as const;\nconst LAYER_ID = \"show_\";\n\nconst humanize = (id: string): string => id.replace(/_/g, \" \");\n\n/** Where the bench stands for a distance (m): a three-quarter view that keeps the blast in frame. */\nconst eyeFor = (distance: number): [number, number, number] => [\n distance * 0.6,\n distance * 0.35 + 1.4,\n distance * 0.8,\n];\n\n/** The tick marks and segments of a sheet's timeline: an explosion's flash, fireball and smoke, or a recipe's time. */\nfunction timelineOf(\n explosion: ExplosionDef | undefined,\n recipe: EffectDef | undefined,\n metric: string,\n): NonNullable<BenchSheet[\"timeline\"]> {\n if (explosion) {\n const flash = explosion.flash.life ?? 0.2;\n const smoke = Math.max(explosion.smoke.life, 1);\n return {\n segments: [\n { name: \"flash\", start: 0, end: flash, color: SEGMENT_COLORS[0] },\n {\n name: \"fireball\",\n start: 0,\n end: Math.min(smoke, 2.4),\n color: SEGMENT_COLORS[1],\n },\n { name: \"smoke\", start: 0.4, end: smoke, color: SEGMENT_COLORS[2] },\n ],\n ticks: Array.from({ length: Math.ceil(smoke) }, (_, index) => index + 1),\n metric,\n };\n }\n const span = recipe?.loop && recipe.loop > 0 ? recipe.loop : 4;\n return {\n segments: [\n { name: recipe?.id ?? \"\", start: 0, end: span, color: SEGMENT_COLORS[1] },\n ],\n ticks: Array.from({ length: Math.floor(span) }, (_, index) => index + 1),\n metric,\n };\n}\n\n/**\n * The effects bench: pick an explosion or a recipe (listed by team), its variant, the distance, the quality and the layers, replay it or let it repeat,\n * and watch the particle and light counters against the budget. It plays through `host.effects` (the room's world) and, in a host without one, draws\n * into a renderer of its own.\n */\nexport function createVfxTestModule(\n options: VfxTestModuleOptions = {},\n): TestableModule {\n const locale = options.locale ?? \"en\";\n const recipes = options.effects ?? GAME_EFFECTS;\n const explosions = options.explosions ?? EXPLOSIONS;\n const text = benchText(locale);\n const strings = resolveStrings(locale);\n\n const effectOptions = (): ChoiceOption[] => [\n ...Object.keys(explosions)\n .filter((id) => id !== FALLBACK_EXPLOSION)\n .map((id) => ({\n id,\n name: humanize(id),\n group: strings.groups.explosions ?? text.sheet.explosion,\n })),\n // an id the explosions already use is the explosion's: the sink tries the explosions first, so the recipe of the same name could not be reached\n ...TEAMS.flatMap((team) =>\n Object.values(recipes)\n .filter((def) => def.team === team && !(def.id in explosions))\n .map((def) => ({\n id: def.id,\n name: strings.effects[def.id]?.name ?? humanize(def.id),\n group: strings.groups[def.team] ?? def.team,\n })),\n ),\n ];\n\n const sheetFor = (id: string): BenchSheet => {\n const explosion = explosions[id];\n if (explosion) {\n return {\n kicker: strings.groups.explosions ?? text.sheet.explosion,\n title: humanize(id),\n facts: [\n { label: text.sheet.lethal, value: `${explosion.lethal} m` },\n { label: text.sheet.injury, value: `${explosion.injury} m` },\n { label: text.sheet.radius, value: `${explosion.visualRadius} m` },\n { label: text.sheet.fireballs, value: String(explosion.fireballs) },\n {\n label: text.sheet.particles,\n value: `${estimateCost(explosion)} / ${EVENT_BUDGET.particles}`,\n },\n ],\n timeline: timelineOf(explosion, undefined, \"blast_time\"),\n };\n }\n const recipe = recipes[id];\n const words = strings.effects[id];\n const labels = strings.sheet;\n return {\n kicker: recipe ? (strings.groups[recipe.team] ?? recipe.team) : undefined,\n title: words?.name ?? humanize(id),\n ...(words ? { body: words.short } : {}),\n facts: words\n ? [{ label: labels.budget, value: `${words.cost} · ${words.costNote}` }]\n : [],\n steps: words\n ? [\n { at: labels.when, text: words.when },\n { at: labels.look, text: words.look },\n { at: labels.budget, text: words.budget },\n { at: labels.network, text: words.network },\n ]\n : [],\n timeline: timelineOf(undefined, recipe, \"phase\"),\n };\n };\n\n const controls = (): ModuleControl[] => [\n {\n kind: \"choice\",\n id: \"effect\",\n name: text.controls.effect,\n options: effectOptions(),\n default:\n DEFAULT_EFFECT in explosions ? DEFAULT_EFFECT : effectOptions()[0]!.id,\n },\n {\n kind: \"choice\",\n id: \"variant\",\n name: text.controls.variant,\n options: [{ id: NO_VARIANT, name: text.none }],\n default: NO_VARIANT,\n hidden: true,\n },\n { kind: \"action\", id: \"replay\", name: text.controls.replay },\n {\n kind: \"boolean\",\n id: \"auto_repeat\",\n name: text.controls.auto_repeat,\n default: false,\n },\n {\n kind: \"number\",\n id: \"distance\",\n name: text.controls.distance,\n min: 4,\n max: 120,\n step: 1,\n unit: \"m\",\n default: DEFAULT_DISTANCE,\n },\n {\n kind: \"choice\",\n id: \"lod_band\",\n name: text.controls.lod_band,\n options: ([\"auto\", \"near\", \"middle\", \"far\"] as const).map((id) => ({\n id,\n name: text.lod[id],\n })),\n default: \"auto\",\n },\n {\n kind: \"choice\",\n id: \"quality\",\n name: text.controls.quality,\n options: ([\"high\", \"medium\", \"low\"] as const).map((id) => ({\n id,\n name: text.quality[id],\n })),\n default: \"high\",\n },\n ];\n\n const layers = (): ModuleLayer[] =>\n VFX_LAYERS.map((id) => ({ id: `${LAYER_ID}${id}`, name: text.layers[id] }));\n\n /** The live counters: shared by `metrics` and filled by `attach` (a module without a host reads zeros). */\n let read: () => {\n stats: Readonly<Record<string, number>>;\n phase: number;\n budget: number;\n } = () => ({ stats: {}, phase: 0, budget: 0 });\n\n const metrics = (): ModuleMetric[] => [\n {\n id: \"puffs\",\n name: text.metrics.puffs,\n digits: 0,\n read: () => read().stats.puffs ?? 0,\n },\n {\n id: \"sparks\",\n name: text.metrics.sparks,\n digits: 0,\n read: () => read().stats.sparks ?? 0,\n },\n {\n id: \"debris\",\n name: text.metrics.debris,\n digits: 0,\n max: EVENT_BUDGET.debris,\n read: () => read().stats.chunks ?? 0,\n },\n {\n id: \"lights\",\n name: text.metrics.lights,\n digits: 0,\n max: LIGHT_BUDGET,\n read: () =>\n (read().stats.blastLights ?? 0) + (read().stats.fireLights ?? 0),\n },\n {\n id: \"budget_particles\",\n name: text.metrics.budget_particles,\n digits: 0,\n max: EVENT_BUDGET.particles,\n read: () => read().budget,\n },\n {\n id: \"lod\",\n name: text.metrics.lod,\n digits: 2,\n read: () => read().stats.lod ?? 1,\n },\n {\n id: \"phase\",\n name: text.metrics.phase,\n unit: \"s\",\n digits: 2,\n read: () => read().phase,\n },\n {\n id: \"blast_time\",\n name: text.metrics.blast_time,\n unit: \"s\",\n digits: 2,\n read: () => Math.max(0, read().stats.blastTime ?? 0),\n },\n ];\n\n return {\n id: \"vfx\",\n name: text.module,\n ground: { surface: 'dirt' },\n group: \"effects\",\n items: () => [],\n controls,\n layers,\n metrics,\n // opening the effects area puts the camera at the bench view (the initial distance does not move it: that would take the player's view on load)\n area: () => ({\n placements: [],\n view: { eye: eyeFor(DEFAULT_DISTANCE), target: [0, 1.2, 0] },\n }),\n attach(host: ModuleHost) {\n const bench = host.bench;\n let own: VfxRenderer | undefined;\n let sink: EffectSink | undefined = host.effects;\n if (!sink) {\n own = createVfxRenderer(host.THREE as ThreeLib, {\n scene: host.scene as THREE_NS.Scene,\n camera: host.camera as THREE_NS.PerspectiveCamera,\n });\n sink = own;\n }\n const effects = sink;\n let effect = \"m67\";\n let variant = NO_VARIANT;\n let distance = DEFAULT_DISTANCE;\n let auto = false;\n let phase = 0;\n let handle: EffectHandle | null = null;\n let sinceRepeat = 0;\n // The room hands a module its initial and restored values right after attach (`sendInitial`), in the same tick: those set the state\n // (effect, variant, sheet) but must not play. Playing starts with the first frame, i.e. with what the user does afterwards.\n let live = false;\n\n read = () => {\n const def = explosions[effect];\n const recipe = recipes[effect];\n const budget = def\n ? estimateCost(def)\n : (recipe?.budget.particles ?? 0);\n return { stats: effects.stats?.() ?? {}, phase, budget };\n };\n\n function replay(): void {\n if (handle !== null) effects.stop(handle);\n phase = 0;\n sinceRepeat = 0;\n handle = effects.play({\n effect,\n point: [BLAST_POINT[0], BLAST_POINT[1], BLAST_POINT[2]],\n direction: [1, 0.2, 0.4],\n normal: [0, 1, 0],\n ...(variant !== NO_VARIANT &&\n recipes[effect]?.params?.options.includes(variant)\n ? { param: variant }\n : {}),\n });\n }\n\n function choose(id: string): void {\n effect = id;\n const params = recipes[id]?.params;\n variant = params\n ? (params.options[params.default] ?? params.options[0] ?? NO_VARIANT)\n : NO_VARIANT;\n bench?.patch(\n \"variant\",\n params\n ? {\n hidden: false,\n options: params.options.map((option) => ({\n id: option,\n name: option,\n })),\n value: variant,\n }\n : {\n hidden: true,\n options: [{ id: NO_VARIANT, name: text.none }],\n value: NO_VARIANT,\n },\n );\n bench?.sheet?.(sheetFor(id));\n if (live) replay();\n }\n\n function look(): void {\n const eye = eyeFor(distance);\n bench?.look(eye, [0, 1.2, 0]);\n }\n\n const apply = (change: BenchChange): void => {\n if (change.kind === \"layer\")\n effects.configure?.({\n [`layer_${change.id.slice(LAYER_ID.length)}`]: change.on,\n });\n else if (change.kind === \"action\") {\n if (change.id === \"replay\") replay();\n } else if (change.id === \"effect\" && typeof change.value === \"string\")\n choose(change.value);\n else if (change.id === \"variant\" && typeof change.value === \"string\") {\n variant = change.value;\n if (live && recipes[effect]?.params) replay();\n } else if (change.id === \"auto_repeat\") auto = change.value === true;\n else if (change.id === \"distance\" && typeof change.value === \"number\") {\n distance = change.value;\n look();\n } else if (change.id === \"lod_band\" || change.id === \"quality\")\n effects.configure?.({ [change.id]: change.value });\n };\n const offChange = bench?.onChange(apply);\n const offFrame = host.onFrame((dt) => {\n live = true;\n phase += dt;\n sinceRepeat += dt;\n own?.update(dt);\n if (\n auto &&\n sinceRepeat >= (options.repeatSeconds ?? DEFAULT_REPEAT_SECONDS)\n )\n replay();\n });\n return () => {\n offChange?.();\n offFrame();\n if (handle !== null) effects.stop(handle);\n bench?.sheet?.(null);\n own?.dispose();\n read = () => ({ stats: {}, phase: 0, budget: 0 });\n };\n },\n };\n}\n","/** The words of the effects bench, per locale (the effects' own texts live in `@adatechnology/game-vfx`). */\nexport interface BenchText {\n readonly module: string\n readonly controls: Readonly<Record<'effect' | 'variant' | 'replay' | 'auto_repeat' | 'distance' | 'lod_band' | 'quality', string>>\n readonly lod: Readonly<Record<'auto' | 'near' | 'middle' | 'far', string>>\n readonly quality: Readonly<Record<'high' | 'medium' | 'low', string>>\n readonly layers: Readonly<Record<'puffs' | 'sparks' | 'glows' | 'debris' | 'shock' | 'sprites', string>>\n readonly metrics: Readonly<Record<'puffs' | 'sparks' | 'debris' | 'lights' | 'budget_particles' | 'lod' | 'phase' | 'blast_time', string>>\n readonly sheet: Readonly<Record<'explosion' | 'lethal' | 'injury' | 'radius' | 'fireballs' | 'particles' | 'scale', string>>\n readonly none: string\n}\n\nexport const benchTexts: Readonly<Record<string, BenchText>> = {\n en: {\n module: 'Effects',\n controls: { effect: 'Effect', variant: 'Variant', replay: 'Replay', auto_repeat: 'Auto replay', distance: 'Distance', lod_band: 'LOD band', quality: 'Quality' },\n lod: { auto: 'Auto', near: 'Near', middle: 'Middle', far: 'Far' },\n quality: { high: 'High', medium: 'Medium', low: 'Low' },\n layers: { puffs: 'Smoke and fire', sparks: 'Sparks', glows: 'Glows', debris: 'Debris', shock: 'Shock wave', sprites: 'Droplets and recipes' },\n metrics: { puffs: 'Puffs', sparks: 'Sparks', debris: 'Debris', lights: 'Lights', budget_particles: 'Particles of the effect', lod: 'LOD scale', phase: 'Time since replay', blast_time: 'Time since the blast' },\n sheet: { explosion: 'Explosion', lethal: 'Lethal radius', injury: 'Injury radius', radius: 'Fireball', fireballs: 'Fireballs', particles: 'Particles', scale: 'Scale' },\n none: 'None',\n },\n 'pt-BR': {\n module: 'Efeitos',\n controls: { effect: 'Efeito', variant: 'Variante', replay: 'Repetir', auto_repeat: 'Repetição automática', distance: 'Distância', lod_band: 'Faixa de LOD', quality: 'Qualidade' },\n lod: { auto: 'Automático', near: 'Perto', middle: 'Meio', far: 'Longe' },\n quality: { high: 'Alta', medium: 'Média', low: 'Baixa' },\n layers: { puffs: 'Fumaça e fogo', sparks: 'Faíscas', glows: 'Brilhos', debris: 'Destroços', shock: 'Onda de choque', sprites: 'Gotas e receitas' },\n metrics: { puffs: 'Nuvens', sparks: 'Faíscas', debris: 'Destroços', lights: 'Luzes', budget_particles: 'Partículas do efeito', lod: 'Escala de LOD', phase: 'Tempo desde a repetição', blast_time: 'Tempo desde a explosão' },\n sheet: { explosion: 'Explosão', lethal: 'Raio letal', injury: 'Raio de ferimento', radius: 'Bola de fogo', fireballs: 'Bolas de fogo', particles: 'Partículas', scale: 'Escala' },\n none: 'Nenhuma',\n },\n}\n\nexport const benchText = (locale: string): BenchText => benchTexts[locale] ?? benchTexts.en!\n","import type * as THREE_NS from 'three'\nimport type { GroundField } from '@adatechnology/game-vfx'\nimport type { ThreeLib } from './types'\n\nexport interface GroundPatchOptions {\n /** The height field the craters dig; the mesh follows it. */\n readonly field: GroundField\n /** What the patch is made of (default a plain flat-shaded grey standard material). */\n readonly material?: THREE_NS.Material\n /** Texture coordinates repeat every this many metres (the Lab's 17). */\n readonly textureMetres?: number\n}\n\nexport interface GroundPatch {\n readonly mesh: THREE_NS.Mesh\n /** Redraws the vertices when the field changed since the last call. Returns whether it did. */\n sync(): boolean\n dispose(): void\n}\n\nconst DEFAULT_TEXTURE_METRES = 17\n\n/** The Lab's 60 m deformable patch with 33 cm cells (L60-83), as a mesh that follows a `GroundField`. */\nexport function createGroundPatch(THREE: ThreeLib, options: GroundPatchOptions): GroundPatch {\n const field = options.field\n const metres = options.textureMetres ?? DEFAULT_TEXTURE_METRES\n const geometry = new THREE.PlaneGeometry(field.size, field.size, field.segments, field.segments).rotateX(-Math.PI / 2)\n const position = geometry.attributes.position!\n const uv = geometry.attributes.uv!\n for (let index = 0; index < position.count; index++) uv.setXY(index, position.getX(index) / metres, position.getZ(index) / metres)\n const material = options.material ?? new THREE.MeshStandardMaterial({ color: 0x2b2c2f, roughness: 0.93, flatShading: true })\n const mesh = new THREE.Mesh(geometry, material)\n mesh.receiveShadow = true\n let version = -1\n\n function sync(): boolean {\n if (field.version === version) return false\n version = field.version\n for (let index = 0; index < position.count; index++) position.setY(index, field.heights[index]!)\n position.needsUpdate = true\n geometry.computeBoundingSphere()\n return true\n }\n\n return {\n mesh,\n sync,\n dispose() {\n geometry.dispose()\n if (!options.material) material.dispose()\n },\n }\n}\n"],"mappings":"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","names":["clamp","layer","GROUND_COLOR","layer"]}