@woosh/meep-engine 3.46.0 → 3.49.0
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/build/bundle-worker-terrain.js +1 -1
- package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
- package/editor/actions/concrete/TransformModifyAction.js +10 -2
- package/editor/ecs/component/FieldDescriptor.js +15 -0
- package/editor/ecs/component/createObjectEditor.js +41 -12
- package/editor/ecs/component/editors/ecs/Transform64Editor.d.ts.map +1 -1
- package/editor/ecs/component/editors/ecs/Transform64Editor.js +77 -70
- package/editor/particles/effect/ParticleReferenceSimulation.d.ts +1 -2
- package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
- package/editor/particles/effect/ParticleReferenceSimulation.js +2 -4
- package/editor/tools/TransformToolV2.d.ts.map +1 -1
- package/editor/tools/TransformToolV2.js +4 -0
- package/editor/tools/v2/TransformControls.d.ts.map +1 -1
- package/editor/tools/v2/TransformControls.js +7 -0
- package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
- package/editor/view/ecs/EntityEditor.js +4 -2
- package/editor/view/particles/effect/ParticleGraphEditorView.js +1 -1
- package/package.json +1 -1
- package/src/core/collection/array/array_insert_at.d.ts +16 -0
- package/src/core/collection/array/array_insert_at.d.ts.map +1 -0
- package/src/core/collection/array/array_insert_at.js +32 -0
- package/src/core/collection/array/array_remove_at.d.ts +15 -0
- package/src/core/collection/array/array_remove_at.d.ts.map +1 -0
- package/src/core/collection/array/array_remove_at.js +30 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts +37 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_look_rotation.js +172 -0
- package/src/core/geom/Quaternion.d.ts +1 -0
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +12 -48
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +9 -4
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +27 -11
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +21 -0
- package/src/engine/ecs/transform/t64_look_rotation.d.ts +4 -4
- package/src/engine/ecs/transform/t64_look_rotation.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_look_rotation.js +7 -18
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +30 -1
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +2 -2
- package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -1
- package/src/engine/graphics/ecs/particles/ParticleEffect.js +7 -7
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +8 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +11 -3
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts +26 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts.map +1 -0
- package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.js +91 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -0
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +72 -29
- package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics3/GraphicsEngine.js +8 -1
- package/src/engine/graphics3/ParticipatingMedia.d.ts +84 -1
- package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMedia.js +139 -5
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +6 -2
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +29 -4
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts +10 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.js +38 -0
- package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -1
- package/src/engine/graphics3/ParticipatingMediaSystem.js +46 -3
- package/src/engine/input/devices/KeyboardDevice.d.ts +1 -0
- package/src/engine/input/devices/KeyboardDevice.d.ts.map +1 -1
- package/src/engine/input/devices/KeyboardDevice.js +7 -6
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.d.ts.map +1 -1
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +15 -2
- package/src/engine/network/CONGESTION_CONTROL.md +9 -9
- package/src/engine/network/MESSAGE_TRANSPORT.md +364 -0
- package/src/engine/network/NetworkSession.d.ts +47 -16
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +556 -292
- package/src/engine/network/README.md +104 -28
- package/src/engine/network/SMOOTHNESS_DESIGN.md +13 -5
- package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
- package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
- package/src/engine/network/orchestrator/HostJoin.d.ts +111 -0
- package/src/engine/network/orchestrator/HostJoin.d.ts.map +1 -0
- package/src/engine/network/orchestrator/HostJoin.js +271 -0
- package/src/engine/network/orchestrator/NetworkPeer.d.ts +151 -112
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +450 -499
- package/src/engine/network/orchestrator/PendingSlices.d.ts +30 -0
- package/src/engine/network/orchestrator/PendingSlices.d.ts.map +1 -0
- package/src/engine/network/orchestrator/PendingSlices.js +83 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts +34 -0
- package/src/engine/network/orchestrator/ReliableFrames.d.ts.map +1 -0
- package/src/engine/network/orchestrator/ReliableFrames.js +96 -0
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +77 -10
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +236 -61
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +59 -23
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +213 -198
- package/src/engine/network/replication/Replicator.d.ts +15 -4
- package/src/engine/network/replication/Replicator.d.ts.map +1 -1
- package/src/engine/network/replication/Replicator.js +57 -17
- package/src/engine/network/sim/ActionLog.d.ts +32 -5
- package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
- package/src/engine/network/sim/ActionLog.js +47 -5
- package/src/engine/network/sim/SimActionExecutor.d.ts +42 -2
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +100 -4
- package/src/engine/network/sim/Snapshotter.d.ts +12 -0
- package/src/engine/network/sim/Snapshotter.d.ts.map +1 -1
- package/src/engine/network/sim/Snapshotter.js +43 -0
- package/src/engine/network/state/Baseline.d.ts +1 -1
- package/src/engine/network/state/Baseline.js +1 -1
- package/src/engine/network/state/FrameBufferRing.d.ts +25 -6
- package/src/engine/network/state/FrameBufferRing.d.ts.map +1 -1
- package/src/engine/network/state/FrameBufferRing.js +51 -6
- package/src/engine/network/state/InputRing.d.ts +4 -0
- package/src/engine/network/state/InputRing.d.ts.map +1 -1
- package/src/engine/network/state/InputRing.js +7 -0
- package/src/engine/network/state/RecordArrivalRing.d.ts +57 -0
- package/src/engine/network/state/RecordArrivalRing.d.ts.map +1 -0
- package/src/engine/network/state/RecordArrivalRing.js +144 -0
- package/src/engine/network/transport/DeferredTransport.d.ts.map +1 -1
- package/src/engine/network/transport/DeferredTransport.js +1 -0
- package/src/engine/network/transport/LoopbackTransport.d.ts.map +1 -1
- package/src/engine/network/transport/LoopbackTransport.js +4 -2
- package/src/engine/network/transport/Transport.d.ts +7 -0
- package/src/engine/network/transport/Transport.d.ts.map +1 -1
- package/src/engine/network/transport/Transport.js +8 -0
- package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/NodeUDPTransport.js +20 -5
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +8 -0
- package/src/engine/network/transport/adapters/WebTransportTransport.d.ts.map +1 -1
- package/src/engine/network/transport/adapters/WebTransportTransport.js +6 -0
- package/src/engine/network/transport/connection/Connection.d.ts +191 -0
- package/src/engine/network/transport/connection/Connection.d.ts.map +1 -0
- package/src/engine/network/transport/connection/Connection.js +1262 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts +94 -0
- package/src/engine/network/transport/connection/RangeSet.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RangeSet.js +260 -0
- package/src/engine/network/transport/connection/RxStream.d.ts +48 -0
- package/src/engine/network/transport/connection/RxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/RxStream.js +211 -0
- package/src/engine/network/transport/connection/TxStream.d.ts +90 -0
- package/src/engine/network/transport/connection/TxStream.d.ts.map +1 -0
- package/src/engine/network/transport/connection/TxStream.js +243 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts +17 -0
- package/src/engine/network/transport/connection/bytes_copy.d.ts.map +1 -0
- package/src/engine/network/transport/connection/bytes_copy.js +34 -0
- package/src/engine/network/transport/connection/varint.d.ts +46 -0
- package/src/engine/network/transport/connection/varint.d.ts.map +1 -0
- package/src/engine/network/transport/connection/varint.js +107 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +354 -0
- package/src/engine/physics/cloth/PLAN.md +85 -5
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +0 -12
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +0 -13
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +2 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +7 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +4 -15
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +2 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +6 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +20 -10
- package/src/engine/physics/cloth/playground/collide.html +5 -3
- package/src/engine/physics/cloth/playground/collide_main.js +14 -13
- package/src/engine/physics/cloth/solver/ClothState.d.ts +30 -2
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +62 -4
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +11 -3
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_self_find.js +52 -11
- package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts +42 -0
- package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_self_radius.js +64 -0
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +99 -24
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +102 -25
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +5 -1
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +13 -3
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +0 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -14
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +23 -4
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +36 -8
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +4 -2
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts +38 -7
- package/src/engine/sound/ecs/audio/AudioEmitter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitter.js +35 -7
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSerializationUpgrader_0_1.js +48 -0
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts +12 -2
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +173 -9
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts +9 -3
- package/src/engine/sound/ecs/audio/LiveEmitterSet.d.ts.map +1 -1
- package/src/engine/sound/ecs/audio/LiveEmitterSet.js +28 -8
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts +8 -0
- package/src/engine/sound/ecs/trigger/AudioEventTrigger.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationAdapter.js +5 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts +18 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSerializationUpgrader_0_1.js +51 -0
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.d.ts.map +1 -1
- package/src/engine/sound/ecs/trigger/AudioEventTriggerSystem.js +15 -1
- package/src/engine/sound/sopra/README.md +768 -644
- package/src/engine/sound/sopra/SopraEngine.d.ts +104 -8
- package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
- package/src/engine/sound/sopra/SopraEngine.js +327 -12
- package/src/engine/sound/sopra/definition/EventDescription.d.ts +28 -2
- package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescription.js +55 -5
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts +10 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationAdapter.js +77 -55
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts +31 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.d.ts.map +1 -0
- package/src/engine/sound/sopra/definition/EventDescriptionSerializationUpgrader_0_1.js +75 -0
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts +38 -9
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/AbstractAudioEffect.js +34 -5
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts +7 -2
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/CompressorEffect.js +137 -122
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts +3 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/EqEffect.js +146 -131
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts +1 -0
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.d.ts.map +1 -1
- package/src/engine/sound/sopra/definition/effect/ReverbEffect.js +6 -1
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts +44 -2
- package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/BusGraph.js +83 -43
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts +96 -0
- package/src/engine/sound/sopra/runtime/EffectChain.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectChain.js +286 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts +123 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.d.ts.map +1 -0
- package/src/engine/sound/sopra/runtime/EffectParamOverrides.js +320 -0
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts +55 -5
- package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
- package/src/engine/sound/sopra/runtime/EventInstance.js +201 -26
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts +2 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/populateSopraSerializationRegistry.js +6 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts +15 -0
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.d.ts.map +1 -1
- package/src/engine/sound/sopra/serialization/sopraSerializationHarness.js +32 -0
- package/src/engine/sound/sopra/util/MockAudioContext.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/MockAudioContext.js +3 -0
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts +13 -3
- package/src/engine/sound/sopra/util/fadeOutAndStop.d.ts.map +1 -1
- package/src/engine/sound/sopra/util/fadeOutAndStop.js +25 -13
- package/src/shade/RENDERER_CONTRACT.md +6 -3
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts +24 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.d.ts.map +1 -0
- package/src/shade/device/SHADE_DEVICE_FLOOR.js +34 -0
- package/src/shade/device/ShadeDeviceFailure.d.ts +12 -5
- package/src/shade/device/ShadeDeviceFailure.d.ts.map +1 -1
- package/src/shade/device/ShadeDeviceFailure.js +17 -8
- package/src/shade/device/ShadeDeviceFailureReason.d.ts +1 -1
- package/src/shade/device/ShadeDeviceFailureReason.js +2 -2
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts +15 -0
- package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
- package/src/shade/device/mock/SoftwareGPUDevice.js +21 -0
- package/src/shade/device/pipeline/ComputePipelineManager.d.ts +20 -0
- package/src/shade/device/pipeline/ComputePipelineManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/ComputePipelineManager.js +80 -6
- package/src/shade/device/pipeline/PipelineEnquiry.d.ts +52 -0
- package/src/shade/device/pipeline/PipelineEnquiry.d.ts.map +1 -0
- package/src/shade/device/pipeline/PipelineEnquiry.js +63 -0
- package/src/shade/device/pipeline/RenderPipelineManager.d.ts +21 -0
- package/src/shade/device/pipeline/RenderPipelineManager.d.ts.map +1 -1
- package/src/shade/device/pipeline/RenderPipelineManager.js +84 -4
- package/src/shade/device/shade_device_floor_unmet.d.ts +13 -0
- package/src/shade/device/shade_device_floor_unmet.d.ts.map +1 -0
- package/src/shade/device/shade_device_floor_unmet.js +32 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts +137 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/ContactShadowLab.js +654 -0
- package/src/shade/playground/contact_shadows/README.md +126 -0
- package/src/shade/playground/contact_shadows/index.html +191 -0
- package/src/shade/playground/contact_shadows/main.d.ts +2 -0
- package/src/shade/playground/contact_shadows/main.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/main.js +888 -0
- package/src/shade/playground/contact_shadows/scenes.d.ts +48 -0
- package/src/shade/playground/contact_shadows/scenes.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/scenes.js +620 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts +36 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_composite.js +245 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts +15 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_reference.js +120 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts +55 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_stats.js +216 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts +20 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_lab_view.js +114 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts +11 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/shader_contact_shadow_march.js +90 -0
- package/src/shade/playground/contact_shadows/textures.d.ts +16 -0
- package/src/shade/playground/contact_shadows/textures.d.ts.map +1 -0
- package/src/shade/playground/contact_shadows/textures.js +123 -0
- package/src/shade/playground/particle_ecs/README.md +1 -1
- package/src/shade/playground/particle_ecs/effects/flame.json +1932 -1881
- package/src/shade/playground/particle_ecs/effects/smoke.json +99 -1
- package/src/shade/playground/particle_ecs/effects/soot.json +152 -145
- package/src/shade/playground/tonemap_sdr/README.md +90 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts +105 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +380 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts +32 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.js +104 -0
- package/src/shade/playground/tonemap_sdr/index.html +90 -0
- package/src/shade/playground/tonemap_sdr/main.d.ts +2 -0
- package/src/shade/playground/tonemap_sdr/main.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/main.js +306 -0
- package/src/shade/playground/tonemap_sdr/scenes.d.ts +26 -0
- package/src/shade/playground/tonemap_sdr/scenes.d.ts.map +1 -0
- package/src/shade/playground/tonemap_sdr/scenes.js +404 -0
- package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/main.js +85 -4
- package/src/shade/playground/water_refraction/README.md +26 -18
- package/src/shade/playground/water_refraction/index.html +1 -1
- package/src/shade/renderer/Renderer.d.ts +37 -3
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +237 -67
- package/src/shade/renderer/ShadeToneMappingMode.d.ts +14 -0
- package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +1 -0
- package/src/shade/renderer/ShadeToneMappingMode.js +30 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +9 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +14 -0
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +5 -3
- package/src/shade/renderer/buffer/GPUBufferAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferAllocator.js +9 -0
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts +21 -12
- package/src/shade/renderer/buffer/buffer_pool_ops.d.ts.map +1 -1
- package/src/shade/renderer/buffer/buffer_pool_ops.js +18 -19
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts +7 -0
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +12 -0
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts +8 -0
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +12 -0
- package/src/shade/renderer/camera/GPUCameraContext.d.ts.map +1 -1
- package/src/shade/renderer/camera/GPUCameraContext.js +19 -8
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_read_gBuffer_material.js +4 -0
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.js +4 -0
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.d.ts.map +1 -1
- package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.js +4 -0
- package/src/shade/renderer/deferred/shader_deferred_main.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_deferred_main.js +3 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts +6 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_HDR.js +13 -3
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts +9 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_none.js +63 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts +10 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.js +87 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts +6 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts.map +1 -1
- package/src/shade/renderer/deferred/shader_tonemap_LDR.js +23 -5
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts +9 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_none.js +68 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts +10 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts.map +1 -0
- package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.js +73 -0
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +58 -9
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +35 -25
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +97 -196
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +121 -129
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.js +3 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.js +4 -0
- package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.js +3 -0
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.js +4 -0
- package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.js +4 -0
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.js +4 -0
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +131 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts +7 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.js +45 -38
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts +2 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.js +81 -79
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts +2 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.js +5 -3
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts +21 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.js +42 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts +19 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.js +44 -0
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts +23 -5
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +139 -23
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts +25 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.js +179 -0
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +7 -16
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts +3 -4
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +6 -23
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts +11 -0
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +14 -3
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.js +13 -3
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +14 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts +26 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.js +52 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts +32 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.js +89 -0
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +10 -0
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +20 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/test/gpu_test.js +8 -11
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +10 -0
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +294 -281
- package/src/shade/renderer/light/GPULightCollection.d.ts +8 -0
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +18 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts +8 -0
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +234 -218
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts +7 -0
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +13 -0
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts +7 -0
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts.map +1 -1
- package/src/shade/renderer/light/cluster/graph_build_light_clusters.js +16 -2
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +10 -0
- package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/execute_filter_environment_map.js +13 -0
- package/src/shade/renderer/lightmap/GPULightMap.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/GPULightMap.js +3 -0
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +4 -0
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.d.ts.map +1 -1
- package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +4 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +16 -4
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +38 -8
- package/src/shade/renderer/particles/DESIGN.md +49 -7
- package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +453 -0
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +5 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +13 -5
- package/src/shade/renderer/particles/data/particle_emitter_record.js +2 -2
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +12 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts +60 -0
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +156 -0
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +2 -2
- package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
- package/src/shade/renderer/particles/runtime/ParticleEmitter.js +8 -8
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +6 -4
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +7 -6
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +91 -58
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +10 -0
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +5 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts.map +1 -1
- package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +6 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts +24 -0
- package/src/shade/renderer/pool/TransientResourcePool.d.ts.map +1 -1
- package/src/shade/renderer/pool/TransientResourcePool.js +41 -10
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts +7 -0
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +18 -0
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.js +1 -0
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.js +6 -4
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +11 -0
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +16 -0
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +10 -0
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +16 -0
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +32 -10
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +3 -0
- package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.js +6 -3
- package/src/shade/renderer/postprocess/taa/TAA.d.ts +12 -0
- package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/taa/TAA.js +15 -0
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts +7 -0
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +13 -0
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts +31 -3
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/TemplatePassDescriptor.js +79 -4
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts +17 -0
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.js +35 -4
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts +7 -0
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +182 -169
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.js +20 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.js +18 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +20 -1
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts +7 -0
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +187 -170
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +19 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts +13 -0
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +25 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts +10 -0
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +20 -0
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -0
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +7 -2
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +12 -4
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js +4 -3
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js +4 -3
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts +2 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +11 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +4 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +4 -3
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts +15 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +35 -2
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts +14 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +32 -4
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts +17 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +34 -4
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts +5 -3
- package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/chunk_restir_resolve.js +8 -3
- package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/graph_restir_di.js +1 -0
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
- package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +5 -1
- package/src/shade/renderer/restir/reservoir/shader.d.ts.map +1 -1
- package/src/shade/renderer/restir/reservoir/shader.js +7 -4
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +7 -0
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +13 -1
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +10 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +19 -0
- package/src/shade/renderer/scene/SceneManager.d.ts +9 -0
- package/src/shade/renderer/scene/SceneManager.d.ts.map +1 -1
- package/src/shade/renderer/scene/SceneManager.js +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.js +17 -0
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts +11 -0
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts.map +1 -1
- package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.js +18 -1
- package/src/shade/renderer/shader/ComputeShader.d.ts +12 -0
- package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ComputeShader.js +71 -2
- package/src/shade/renderer/shader/ImageShader.d.ts +27 -8
- package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
- package/src/shade/renderer/shader/ImageShader.js +299 -218
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts +21 -0
- package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
- package/src/shade/renderer/shader/ShaderDescriptor.js +71 -1
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts +17 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.js +45 -0
- package/src/shade/renderer/shader/chunk/camera/chunk_screen_coordinate_to_view.js +3 -3
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts +1 -1
- package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js +62 -62
- package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +318 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +237 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts +17 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js +22 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts +14 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.js +28 -15
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.js +128 -110
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts +20 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.js +33 -0
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts +4 -0
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.js +12 -1
- package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.js +7 -0
- package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +108 -0
- package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.js +23 -4
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts +18 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.js +56 -0
- package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.js +2 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts +43 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.js +319 -0
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +33 -0
- package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
- package/src/shade/renderer/shader/compiler/CodeChunk.js +140 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts +74 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/CodeChunkChoice.js +166 -0
- package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +680 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts +86 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitch.js +178 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts +67 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts.map +1 -0
- package/src/shade/renderer/shader/compiler/ShaderSwitchSet.js +205 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts +14 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.js +13 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts +65 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.js +252 -0
- package/src/shade/renderer/shadow/contact/FINDINGS.md +413 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.js +105 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.js +39 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.js +92 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts +29 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.js +128 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts +52 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts.map +1 -0
- package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.js +358 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts +10 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.js +12 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts +13 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.js +14 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +14 -8
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +20 -86
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts +14 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts.map +1 -0
- package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.js +79 -0
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.js +12 -12
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
- package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +153 -151
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts +13 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts.map +1 -0
- package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.js +48 -0
- package/src/shade/renderer/texture/GPUTextureContext.d.ts +10 -0
- package/src/shade/renderer/texture/GPUTextureContext.d.ts.map +1 -1
- package/src/shade/renderer/texture/GPUTextureContext.js +24 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts +219 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts.map +1 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.js +671 -0
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts +26 -2
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +108 -4
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +5 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +6 -0
- package/src/shade/renderer/volumetrics/NOTES.md +50 -0
- package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.js +30 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +51 -13
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +98 -13
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +9 -0
- package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/SceneVolumetrics.js +78 -68
- package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +326 -0
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts +7 -4
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.js +21 -9
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts +19 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.js +53 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +12 -3
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +85 -48
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +4 -1
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +4 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +4 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +21 -1
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts +98 -0
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.js +115 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts +9 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.js +24 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts +27 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.js +91 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts +35 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.js +92 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts +10 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.js +121 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +38 -3
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +311 -290
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.js +28 -49
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +3 -1
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +24 -18
- package/src/shade/renderer/water/chunk_water_transport.d.ts +0 -1
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_transport.js +0 -17
- package/src/shade/renderer/water/shader_water.d.ts +4 -2
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +27 -16
- package/src/shade/renderer/water/shader_water_avboit.d.ts +0 -4
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water_avboit.js +0 -63
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +43 -9
- package/src/view/graphics/GraphicsContextFailureView.d.ts +1 -2
- package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
- package/src/view/graphics/GraphicsContextFailureView.js +1 -2
- package/src/engine/network/transport/Channel.d.ts +0 -85
- package/src/engine/network/transport/Channel.d.ts.map +0 -1
- package/src/engine/network/transport/Channel.js +0 -336
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts +0 -155
- package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +0 -1
- package/src/engine/network/transport/ReliableCommandPipeline.js +0 -335
- package/src/engine/network/transport/fragments/FragmentAssembler.d.ts +0 -105
- package/src/engine/network/transport/fragments/FragmentAssembler.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/FragmentAssembler.js +0 -350
- package/src/engine/network/transport/fragments/FragmentRetention.d.ts +0 -103
- package/src/engine/network/transport/fragments/FragmentRetention.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/FragmentRetention.js +0 -191
- package/src/engine/network/transport/fragments/fragment_send.d.ts +0 -61
- package/src/engine/network/transport/fragments/fragment_send.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/fragment_send.js +0 -157
- package/src/engine/network/transport/fragments/packet_size.d.ts +0 -99
- package/src/engine/network/transport/fragments/packet_size.d.ts.map +0 -1
- package/src/engine/network/transport/fragments/packet_size.js +0 -107
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts +0 -6
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.js +0 -16
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts +0 -7
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.js +0 -46
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts +0 -10
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.js +0 -127
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts +0 -7
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.js +0 -39
|
@@ -1,644 +1,768 @@
|
|
|
1
|
-
# Sopra
|
|
2
|
-
|
|
3
|
-
An object-oriented, data-driven sound engine for the meep ECS, loosely modelled on FMOD / Wwise
|
|
4
|
-
concepts (events, a mixer bus tree, RTPC parameters, voice stealing, snapshots, ducking) but built
|
|
5
|
-
around meep's own data model instead of an opaque middleware bank.
|
|
6
|
-
|
|
7
|
-
Sopra is **ECS-agnostic at its core**. The engine (`SopraEngine` + its services) knows nothing about
|
|
8
|
-
entities; it is a self-contained audio renderer driven by a single clock. A thin ECS layer
|
|
9
|
-
(`AudioEmitter` + `AudioEmitterSystem`, outside this folder under `sound/ecs/audio/`) binds it to the
|
|
10
|
-
game. You can use the core standalone (tools, previews, tests) with nothing but a `BaseAudioContext`
|
|
11
|
-
and a `BufferProvider`.
|
|
12
|
-
|
|
13
|
-
> The name "sopra" is internal. The player-facing / integration layer uses familiar terms
|
|
14
|
-
> (`AudioEmitter`, `AudioEventTrigger`); "sopra" never appears in user-facing API.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## The one idea you must understand: definition vs. runtime
|
|
19
|
-
|
|
20
|
-
Everything in Sopra is split into two halves. Get this and the rest follows.
|
|
21
|
-
|
|
22
|
-
| | **Definition** (authored data) | **Runtime** (transient playback) |
|
|
23
|
-
|---|---|---|
|
|
24
|
-
| What | `EventDescription`, the `*AudioClip` graph, `BusDefinition`, `*AudioEffect`, `ParameterDefinition`, `MixerSnapshot`, `DuckingRule` | `EventInstance`, `Voice`, the live WebAudio node graph |
|
|
25
|
-
| Lifetime | Immutable, shared, **serializable** (save/load, network) | Created on trigger, pooled, **never serialized** |
|
|
26
|
-
| Holds | Spec only — urls, gains in dB, curves, child clips, routing | WebAudio nodes, the resolved timeline, the playhead, RNG state |
|
|
27
|
-
| Lives in | `definition/` | `runtime/` |
|
|
28
|
-
|
|
29
|
-
A definition is a recipe. Playing it spawns a transient `EventInstance` that reads the recipe once,
|
|
30
|
-
resolves a concrete timeline of leaf plays, and drives WebAudio nodes. The same definition can back
|
|
31
|
-
many simultaneous instances. **Definitions never hold playback state** — that is the rule the whole
|
|
32
|
-
architecture defends.
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
EventDescription (definition)
|
|
36
|
-
│ engine.playEvent(...)
|
|
37
|
-
▼
|
|
38
|
-
EventInstance (runtime) ──spawns──► Voice ──► bus chain ──► destination
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## Directory map
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
sopra/
|
|
47
|
-
SopraEngine.js the facade: owns the bus graph, parameters, active instances, the clock
|
|
48
|
-
definition/ immutable, serializable authored data (+ co-located *SerializationAdapter.js)
|
|
49
|
-
EventDescription.js the triggerable unit (root clip + routing + 3D + voice config)
|
|
50
|
-
BusDefinition.js one node in the mixer tree (gain, effect chain, aux sends)
|
|
51
|
-
ParameterDefinition.js a declared RTPC parameter
|
|
52
|
-
MixerSnapshot.js a named set of per-bus target gains
|
|
53
|
-
DuckingRule.js an emulated sidechain duck (trigger bus → target bus)
|
|
54
|
-
SopraPanningModel.js HRTF | EqualPower
|
|
55
|
-
VoiceStealMode.js None | Oldest | Quietest
|
|
56
|
-
clip/ the clip graph — what actually makes sound
|
|
57
|
-
AbstractAudioClip.js base; planTimeline() + loops() + collectSampleClips()
|
|
58
|
-
SampleAudioClip.js a single audio asset (the only buffer-referencing leaf)
|
|
59
|
-
SilenceAudioClip.js dead air (a gap in a sequence)
|
|
60
|
-
SequenceContainerAudioClip.js plays children in order
|
|
61
|
-
RandomContainerAudioClip.js plays one child at weighted random (avoid-repeat)
|
|
62
|
-
SwitchContainerAudioClip.js plays one child chosen by a parameter (discrete)
|
|
63
|
-
BlendContainerAudioClip.js plays several children, gains driven by a parameter (continuous)
|
|
64
|
-
effect/ bus
|
|
65
|
-
AbstractAudioEffect.js base; build(ctx) → { input, output }
|
|
66
|
-
EqEffect.js BiquadFilter
|
|
67
|
-
CompressorEffect.js DynamicsCompressor
|
|
68
|
-
ReverbEffect.js Convolver (procedural impulse response)
|
|
69
|
-
runtime/ transient playback state
|
|
70
|
-
EventInstance.js one triggered playing of an event (cursor-based scheduler)
|
|
71
|
-
Voice.js / VoicePool.js one pooled AudioBufferSourceNode + its gain/detune
|
|
72
|
-
BusGraph.js instantiates BusDefinitions into chained WebAudio nodes
|
|
73
|
-
VoiceManager.js per-event instance limits + voice stealing
|
|
74
|
-
ParameterStore.js live RTPC values + change bindings
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
import {
|
|
99
|
-
import {
|
|
100
|
-
import {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
frame();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
AnimationCurve.linear(0,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
>
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
import {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
- `oneShot:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
inst.
|
|
295
|
-
inst.
|
|
296
|
-
inst.
|
|
297
|
-
inst.
|
|
298
|
-
|
|
299
|
-
inst.
|
|
300
|
-
|
|
301
|
-
inst.
|
|
302
|
-
inst.
|
|
303
|
-
inst.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
```js
|
|
360
|
-
engine.
|
|
361
|
-
engine.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
`
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
---
|
|
455
|
-
|
|
456
|
-
##
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
engine.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
`
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
1
|
+
# Sopra
|
|
2
|
+
|
|
3
|
+
An object-oriented, data-driven sound engine for the meep ECS, loosely modelled on FMOD / Wwise
|
|
4
|
+
concepts (events, a mixer bus tree, RTPC parameters, voice stealing, snapshots, ducking) but built
|
|
5
|
+
around meep's own data model instead of an opaque middleware bank.
|
|
6
|
+
|
|
7
|
+
Sopra is **ECS-agnostic at its core**. The engine (`SopraEngine` + its services) knows nothing about
|
|
8
|
+
entities; it is a self-contained audio renderer driven by a single clock. A thin ECS layer
|
|
9
|
+
(`AudioEmitter` + `AudioEmitterSystem`, outside this folder under `sound/ecs/audio/`) binds it to the
|
|
10
|
+
game. You can use the core standalone (tools, previews, tests) with nothing but a `BaseAudioContext`
|
|
11
|
+
and a `BufferProvider`.
|
|
12
|
+
|
|
13
|
+
> The name "sopra" is internal. The player-facing / integration layer uses familiar terms
|
|
14
|
+
> (`AudioEmitter`, `AudioEventTrigger`); "sopra" never appears in user-facing API.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## The one idea you must understand: definition vs. runtime
|
|
19
|
+
|
|
20
|
+
Everything in Sopra is split into two halves. Get this and the rest follows.
|
|
21
|
+
|
|
22
|
+
| | **Definition** (authored data) | **Runtime** (transient playback) |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| What | `EventDescription`, the `*AudioClip` graph, `BusDefinition`, `*AudioEffect`, `ParameterDefinition`, `MixerSnapshot`, `DuckingRule` | `EventInstance`, `Voice`, the live WebAudio node graph |
|
|
25
|
+
| Lifetime | Immutable, shared, **serializable** (save/load, network) | Created on trigger, pooled, **never serialized** |
|
|
26
|
+
| Holds | Spec only — urls, gains in dB, curves, child clips, routing | WebAudio nodes, the resolved timeline, the playhead, RNG state |
|
|
27
|
+
| Lives in | `definition/` | `runtime/` |
|
|
28
|
+
|
|
29
|
+
A definition is a recipe. Playing it spawns a transient `EventInstance` that reads the recipe once,
|
|
30
|
+
resolves a concrete timeline of leaf plays, and drives WebAudio nodes. The same definition can back
|
|
31
|
+
many simultaneous instances. **Definitions never hold playback state** — that is the rule the whole
|
|
32
|
+
architecture defends.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
EventDescription (definition)
|
|
36
|
+
│ engine.playEvent(...)
|
|
37
|
+
▼
|
|
38
|
+
EventInstance (runtime) ──spawns──► Voice ──► bus chain ──► destination
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Directory map
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
sopra/
|
|
47
|
+
SopraEngine.js the facade: owns the bus graph, parameters, active instances, the clock
|
|
48
|
+
definition/ immutable, serializable authored data (+ co-located *SerializationAdapter.js)
|
|
49
|
+
EventDescription.js the triggerable unit (root clip + routing + 3D + voice config)
|
|
50
|
+
BusDefinition.js one node in the mixer tree (gain, effect chain, aux sends)
|
|
51
|
+
ParameterDefinition.js a declared RTPC parameter
|
|
52
|
+
MixerSnapshot.js a named set of per-bus target gains
|
|
53
|
+
DuckingRule.js an emulated sidechain duck (trigger bus → target bus)
|
|
54
|
+
SopraPanningModel.js HRTF | EqualPower
|
|
55
|
+
VoiceStealMode.js None | Oldest | Quietest
|
|
56
|
+
clip/ the clip graph — what actually makes sound
|
|
57
|
+
AbstractAudioClip.js base; planTimeline() + loops() + collectSampleClips()
|
|
58
|
+
SampleAudioClip.js a single audio asset (the only buffer-referencing leaf)
|
|
59
|
+
SilenceAudioClip.js dead air (a gap in a sequence)
|
|
60
|
+
SequenceContainerAudioClip.js plays children in order
|
|
61
|
+
RandomContainerAudioClip.js plays one child at weighted random (avoid-repeat)
|
|
62
|
+
SwitchContainerAudioClip.js plays one child chosen by a parameter (discrete)
|
|
63
|
+
BlendContainerAudioClip.js plays several children, gains driven by a parameter (continuous)
|
|
64
|
+
effect/ insert effects, on a bus or on an event
|
|
65
|
+
AbstractAudioEffect.js base; static parameters; build(ctx) → { input, output, params? }
|
|
66
|
+
EqEffect.js BiquadFilter
|
|
67
|
+
CompressorEffect.js DynamicsCompressor
|
|
68
|
+
ReverbEffect.js Convolver (procedural impulse response)
|
|
69
|
+
runtime/ transient playback state
|
|
70
|
+
EventInstance.js one triggered playing of an event (cursor-based scheduler)
|
|
71
|
+
Voice.js / VoicePool.js one pooled AudioBufferSourceNode + its gain/detune
|
|
72
|
+
BusGraph.js instantiates BusDefinitions into chained WebAudio nodes
|
|
73
|
+
VoiceManager.js per-event instance limits + voice stealing
|
|
74
|
+
ParameterStore.js live RTPC values + change bindings
|
|
75
|
+
EffectParamOverrides.js an owner's effect parameters, put onto each instance it gets
|
|
76
|
+
SopraPlaybackContext.js per-source seeded RNG + random-container history (determinism)
|
|
77
|
+
asset/ how the engine gets decoded buffers
|
|
78
|
+
BufferProvider.js the interface (tryGet sync / get async)
|
|
79
|
+
AssetManagerBufferProvider.js production: pulls from the meep AssetManager
|
|
80
|
+
StubBufferProvider.js in-memory, for tests / offline
|
|
81
|
+
serialization/ sopraJSON (type-tag JSON dispatch) + the binary registry + test harness
|
|
82
|
+
util/ buildAttenuationCurve, fadeOutAndStop, MockAudioContext
|
|
83
|
+
legacy/ frozen SoundEmitter/SoundController readers + the converter that
|
|
84
|
+
turns saved ones into AudioEmitter / AudioEventTrigger
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The ECS binding lives **outside** this folder, under `sound/ecs/audio/`: `AudioEmitter.js` (component),
|
|
88
|
+
`AudioEmitterSystem.js` (system), and the spatial-scaling layer `SpatialAudioIndex.js` (BVH cull) +
|
|
89
|
+
`LiveEmitterSet.js` (live/dormant budget) that lets it carry ~100k 3D emitters (see ECS integration).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Quick start (standalone)
|
|
94
|
+
|
|
95
|
+
The core needs three things: an audio context, a destination node, and a `BufferProvider`.
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
import { SopraEngine } from "./SopraEngine.js";
|
|
99
|
+
import { BufferProvider } from "./asset/BufferProvider.js";
|
|
100
|
+
import { EventDescription } from "./definition/EventDescription.js";
|
|
101
|
+
import { SampleAudioClip } from "./definition/clip/SampleAudioClip.js";
|
|
102
|
+
|
|
103
|
+
// 1. Tell Sopra how to obtain decoded AudioBuffers. Here, a trivial in-memory provider.
|
|
104
|
+
class MapBufferProvider extends BufferProvider {
|
|
105
|
+
constructor(map) { super(); this.map = map; } // Map<url, AudioBuffer>
|
|
106
|
+
tryGet(url, usingAlias) { return this.map.get(url) ?? null; } // sync fast path (already decoded)
|
|
107
|
+
get(url, usingAlias) { // async path (rejects if unavailable)
|
|
108
|
+
const b = this.map.get(url);
|
|
109
|
+
return b ? Promise.resolve(b) : Promise.reject(new Error(`missing ${url}`));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const ctx = new AudioContext();
|
|
114
|
+
const buffers = new Map([["click.ogg", await ctx.decodeAudioData(bytes)]]);
|
|
115
|
+
const engine = new SopraEngine(ctx, ctx.destination, new MapBufferProvider(buffers));
|
|
116
|
+
|
|
117
|
+
// 2. Describe an event (a definition). Reuse it as many times as you like.
|
|
118
|
+
const click = EventDescription.from("ui.click", SampleAudioClip.from("click.ogg"), { busId: "effects" });
|
|
119
|
+
|
|
120
|
+
// 3. Play it. playOneShot auto-releases when the sound finishes.
|
|
121
|
+
engine.playOneShot(click);
|
|
122
|
+
|
|
123
|
+
// 4. Drive the engine once per frame — this is mandatory (see "The update loop").
|
|
124
|
+
function frame() { engine.update(); requestAnimationFrame(frame); }
|
|
125
|
+
frame();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`SopraEngine` ships with a default bus tree — `master` → (`effects`, `music`, `ambient`) — at the
|
|
129
|
+
legacy mix, so `busId: "effects"` works out of the box.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## The clip graph
|
|
134
|
+
|
|
135
|
+
`EventDescription.rootClip` is a tree of `AbstractAudioClip` nodes. Each node implements
|
|
136
|
+
`planTimeline()`, which the instance calls **once** at trigger time to flatten the tree into a list of
|
|
137
|
+
timed leaf plays. Gain (dB) and pitch (cents) accumulate additively down the tree and are resolved
|
|
138
|
+
there — the runtime never sees an "inherit" sentinel.
|
|
139
|
+
|
|
140
|
+
Only `SampleAudioClip` references a buffer; everything else arranges, selects, or layers.
|
|
141
|
+
|
|
142
|
+
### SampleAudioClip — a single asset (leaf)
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
SampleAudioClip.from("explosion.ogg", {
|
|
146
|
+
gain: -3, // dB, added to the event/parent gain
|
|
147
|
+
pitch: 0, // cents
|
|
148
|
+
loop: false,
|
|
149
|
+
loopStart: 0, loopEnd: 0,
|
|
150
|
+
pitchRandom: 50, // ± cents, randomised per trigger (deterministic, see below)
|
|
151
|
+
gainRandom: 2, // ± dB, randomised per trigger
|
|
152
|
+
usingAlias: false // if true, `url` is an AssetManager alias, not a path
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
A `loop: true` sample plays forever — it makes its event a **persistent source** (see one-shot
|
|
157
|
+
vs. persistent below).
|
|
158
|
+
|
|
159
|
+
### SilenceAudioClip — a gap
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
SilenceAudioClip.from(0.5); // 0.5s of dead air, e.g. between sequence steps
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### SequenceContainerAudioClip — children in order
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
SequenceContainerAudioClip.from([
|
|
169
|
+
SampleAudioClip.from("intro.ogg"),
|
|
170
|
+
SilenceAudioClip.from(0.25),
|
|
171
|
+
SampleAudioClip.from("loop.ogg", { loop: true }) // a looping child is terminal: the sequence
|
|
172
|
+
]); // cannot advance past it
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### RandomContainerAudioClip — one child at weighted random
|
|
176
|
+
|
|
177
|
+
Picks one child per trigger, avoiding the last N picks. Weights are **per-child, one entry per child**
|
|
178
|
+
(default `1` = uniform); a weight of `0` means "never picked".
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
RandomContainerAudioClip.from(
|
|
182
|
+
[SampleAudioClip.from("step1.ogg"), SampleAudioClip.from("step2.ogg"), SampleAudioClip.from("step3.ogg")],
|
|
183
|
+
{ avoidRepeatingLast: 1, weights: [3, 1, 1] } // step1 ~3× as likely; never the same twice in a row
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Selection is **deterministic** given a seed (see Determinism) — critical for networked play.
|
|
188
|
+
|
|
189
|
+
### SwitchContainerAudioClip — one child by a parameter (discrete)
|
|
190
|
+
|
|
191
|
+
Reads a parameter once at trigger, rounds + clamps it to a child index. Classic surface-switch:
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
SwitchContainerAudioClip.from(
|
|
195
|
+
[grassClip, stoneClip, woodClip],
|
|
196
|
+
{ parameter: "surface", defaultValue: 0 } // surface 0→grass, 1→stone, 2→wood
|
|
197
|
+
);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### BlendContainerAudioClip — several children, gains by a parameter (continuous)
|
|
201
|
+
|
|
202
|
+
Reads a parameter once at trigger and plays every child whose blend gain is > 0, each scaled by its
|
|
203
|
+
per-child `AnimationCurve` (parameter value → linear gain). A child with no curve is always full.
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
import { AnimationCurve } from "../../animation/curve/AnimationCurve.js";
|
|
207
|
+
|
|
208
|
+
BlendContainerAudioClip.from(
|
|
209
|
+
[calmLayer, stormLayer],
|
|
210
|
+
{
|
|
211
|
+
parameter: "weather",
|
|
212
|
+
blends: [
|
|
213
|
+
AnimationCurve.linear(0, 1, 1, 0), // calm: full at 0, silent at 1
|
|
214
|
+
AnimationCurve.linear(0, 0, 1, 1) // storm: silent at 0, full at 1
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
> v1 Blend is a **trigger-time snapshot**: the mix is fixed when the event starts; it does not
|
|
221
|
+
> re-blend live as the parameter sweeps afterwards. Live per-voice re-blend is a planned follow-up.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Events
|
|
226
|
+
|
|
227
|
+
`EventDescription` is the triggerable unit. It wraps a root clip with routing, 3D, and voice config.
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
import { SopraPanningModel } from "./definition/SopraPanningModel.js";
|
|
231
|
+
import { VoiceStealMode } from "./definition/VoiceStealMode.js";
|
|
232
|
+
|
|
233
|
+
EventDescription.from("monster.roar", rootClip, {
|
|
234
|
+
busId: "effects", // which mixer bus this routes to
|
|
235
|
+
gainDb: 0, // event master gain
|
|
236
|
+
is3D: true, // enable spatialization
|
|
237
|
+
panningModel: SopraPanningModel.HRTF,
|
|
238
|
+
distanceMin: 2, // panner reference distance
|
|
239
|
+
distanceMax: 60, // beyond this the source is culled (virtualized)
|
|
240
|
+
attenuation: AnimationCurve.linear(0, 1, 60, 0), // distance → linear gain multiplier
|
|
241
|
+
maxInstances: 8, // concurrency cap for this event
|
|
242
|
+
priority: 0,
|
|
243
|
+
stealMode: VoiceStealMode.Oldest,
|
|
244
|
+
virtualThresholdDb: -60, // below this post-attenuation gain a voice goes virtual
|
|
245
|
+
effects: [] // the event's own insert effects — see "Event effects"
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Non-3D events ignore the 3D fields; `attenuation` defaults to a flat-1 curve (no attenuation).
|
|
250
|
+
|
|
251
|
+
An `EventDescription` is a plain object — hold it wherever you like (a module constant, a component
|
|
252
|
+
field, a map of your own) and pass it straight to the playback methods:
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
engine.playOneShot(roar, { position: monsterPos });
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Playback and instance control
|
|
261
|
+
|
|
262
|
+
`playEvent` / `playOneShot` / `createInstance` / `crossfade` all take an `EventDescription` directly —
|
|
263
|
+
there is no id registry. Keep a reference to the description and pass it in.
|
|
264
|
+
|
|
265
|
+
```js
|
|
266
|
+
// fire-and-forget; auto-releases when the content finishes
|
|
267
|
+
engine.playOneShot(click);
|
|
268
|
+
|
|
269
|
+
// keep the handle to control it; persistent until you stop it
|
|
270
|
+
const inst = engine.playEvent(music, { busId: "music" });
|
|
271
|
+
|
|
272
|
+
// build without starting (e.g. to configure first), then start manually
|
|
273
|
+
const i = engine.createInstance(music);
|
|
274
|
+
i.start(engine.currentTime);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`playEvent` returns the `EventInstance`, or **`null`** if the play was denied by the voice limit
|
|
278
|
+
(steal mode `None`). Always handle the null.
|
|
279
|
+
|
|
280
|
+
### One-shot vs. persistent
|
|
281
|
+
|
|
282
|
+
- `oneShot: true` (what `playOneShot` sets) — the instance **self-releases** when its timeline
|
|
283
|
+
finishes, and is killed by a `maxLifetime` backstop (default 60s) as a safety net.
|
|
284
|
+
- `oneShot: false` (default for `playEvent`) — the instance **persists** until you stop it. Use this
|
|
285
|
+
for looping music/ambience (whose root clip loops). A *non-looping*, non-one-shot instance plays
|
|
286
|
+
once then sits idle (silent) until stopped — usually not what you want, so loop the clip or use
|
|
287
|
+
`playOneShot`.
|
|
288
|
+
|
|
289
|
+
The ECS `AudioEmitterSystem` derives `oneShot` automatically from `event.rootClip.loops()`.
|
|
290
|
+
|
|
291
|
+
### EventInstance API
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
inst.setGainDb(-6); // immediate volume (dB), composes with 3D attenuation
|
|
295
|
+
inst.fadeToGainDb(0, 2); // click-safe ramp to 0 dB over 2s (does not stop)
|
|
296
|
+
inst.fadeOutAndStop(1.5); // fade to silence over 1.5s, then stop (audio-clock deadline)
|
|
297
|
+
inst.seek(10); // jump the playhead to 10s (keeps the resolved timeline + RNG)
|
|
298
|
+
inst.restart(); // seek(0)
|
|
299
|
+
inst.stop(); // stop now, tear down nodes, fire onEnded
|
|
300
|
+
|
|
301
|
+
inst.playhead; // current position in seconds
|
|
302
|
+
inst.gainDb; // current instance gain (dB)
|
|
303
|
+
inst.state; // EventInstanceState: Initial | Playing | Stopped
|
|
304
|
+
inst.currentGain; // current post-attenuation linear gain
|
|
305
|
+
inst.onEnded.add(i => { ... }); // fires once when the instance fully stops
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Crossfade
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
// fade `current` out and a fresh play of `calmTrack` in, over 3s
|
|
312
|
+
const next = engine.crossfade(current, calmTrack, { busId: "music", duration: 3 });
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Buses, effects, and sends
|
|
318
|
+
|
|
319
|
+
The mixer is a tree of `BusDefinition`s. Each bus is `input → effect[0] → … → effect[n] → gain`, and
|
|
320
|
+
its output routes into its parent's input (or the engine destination for a root bus, `parentId: ""`).
|
|
321
|
+
|
|
322
|
+
`setBuses` **replaces** the whole tree (and rebuilds the WebAudio graph). Effects and sends are wired
|
|
323
|
+
at build time; there is no live effect insertion — but an effect's *parameters* move live (below).
|
|
324
|
+
|
|
325
|
+
Every bus of the new tree starts at its **defined** gain, which resets any fader moved since (a player's
|
|
326
|
+
volume setting, a bound parameter). That is right when the new tree *is* the new mix. To change the
|
|
327
|
+
tree without touching the mix — adding a bus to the one the player has been adjusting — pass
|
|
328
|
+
`keepVolumes`: buses in both trees keep their faders (and any engaged duck), new ones start at their
|
|
329
|
+
definition.
|
|
330
|
+
|
|
331
|
+
```js
|
|
332
|
+
engine.setBuses([...SopraEngine.defaultBuses(), worldBus], { keepVolumes: true });
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
```js
|
|
336
|
+
import { BusDefinition } from "./definition/BusDefinition.js";
|
|
337
|
+
import { EqEffect, EqFilterType } from "./definition/effect/EqEffect.js";
|
|
338
|
+
import { CompressorEffect } from "./definition/effect/CompressorEffect.js";
|
|
339
|
+
import { ReverbEffect } from "./definition/effect/ReverbEffect.js";
|
|
340
|
+
|
|
341
|
+
engine.setBuses([
|
|
342
|
+
BusDefinition.from("master", { gainDb: 0 }), // root (parentId "")
|
|
343
|
+
BusDefinition.from("music", { parentId: "master", gainDb: -6,
|
|
344
|
+
effects: [CompressorEffect.from({ threshold: -18, ratio: 4 })] }),
|
|
345
|
+
BusDefinition.from("sfx", { parentId: "master",
|
|
346
|
+
effects: [EqEffect.from({ filterType: EqFilterType.Highshelf, frequency: 6000, gainDb: -3 })],
|
|
347
|
+
sends: [{ targetBusId: "reverb", levelDb: -9 }] }), // post-fader aux send
|
|
348
|
+
BusDefinition.from("reverb", { parentId: "master", // a "reverb bus": others send to it
|
|
349
|
+
effects: [ReverbEffect.from({ decaySeconds: 2.0, decayPower: 2 })] })
|
|
350
|
+
]);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
A **send** routes a post-fader copy of a bus into another bus at a given level — the standard way to
|
|
354
|
+
share one reverb across many sources. `ReverbEffect` generates its impulse response procedurally
|
|
355
|
+
(decaying noise), so there is no IR asset to load and `build` stays synchronous.
|
|
356
|
+
|
|
357
|
+
Live bus volume (linear gain):
|
|
358
|
+
|
|
359
|
+
```js
|
|
360
|
+
engine.getBusVolume("music"); // → linear gain
|
|
361
|
+
engine.setBusVolume("music", 0.5);
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Live effect parameters. An effect is addressed by its index in the bus's `effects`, a parameter by one
|
|
365
|
+
of its class's `parameters` — the definition field it starts from (`EqEffect.parameters`: `frequency`,
|
|
366
|
+
`Q`, `gainDb`; `CompressorEffect`: `threshold`, `knee`, `ratio`, `attack`, `release`; `ReverbEffect` has
|
|
367
|
+
none). The move lands on the bus's built copy; the definition is never written. The verbs are the
|
|
368
|
+
fader's: `set` moves it now, `approach` glides there exponentially (a time constant, like ducking), and
|
|
369
|
+
whatever was in flight is cancelled and held first, so a value sent every frame retargets smoothly.
|
|
370
|
+
("Effect param" = a live `AudioParam` of an insert; a sopra *parameter* is a named game value,
|
|
371
|
+
`setParameter`.)
|
|
372
|
+
|
|
373
|
+
```js
|
|
374
|
+
engine.setBusEffectParam("sfx", 0, "gainDb", -9);
|
|
375
|
+
engine.approachBusEffectParam("sfx", 0, "gainDb", -3, 0.05);
|
|
376
|
+
engine.getBusEffectParam("sfx", 0, "gainDb"); // → -3 (where it was sent, not where the glide has got to)
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Event effects
|
|
380
|
+
|
|
381
|
+
An `EventDescription` carries insert effects of its own — the same effect types, in `effects`. Every
|
|
382
|
+
instance builds its own copy, **pre-fader**: `voices → effects → instance gain → (3D chain) → bus`. So
|
|
383
|
+
one play of a cue can sound different from the next without touching the bus everything else shares:
|
|
384
|
+
|
|
385
|
+
```js
|
|
386
|
+
const hurt = EventDescription.from("player.hurt", SampleAudioClip.from("hurt.ogg"), {
|
|
387
|
+
effects: [EqEffect.from({ filterType: EqFilterType.Lowpass, frequency: 20000 })]
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// a light blow sounds dull, a heavy one bright — this play only
|
|
391
|
+
const instance = engine.playOneShot(hurt, { position });
|
|
392
|
+
instance?.setEffectParam(0, "frequency", lightBlow ? 1200 : 20000);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
`setEffectParam` / `approachEffectParam` / `getEffectParam` work from the moment the instance exists, while its buffers are
|
|
396
|
+
still loading included. (`playOneShot` returns `null` when the event's instance limit denies the play.)
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Parameters (RTPC)
|
|
401
|
+
|
|
402
|
+
Named float values that drive selection (`Switch`/`Blend`) and automation. They live in the
|
|
403
|
+
`ParameterStore`; `Switch`/`Blend` read them **once at trigger time**.
|
|
404
|
+
|
|
405
|
+
```js
|
|
406
|
+
engine.defineParameter("surface", 0); // declare with a default (no-op if already defined)
|
|
407
|
+
engine.setParameter("surface", 1); // 1 → the next footstep Switch picks child 1 (stone)
|
|
408
|
+
engine.getParameter("surface"); // → 1
|
|
409
|
+
|
|
410
|
+
// Drive a bus volume from a parameter through a curve — updates live as the parameter changes.
|
|
411
|
+
engine.bindParameterToBusVolume("tension", "music", AnimationCurve.linear(0, 0.2, 1, 1));
|
|
412
|
+
engine.setParameter("tension", 0.8); // music bus volume follows the curve immediately
|
|
413
|
+
|
|
414
|
+
// Or bind an arbitrary callback (runs on change, and once now if already set).
|
|
415
|
+
engine.bindParameter("tension", value => console.log("tension is", value));
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Note the timing difference: bus-volume and bus-effect bindings update **live**; clip selection
|
|
419
|
+
(`Switch`/`Blend`) is sampled **when the event is triggered**, so changing a parameter affects the *next*
|
|
420
|
+
play, not voices already sounding.
|
|
421
|
+
|
|
422
|
+
### Binding a bus effect to a parameter
|
|
423
|
+
|
|
424
|
+
A bus effect parameter binds the way a bus volume does: the game sets one sopra parameter, and how far
|
|
425
|
+
the effect moves for it is authored in an `AnimationCurve` (parameter value → effect value, in the effect
|
|
426
|
+
parameter's own units), not worked out in game code. The address is the one `setBusEffectParam` takes.
|
|
427
|
+
An optional time constant makes each change a glide (`approachBusEffectParam`), so a value set every
|
|
428
|
+
frame is tracked smoothly.
|
|
429
|
+
|
|
430
|
+
```js
|
|
431
|
+
// the world muffles as health runs out: open at full health, 500 Hz at none
|
|
432
|
+
engine.defineParameter("health", 1);
|
|
433
|
+
engine.bindParameterToBusEffectParam("health", "world", 0, "frequency",
|
|
434
|
+
AnimationCurve.linear(0, 500, 1, 20000), 0.05);
|
|
435
|
+
|
|
436
|
+
engine.setParameter("health", 0.25); // the world's lowpass glides toward 5375 Hz
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
A binding is a standing rule, not one move:
|
|
440
|
+
|
|
441
|
+
- The address is checked when you bind: a bus, effect or parameter the current tree lacks throws there.
|
|
442
|
+
The parameter's value takes hold at once, without a glide — now if it has one, else when it is first
|
|
443
|
+
defined or set; only later changes glide.
|
|
444
|
+
- Every tree `setBuses` builds that has the target starts **at the bound value**, with `keepVolumes` or
|
|
445
|
+
without — a rebuilt effect does not sit at its definition until the parameter next changes.
|
|
446
|
+
- Over a tree without the target the binding does nothing, and holds again over the next tree that has
|
|
447
|
+
it. Bindings cannot be removed, so they outlive a tree swap; a mistyped address is caught at the bind.
|
|
448
|
+
- One binding per parameter and target: binding the pair again replaces its curve and time constant and
|
|
449
|
+
moves the effect to the new curve as a change would — it adds nothing, so binding again after a
|
|
450
|
+
`setBuses` that keeps the target is harmless (the address is still checked: one the tree lacks throws).
|
|
451
|
+
- The address is positional: reorder a bus's `effects` and the binding follows whatever sits at its index.
|
|
452
|
+
- A direct `setBusEffectParam` on a bound effect holds until the parameter next changes.
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## 3D / spatialization
|
|
457
|
+
|
|
458
|
+
Set the listener position, give 3D events a position, call `update()` each frame, and say when either
|
|
459
|
+
moves. An instance is placed and attenuated when it starts, and again only after a reported move: a
|
|
460
|
+
crowd standing still costs no Web Audio writes.
|
|
461
|
+
|
|
462
|
+
```js
|
|
463
|
+
engine.setListener(camera.position); // held by reference, read by index
|
|
464
|
+
|
|
465
|
+
const inst = engine.playOneShot(roar, { position: monster.position });
|
|
466
|
+
// `position` is held by reference too, and read only when told it moved:
|
|
467
|
+
monster.position.set(4, 0, 9);
|
|
468
|
+
inst.moved(); // the next update() re-places and re-attenuates it
|
|
469
|
+
|
|
470
|
+
camera.position.set(0, 2, 5);
|
|
471
|
+
engine.setListener(camera.position); // a listener move: every 3D instance re-attenuates
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
A write nobody reports is not heard. Give each instance a position of its own: instances sharing one
|
|
475
|
+
array are all wherever it was last written.
|
|
476
|
+
|
|
477
|
+
Per instance, distance attenuation is a custom gain node driven by `attenuation.evaluate(distance)`;
|
|
478
|
+
the `PannerNode` does direction only (rolloff disabled). Beyond `distanceMax`, or below
|
|
479
|
+
`virtualThresholdDb`, the instance goes **virtual**: its voices stop while the playhead keeps
|
|
480
|
+
advancing, and revive at the correct child + buffer offset when it becomes audible again.
|
|
481
|
+
|
|
482
|
+
Virtualization bounds the *voice* (source-node) count among the **live** instances. The bigger lever
|
|
483
|
+
for huge worlds is one tier up, in the ECS layer: the `LiveEmitterSet` keeps all-but-a-budget of the
|
|
484
|
+
registered 3D emitters **dormant** (not even an `EventInstance`), so a scene can register ~100k
|
|
485
|
+
emitters and still tick only ~budget of them. See **ECS integration**.
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Voice limits and stealing
|
|
490
|
+
|
|
491
|
+
`VoiceManager` caps concurrent instances **per event** at `EventDescription.maxInstances` and steals
|
|
492
|
+
when full, per the event's `stealMode`:
|
|
493
|
+
|
|
494
|
+
- `None` — over the limit, the new play is dropped (`playEvent` returns `null`).
|
|
495
|
+
- `Oldest` — stop the earliest-started instance.
|
|
496
|
+
- `Quietest` — stop the instance with the lowest post-attenuation gain.
|
|
497
|
+
|
|
498
|
+
Defaults (`maxInstances: 32`, `stealMode: Oldest`) effectively never engage until content opts into a
|
|
499
|
+
low limit — e.g. a machine-gun: `maxInstances: 6`.
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Mixer snapshots and ducking
|
|
504
|
+
|
|
505
|
+
### Snapshots — shift the whole mix between game states
|
|
506
|
+
|
|
507
|
+
A `MixerSnapshot` is a named set of per-bus target gains (dB). Apply it instantly or as a click-safe
|
|
508
|
+
ramp.
|
|
509
|
+
|
|
510
|
+
```js
|
|
511
|
+
import { MixerSnapshot } from "./definition/MixerSnapshot.js";
|
|
512
|
+
|
|
513
|
+
const combat = MixerSnapshot.from("combat", [
|
|
514
|
+
{ busId: "music", gainDb: 0 },
|
|
515
|
+
{ busId: "ambient", gainDb: -12 }
|
|
516
|
+
]);
|
|
517
|
+
|
|
518
|
+
engine.applySnapshot(combat, { duration: 1.5 }); // ramp into the combat mix over 1.5s
|
|
519
|
+
const saved = engine.captureSnapshot("pre-combat", ["music", "ambient"]); // grab the current mix to restore later
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Ducking — emulated sidechain
|
|
523
|
+
|
|
524
|
+
WebAudio has no native sidechain, so this is **play-state** ducking: while any instance is live on the
|
|
525
|
+
trigger bus, the target bus is attenuated by `duckDb` (smooth `setTargetAtTime` attack/release),
|
|
526
|
+
restored to its captured nominal when the trigger goes quiet.
|
|
527
|
+
|
|
528
|
+
```js
|
|
529
|
+
import { DuckingRule } from "./definition/DuckingRule.js";
|
|
530
|
+
|
|
531
|
+
// duck music by 8 dB whenever anything plays on the effects bus
|
|
532
|
+
engine.addDucker(DuckingRule.from({
|
|
533
|
+
triggerBusId: "effects", targetBusId: "music",
|
|
534
|
+
duckDb: -8, attack: 0.1, release: 0.4
|
|
535
|
+
}));
|
|
536
|
+
|
|
537
|
+
engine.clearDuckers(); // remove all rules (restoring any currently-ducked target)
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
The trigger matches by `instance.busId`. Duckers are evaluated every `update()`.
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
## Determinism
|
|
545
|
+
|
|
546
|
+
Random selection (`RandomContainer`, per-trigger pitch/gain randomisation) runs on a **seeded** RNG
|
|
547
|
+
held in a `SopraPlaybackContext`. Same seed → identical pick stream → networked clients stay in sync.
|
|
548
|
+
|
|
549
|
+
```js
|
|
550
|
+
// seed from a replicated source, e.g. entity id + fixed-step tick
|
|
551
|
+
engine.playEvent(footsteps, { seed: entityId * 31 + tick });
|
|
552
|
+
|
|
553
|
+
// or supply your own context (its history persists across re-triggers — reuse one per emitter)
|
|
554
|
+
import { SopraPlaybackContext } from "./runtime/SopraPlaybackContext.js";
|
|
555
|
+
const ctx = new SopraPlaybackContext(seed);
|
|
556
|
+
engine.playEvent(footsteps, { playbackContext: ctx });
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
If you supply neither, the engine's shared `defaultPlaybackContext` is used.
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## The update loop
|
|
564
|
+
|
|
565
|
+
`SopraEngine` is driven by a single clock — the injected `AudioContext.currentTime`. **You must call
|
|
566
|
+
`engine.update()` once per frame.** It advances every instance (scheduling/virtualization, 3D
|
|
567
|
+
attenuation, fade-out deadlines, one-shot release) and evaluates ducking rules.
|
|
568
|
+
|
|
569
|
+
```js
|
|
570
|
+
engine.update(); // uses the live clock
|
|
571
|
+
engine.update(someTime); // or pass an explicit context time (tests do this)
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
Nothing self-schedules with `setTimeout`; fades and stops are resolved against the audio clock inside
|
|
575
|
+
`update`, so a late frame never desynchronises audio.
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## Serialization
|
|
580
|
+
|
|
581
|
+
Definitions are fully serializable, two ways:
|
|
582
|
+
|
|
583
|
+
**JSON** — every definition has `toJSON()` / `fromJSON()`. Polymorphic clip/effect trees go through
|
|
584
|
+
type-tagged dispatch in `serialization/sopraJSON.js`:
|
|
585
|
+
|
|
586
|
+
```js
|
|
587
|
+
const json = description.toJSON();
|
|
588
|
+
const restored = new EventDescription();
|
|
589
|
+
restored.fromJSON(json);
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
**Binary** — each class has a co-located `<Class>SerializationAdapter.js`. Register them all — with
|
|
593
|
+
the upgraders that read their older formats (e.g. an `EventDescription` saved before events had
|
|
594
|
+
`effects`) — on a `BinarySerializationRegistry` with `populateSopraSerializationRegistry`:
|
|
595
|
+
|
|
596
|
+
```js
|
|
597
|
+
import { BinarySerializationRegistry } from "../../ecs/storage/binary/BinarySerializationRegistry.js";
|
|
598
|
+
import { populateSopraSerializationRegistry } from "./serialization/populateSopraSerializationRegistry.js";
|
|
599
|
+
|
|
600
|
+
const registry = new BinarySerializationRegistry();
|
|
601
|
+
populateSopraSerializationRegistry(registry);
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Numeric fields are stored as float32. `serialization/sopraSerializationHarness.js` provides
|
|
605
|
+
`makeSopraObjectAdapter()` + `binaryRoundTrip()` for round-trip tests.
|
|
606
|
+
|
|
607
|
+
---
|
|
608
|
+
|
|
609
|
+
## ECS integration
|
|
610
|
+
|
|
611
|
+
In-game you almost never touch `SopraEngine` directly — you add an `AudioEmitter` component.
|
|
612
|
+
|
|
613
|
+
```js
|
|
614
|
+
import { AudioEmitter } from "../ecs/audio/AudioEmitter.js";
|
|
615
|
+
|
|
616
|
+
const emitter = new AudioEmitter();
|
|
617
|
+
emitter.event = EventDescription.from(
|
|
618
|
+
"torch.loop", SampleAudioClip.from("torch.ogg", { loop: true }),
|
|
619
|
+
{ busId: "ambient", is3D: true, distanceMax: 20 }
|
|
620
|
+
);
|
|
621
|
+
emitter.autoplay = true; // this is a looping 3D event -> spatially managed (sounds when the
|
|
622
|
+
// listener is in range + within budget); see the two play paths below
|
|
623
|
+
emitter.volume.set(0.8); // live multiplier on top of the event gain (Vector1)
|
|
624
|
+
|
|
625
|
+
entity.add(emitter).add(new Transform(...));
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
`AudioEmitter` **owns a full `EventDescription`** — the whole clip graph, routing, 3D, voice config —
|
|
629
|
+
as first-class ECS data. There is no global "bank"; the `EntityComponentDataset` *is* the data store.
|
|
630
|
+
|
|
631
|
+
`AudioEmitterSystem(assetManager, soundEngine, liveEmitterSetOptions?)` drives all emitters. It shares
|
|
632
|
+
the one `SopraEngine` (via `SoundEngine.createSopra(bufferProvider)`, idempotent), feeds the
|
|
633
|
+
`SoundListener` pose, and ticks the engine each frame. *How* an emitter plays is decided **once at
|
|
634
|
+
link**, from `autoplay` + the event:
|
|
635
|
+
|
|
636
|
+
- **Spatially managed** — `autoplay && is3D && looping`. Registered with a `LiveEmitterSet` (a BVH
|
|
637
|
+
broadphase, `SpatialAudioIndex`, + a live/dormant lifecycle) and left **dormant**: no instance, no
|
|
638
|
+
nodes, no per-frame work — just one BVH leaf. Each frame the system culls by the listener position and
|
|
639
|
+
promotes the nearest in-range emitters up to a global voice **budget** (default 64), demoting the rest
|
|
640
|
+
(a hard cut when culled out of range, a click-safe fade on contention). This is what lets the engine
|
|
641
|
+
carry **~100,000 registered emitters** while only the audible ~budget ever hold WebAudio nodes — the
|
|
642
|
+
per-frame cost tracks the budget, not the registered count.
|
|
643
|
+
- **Direct** — any other `autoplay` event (2D sounds like music / ambience beds, or finite 3D
|
|
644
|
+
one-shots): played immediately on link, stopped on unlink. Nothing to cull by distance, and these are
|
|
645
|
+
few.
|
|
646
|
+
- **Inert** — `autoplay === false`: neither played nor registered.
|
|
647
|
+
|
|
648
|
+
The entity's `Transform64` translation is held by the instance, which follows the entity when its
|
|
649
|
+
transform announces a move (`t64_announce_change`), as the rendered row does — and so does the
|
|
650
|
+
`SoundListener` entity's;
|
|
651
|
+
`AudioEmitter.volume` is a live multiplier carried **through** promote/demote, so a managed emitter
|
|
652
|
+
keeps its volume across a cull. `system.instanceFor(entity)` returns the active instance (or `null`
|
|
653
|
+
while dormant).
|
|
654
|
+
|
|
655
|
+
### Per-emitter effect parameters
|
|
656
|
+
|
|
657
|
+
An instance of a managed emitter lives only as long as its promotion: demoted, it is torn down; promoted
|
|
658
|
+
again, a new one is built from the event. A parameter moved on `instanceFor(entity)` goes with the
|
|
659
|
+
instance it was moved on. To move an effect *for the emitter*, use `AudioEmitter.effectOverrides`: the
|
|
660
|
+
system moves whichever instance is current, and builds every new one at the overrides, not at the
|
|
661
|
+
event's definition.
|
|
662
|
+
|
|
663
|
+
```js
|
|
664
|
+
// one torch muffled as a door shuts on it; every other torch playing the same event stays bright
|
|
665
|
+
emitter.effectOverrides.approach(0, "frequency", 900, 0.1); // glide the live instance, if any
|
|
666
|
+
emitter.effectOverrides.set(0, "Q", 2); // move it now
|
|
667
|
+
emitter.effectOverrides.remove(0, "frequency"); // back to the event's own value
|
|
668
|
+
emitter.effectOverrides.clear(); // drop them all
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
Addressed as `EventInstance.setEffectParam` addresses the instance's own copy (effect index in the
|
|
672
|
+
event's `effects`, one of the class's `parameters`), and checked against the event where it is written:
|
|
673
|
+
on a linked emitter a parameter the event does not have throws at the `set`, and is not kept; overrides
|
|
674
|
+
written before the link are checked by the link, which throws instead of playing. Values are checked too,
|
|
675
|
+
in every build (not by `assert`). So nothing that is held can trip a later promotion, and a dormant
|
|
676
|
+
emitter's override simply waits for it. Clear the overrides before re-adding the component with another
|
|
677
|
+
event, and keep the event as it is while the emitter is linked, dormant included. One entity per
|
|
678
|
+
`AudioEmitter`: the overrides follow one playing instance, and a second link of the same component throws.
|
|
679
|
+
|
|
680
|
+
Overrides are **live state**, like `volume`: never saved, and outside `equals`/`hash`, so two emitters
|
|
681
|
+
differing only in a turned filter are still one polyphony bucket. `EffectParamOverrides` itself is
|
|
682
|
+
ECS-agnostic (`sopra/runtime`): anything that rebuilds instances of one event can hold one —
|
|
683
|
+
`attach(event, onChange)` to have writes checked against the event and to be told of each (move the
|
|
684
|
+
current instance now, or glide it when the time constant is above 0; a removal sends the event's own
|
|
685
|
+
value), `checkAttach(event)` to ask first, `applyTo(instance)` each fresh instance, and `detach(onChange)`
|
|
686
|
+
when done. One owner at a time.
|
|
687
|
+
|
|
688
|
+
> **Content rule for managed crowds:** the live `budget` and an event's `maxInstances` are independent
|
|
689
|
+
> caps. If many emitters share one *content-equal* `EventDescription` (e.g. 100k identical birds), give
|
|
690
|
+
> that event `maxInstances ≥ budget` — content-equal events share one polyphony bucket, so a lower cap
|
|
691
|
+
> would gate the budget and fewer than `budget` would actually sound.
|
|
692
|
+
|
|
693
|
+
In production the provider is an `AssetManagerBufferProvider` over the meep `AssetManager` (shared
|
|
694
|
+
decode cache + the alias system).
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
## Testing
|
|
699
|
+
|
|
700
|
+
The entire core is unit-testable without real audio: a `MockAudioContext` records the constructed
|
|
701
|
+
graph and scheduled events, and a `StubBufferProvider` hands over fake buffers. Tests assert the graph
|
|
702
|
+
shape, timeline math, voice lifecycle, deterministic selection, and serialization — never sound.
|
|
703
|
+
|
|
704
|
+
```js
|
|
705
|
+
import { SopraEngine } from "./SopraEngine.js";
|
|
706
|
+
import { MockAudioContext } from "./util/MockAudioContext.js";
|
|
707
|
+
import { StubBufferProvider } from "./asset/StubBufferProvider.js";
|
|
708
|
+
|
|
709
|
+
const ctx = new MockAudioContext();
|
|
710
|
+
const provider = new StubBufferProvider();
|
|
711
|
+
provider.set("x.ogg", { duration: 2 }); // a fake buffer is anything with a `duration`
|
|
712
|
+
// provider.failOn("y.ogg"); // simulate a failed/missing asset
|
|
713
|
+
|
|
714
|
+
const engine = new SopraEngine(ctx, ctx.destination, provider);
|
|
715
|
+
const inst = engine.playOneShot(EventDescription.from("e", SampleAudioClip.from("x.ogg")));
|
|
716
|
+
|
|
717
|
+
ctx.currentTime = 2;
|
|
718
|
+
engine.update(2);
|
|
719
|
+
// inst.state === EventInstanceState.Stopped (the one-shot self-released at the end)
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
Run the suite from the repo root:
|
|
723
|
+
|
|
724
|
+
```
|
|
725
|
+
npx jest --config jest.conf.json engine/sound
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## Design rules (don't break these)
|
|
731
|
+
|
|
732
|
+
- **Definitions are immutable, shared, and serializable.** No WebAudio nodes, no playback state, no
|
|
733
|
+
per-instance mutation on a definition. Runtime state lives on `EventInstance` / the
|
|
734
|
+
`SopraPlaybackContext`.
|
|
735
|
+
- **Gain is composed exactly once.** Authored gains are dB and accumulate down the clip tree at plan
|
|
736
|
+
time; bus/instance gains are linear on their own nodes. Don't double-apply.
|
|
737
|
+
- **One clock.** Everything reads `AudioContext.currentTime`; no `setTimeout`-driven audio.
|
|
738
|
+
- **The core never creates an `AudioContext`** and never imports ECS. It takes a context, a
|
|
739
|
+
destination, and a `BufferProvider`.
|
|
740
|
+
- **Errors surface.** Expected failures (missing asset, unresolved alias, limit reached) return a
|
|
741
|
+
sentinel (`null`) or reject; unexpected errors throw. Nothing is silently swallowed.
|
|
742
|
+
- **Determinism is sacred.** Random selection is seeded from a replicated source; never reach for
|
|
743
|
+
`Math.random()` in the playback path.
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
## Glossary
|
|
748
|
+
|
|
749
|
+
Acronyms and shorthand used in this document (and the code).
|
|
750
|
+
|
|
751
|
+
| Term | Expansion | Meaning in Sopra |
|
|
752
|
+
|---|---|---|
|
|
753
|
+
| **2D / 3D** | two- / three-dimensional | A 2D event is non-positional (plays straight into its bus); a 3D event (`is3D: true`) is spatialised — panned and distance-attenuated relative to the listener. |
|
|
754
|
+
| **API** | Application Programming Interface | The public methods/classes you call. |
|
|
755
|
+
| **aux send** | auxiliary send | A post-fader copy of a bus routed into another bus at a level (`BusDefinition.sends`), e.g. feeding a shared reverb bus. |
|
|
756
|
+
| **cents** | — | Pitch unit; 100 cents = 1 semitone, 1200 = 1 octave. All pitch offsets/randomisation are in cents. |
|
|
757
|
+
| **dB** | decibel | Logarithmic gain unit; 0 dB = unity, −6 dB ≈ half power. **All authored gains are in dB**; node gains on the WebAudio graph are linear (the two are converted by `dB2Volume` / `volume2dB`). |
|
|
758
|
+
| **ECS** | Entity Component System | meep's architecture: entities are ids, data lives in components, behaviour in systems. Sopra's *core* is ECS-agnostic; the ECS binding is `AudioEmitter` + `AudioEmitterSystem`. |
|
|
759
|
+
| **EQ** | equaliser | A filter insert (`EqEffect`), backed by a WebAudio `BiquadFilterNode`. |
|
|
760
|
+
| **FMOD / Wwise** | (product names) | Industry audio middleware. Sopra borrows their concepts — events, a bus tree, RTPC, voice stealing, snapshots, ducking — but is built on meep's data model, not a bank file. |
|
|
761
|
+
| **HRTF** | Head-Related Transfer Function | The high-quality (per-source convolution) 3D panning model; one of the `SopraPanningModel` options (the other, `EqualPower`, is cheaper). |
|
|
762
|
+
| **Hz** | hertz | Frequency unit (cycles/second), e.g. an EQ cutoff/centre frequency. |
|
|
763
|
+
| **IR** | Impulse Response | The convolution kernel that defines a reverb's space. `ReverbEffect` **generates one procedurally** (decaying noise), so there is no IR asset to load. |
|
|
764
|
+
| **JSON** | JavaScript Object Notation | One of the two serialization formats (human-readable; via `toJSON`/`fromJSON` + the type-tag dispatch in `sopraJSON.js`). The other is binary. |
|
|
765
|
+
| **Q** | quality factor | A filter's bandwidth/resonance control (`EqEffect.Q`). |
|
|
766
|
+
| **RNG** | Random Number Generator | Sopra's RNG is **seeded** (per `SopraPlaybackContext`) so random selection is reproducible across networked clients. |
|
|
767
|
+
| **RTPC** | Real-Time Parameter Control | A named float "parameter" (FMOD's term). Drives `Switch`/`Blend` selection and bus-volume / bus-effect automation. Stored in the `ParameterStore`; see `defineParameter` / `setParameter`. |
|
|
768
|
+
| **WebAudio** | Web Audio API | The browser audio API Sopra renders through (`AudioContext`, `GainNode`, `PannerNode`, `BiquadFilterNode`, `ConvolverNode`, …). Sopra never creates the `AudioContext` — meep's `SoundEngine` does. |
|