Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

EPU Architecture Overview

The Environment Processing Unit (EPU) is Nethercore ZX’s GPU-driven, fully procedural environment system. This page provides an architectural overview.

For the complete specification (opcode catalog, packing rules, and shader implementations), see:

  • nethercore-design/specs/epu-feature-catalog.md
  • nethercore/include/zx.rs
  • nethercore/nethercore-zx/shaders/epu/

For the current API reference and quick-start guide, see:


Introduction

The EPU provides a universal, stylized environment system that:

  • Renders backgrounds (sky/walls/void) with strong, art-directable motifs
  • Provides lighting data for objects (diffuse ambient + reflection color)

The system is designed around these hard constraints:

ConstraintValue
Config size128 bytes per environment state
Layer count8 instructions (4 Bounds + 4 Radiance)
Instruction size128 bits (two u64 values)
CubemapsNone (fully procedural octahedral maps)
MipmapsYes (compute-generated downsample pyramid)
Color modelDirect RGB24 x 2 per layer
AestheticPS1/PS2-era stylized, quantized params

System Diagram

CPU (game)                                         GPU
---------                                         ---
Call environment_index(...)+epu_set(...) during render()   --->   [Compute] EPU_Build(configs)
Call draw_epu() to request a background draw            - Evaluate 8-layer microprogram into EnvRadiance (mip 0)
Capture (viewport, pass) draw requests                  - Generate mip pyramid from EnvRadiance mip 0
                                                    - Extract SH9 from a coarse mip (e.g. 16x16)

Main render (background + objects)          --->   [Render] Sample prebuilt results
                                                  - Background: EPU environment draw per viewport/pass
                                                  - Specular:   EnvRadiance sampled by roughness (LOD)
                                                  - Diffuse:    SH9 evaluated at the shading normal

Radiance Flow

The EPU produces a single directional radiance signal per environment (EnvRadiance, mip 0). From that radiance, the runtime builds a downsample mip pyramid used for continuous roughness-based reflections, and extracts SH9 coefficients for diffuse ambient.


Data Model

PackedEnvironmentState (128 bytes)

Each environment is exactly 8 x 128-bit instructions:

SlotKindRecommended Use
0-3BoundsAny bounds opcode (0x01..0x07). Any bounds opcode can be first; each bounds layer outputs RegionWeights consumed by later feature/radiance layers.
4-7RadianceDECAL / GRID / SCATTER / FLOW + radiance ops (0x0C..0x13)

Implementation note: in the shaders, bounds opcodes return (sample, regions). Dispatch updates regions after every bounds layer, and feature layers apply region masking using the current regions.

Instruction Bit Layout (128-bit)

Each instruction is packed as two u64 values:

High word (bits 127..64):

bits 127..123: opcode     (5)  - 32 opcodes available
bits 122..120: region     (3)  - Bitfield: SKY=0b100, WALLS=0b010, FLOOR=0b001
bits 119..117: blend      (3)  - 8 blend modes
bits 116..112: meta5      (5)  - (domain_id<<3)|variant_id; use 0 when unused
bits 111..88:  color_a    (24) - RGB24 primary color
bits 87..64:   color_b    (24) - RGB24 secondary color

Low word (bits 63..0):

bits 63..56:   intensity  (8)  - Layer brightness
bits 55..48:   param_a    (8)  - Opcode-specific
bits 47..40:   param_b    (8)  - Opcode-specific
bits 39..32:   param_c    (8)  - Opcode-specific
bits 31..24:   param_d    (8)  - Opcode-specific
bits 23..8:    direction  (16) - Octahedral-encoded direction (u8,u8)
bits 7..4:     alpha_a    (4)  - color_a alpha (0-15)
bits 3..0:     alpha_b    (4)  - color_b alpha (0-15)

Opcodes

OpcodeNameKindPurpose
0x00NOPAnyDisable layer
0x01RAMPBoundsBounds gradient (sky/walls/floor)
0x02SECTORBoundsAzimuthal opening wedge modifier
0x03SILHOUETTEBoundsSkyline/horizon cutout modifier
0x04SPLITBoundsGeometric divisions
0x05CELLBoundsVoronoi/mosaic cells
0x06PATCHESBoundsNoise patches
0x07APERTUREBoundsShaped opening/viewport
0x08DECALRadianceSharp SDF shape (disk/ring/rect/line)
0x09GRIDRadianceRepeating lines/panels
0x0ASCATTERRadiancePoint field (stars/dust/bubbles)
0x0BFLOWRadianceAnimated noise/streaks/caustics
0x0CTRACERadianceLine/crack patterns
0x0DVEILRadianceCurtain/ribbon effects
0x0EATMOSPHERERadianceAtmospheric absorption + scattering
0x0FPLANERadianceGround/surface textures
0x10CELESTIALRadianceMoon/sun/planet bodies
0x11PORTALRadiancePortal/vortex effects
0x12LOBERadianceRegion-masked directional glow
0x13BANDRadianceRegion-masked horizon band

