Builtin Library
- ..
- ParticipatingMedium.component
- README.md4.8 KB
- Volume.component
- VolumeSequence.component
- VolumetricLighting.component
- VolumetricSky.component
- _probe.module
- demo
- documentation
- emission_raymarch.computeShader
- importers
- lightScattering.renderFeature
- mediaShadow.renderFeature
- mediaTransmittance.module
- media_common.shaderModule
- media_shadow_apply.computeShader
- media_tau_map.computeShader
- package.yaml477 B
- presets
- scattering_common.shaderModule
- shaders
- vol_composite.computeShader
- vol_scatter.computeShader
- volume.module
- volumeDemos.module
- volumeSequence.module
- volumetricLighting.module
- volumetricSky.module
- volumetricSky.renderFeature
README.md
volumetrics
Volumetric (3D-texture) rendering, end to end, in one package. Built
entirely on the engine's generic compute.* GPU primitives — no
Rust changes are needed to author new volumetric content.
Layout
| Asset | Identity | Role |
|---|---|---|
Volume.component | @builtin::systems.volumetrics.Volume | Attach a 3D voxel texture to an entity; raymarches it through the entity's transform AABB. |
VolumetricSky.component | @builtin::systems.volumetrics.VolumetricSky | Singleton procedural cloud layer with TAA. |
ParticipatingMedium.component | @builtin::systems.volumetrics.ParticipatingMedium | Mark an entity as fog/smoke/dust that attenuates the light passing through it. |
mediaTransmittance.module | @builtin::systems.volumetrics.mediaTransmittance | Light-space optical-depth map: the registry, the settings, and the basis the map is built in. |
mediaShadow.renderFeature | @builtin::systems.volumetrics.mediaShadow | Builds the optical-depth map and attenuates each surface by the density in front of it. |
volume.module | @builtin::systems.volumetrics.volume | Builders (noise/sphere/box/wrap) + the .zvol header reader + occupancy + brick paging + the per-entity raymarch dispatch. |
VolumeSequence.component | @builtin::systems.volumetrics.VolumeSequence | Play an open volume sequence through an entity's transform AABB. |
volumeSequence.module | @builtin::systems.volumetrics.volumeSequence | A run of .zvol frames streamed through a fixed ring of resident volumes. |
volumeDemos.module | @builtin::systems.volumetrics.volumeDemos | Shared pipeline for the showcase scenes (fill + emissive raymarch + composite). |
volumetricSky.module | @builtin::systems.volumetrics.volumetricSky | Cloud volume + raymarch + TAA + composite orchestration. |
shaders/*.shader | @builtin::systems.volumetrics.shaders.* | volume_raymarch, volume_pages, volume_pack, cloud_noise[_v3/_v5], cloud_raymarch[_v3/_v4/_v5], cloud_taa. |
importers/vdb_to_zvol.importer | (auto-discovered) | .vdb → dense .zvol via the openvdb WASM plugin (procedural fallback when the plugin isn't loaded). |
presets/cumulus_default.preset | @builtin::systems.volumetrics.cumulus_default | Canonical full VolumetricSky weather preset. |
demo/*.scene | @builtin::systems.volumetrics.demo.* | sdf_solids, smoke_plume, nebula, godrays, zvol_viewer, sky. |
Path convention — fully-qualified builtin identities
Every intra-package reference uses the asset's fully-qualified builtin identity, the same convention every other builtin package follows:
local Volume = require("@builtin::systems.volumetrics.volume")
local Sky = require("@builtin::systems.volumetrics.volumetricSky")
local V = require("@builtin::systems.volumetrics.volumeDemos")
-- shader identities, e.g. asset.resolve("@builtin::systems.volumetrics.shaders.volume_raymarch")
Qualified identities are caller-independent: they resolve identically
from a module, a scene entrypoint, or a component. Caller-relative
(.sibling) requires are deliberately avoided here because the
component runtime caller identity is @builtin::components.<Name>, so a
.sibling require from a component resolves against the wrong root.
(An earlier revision of this package used a ~volumetrics package-root
alias for relocatability; that alias is not resolvable on current main,
so the package uses qualified identities throughout.)
Usage
-- Per-entity volume. The component resolves the name through `Volume.get`,
-- so a volume paged into a brick pool renders from the pool under the same
-- name:
local Volume = require("@builtin::systems.volumetrics.volume")
local cloud = Volume.noise({ name = "cloud", size = 64, scale = 4 })
cloud:buildSparse({ brickSize = 8 })
cloud:releaseDense()
entity(id).component.add("Volume", { volumeName = "cloud", density = 6.0 })
-- Procedural sky:
local sky = entity.spawn("sky")
sky.component.add("VolumetricSky", {})
preset.apply("cumulus_default", { entity = sky.id, component = "VolumetricSky" })
-- VDB import: drop a `.vdb` into the VFS; the importer writes a `.zvol`
-- alongside it. Load it with the zvol_viewer demo scene.
-- Animated run: one `.zvol` per frame, played through a bounded ring.
local Seq = require("@builtin::systems.volumetrics.volumeSequence")
Seq.open({ name = "plume", frames = framePaths, resident = 3, fps = 24 })
entity(id).component.add("VolumeSequence", { sequenceName = "plume", density = 6.0 })
Plugin dependency
The VDB importer delegates real OpenVDB parsing to the openvdb plugin
in the builtin library, @builtin::plugins.openvdb. Without the plugin
the importer falls back to a deterministic procedural torus so the
pipeline stays functional.