Blend Modes (8 modes)

ValueNameFormula
0ADDdst + src * a
1MULTIPLYdst * mix(1, src, a)
2MAXmax(dst, src * a)
3LERPmix(dst, src, a)
4SCREEN1 - (1-dst)*(1-src*a)
5HSV_MODHSV shift dst by src
6MINmin(dst, src * a)
7OVERLAYPhotoshop-style overlay

Compute Pipeline

Implementation note: Internally, the runtime stores outputs in arrays indexed by env_id. Games can provide configs for one or more env_ids by setting environment_index(env_id) then calling epu_set(config_ptr). Any env_id without an explicit config falls back to env_id = 0, and then to the built-in default config.

The EPU runtime maintains these outputs per env_id:

OutputTypePurpose
EnvRadiance[env_id]mip-mapped octahedral 2D arrayBackground + roughness-based reflections
SH9[env_id]storage bufferL2 diffuse irradiance (spherical harmonics)

Frame Execution Order

  1. Capture EPU draw requests (per viewport/pass) and determine active environment states
  2. Deduplicate env_id list, cap to MAX_ACTIVE_ENVS
  3. Determine which env_ids are dirty (hash)
  4. Dispatch compute passes:
    • Environment evaluation (build EnvRadiance mip 0)
    • Mip pyramid generation (2x2 downsample chain)
    • Irradiance extraction (SH9)
  5. Barrier: compute to render
  6. Render background + objects (sampling by env_id)

Render Integration

Background Sampling

Render sky/background by evaluating the EPU directly per pixel (L_hi(dir)), not by sampling EnvRadiance. This guarantees the sky is never limited by the EnvRadiance base resolution.

Reflection Sampling

Sample EnvRadiance with a continuous roughness-to-LOD mapping across mip levels. A common mapping is:

  • lod = (roughness^2) * (mip_count - 1)

Then sample at that LOD (trilinear) or lerp between floor(lod) and ceil(lod).

To avoid hard cutoffs while still preserving mirror-quality reflections, add a high-frequency residual term that fades out with roughness:

  • alpha = roughness^2
  • L_spec = L_lp + (1 - alpha) * (L_hi - L0)
    • L_hi is procedural EPU evaluation at the reflection direction
    • L0 is EnvRadiance sampled at mip 0
    • L_lp is EnvRadiance sampled at the roughness-derived LOD

Ambient Lighting

Diffuse ambient is evaluated from SH9 coefficients at the shading normal n.


Multiple Environments

The EPU supports multiple environments per frame through texture array indexing:

  • All outputs are stored in array layers indexed by env_id
  • Renderers pass env_id per draw/instance (internal)
  • No per-draw rebinding required
ConstantTypical Value
MAX_ENV_STATES256
MAX_ACTIVE_ENVS32
EPU_MAP_SIZE128 (default; override via NETHERCORE_EPU_MAP_SIZE)
EPU_MIN_MIP_SIZE4 (default; override via NETHERCORE_EPU_MIN_MIP_SIZE)
EPU_IRRAD_TARGET_SIZE16

Dirty-State Caching

For environments, the EPU tracks:

  • state_hash: Hash of the 128-byte config
  • valid: Whether the cached entry has been initialized

Update policy:

ConditionAction
Unused this frameSkip
Used + unchangedSkip
Used + changedRebuild, then update state_hash

Format Summary

AspectValue
Instruction size128-bit
Environment size128 bytes
Opcode bits5-bit (32 opcodes)
Region3-bit mask (combinable)
Blend modes8 modes
ColorRGB24 × 2 per layer
EmissiveReserved (future use)
Alpha4-bit × 2 (per-color)
Parameters4 (+param_d)

Full Specification

For complete details including:

  • WGSL shader implementations
  • Per-opcode parameter tables
  • Example configurations
  • Performance considerations

See: