--- title: "Compositor" type: docs --- # The Compositor The compositor is Prosperon's rendering orchestrator. You describe your scene — planes, layers, effects — and the compositor figures out what render passes are needed and executes them. ## The Basic Idea You don't issue draw calls. You create sprites and set their properties. The compositor does the rest: 1. Queries all registered drawables 2. Organizes them by plane and layer 3. Applies effects to tagged groups 4. Composites everything to the screen Think of it like a GBA: you declare "sprite here, sprite there," get handles back, and poke their positions. The hardware (in this case, the compositor + GPU backend) handles the actual rendering. ## Scene Configuration A scene is described as a config object passed to the compositor: ```javascript var compositor = use('compositor') var plan = compositor.compile({ clear: {r: 0, g: 0, b: 0, a: 1}, planes: [ { name: 'background', plane: 'background', resolution: {width: 320, height: 240}, camera: bg_camera, presentation: 'integer_scale' }, { name: 'game', plane: 'default', resolution: {width: 320, height: 240}, camera: game_camera, layer_sort: {'5': 'y'}, presentation: 'integer_scale' }, { name: 'hud', plane: 'hud', resolution: {width: 1280, height: 720}, camera: hud_camera, presentation: 'stretch' } ] }) ``` Each plane renders independently at its own resolution and composites onto the screen. ## Planes A **plane** is a named rendering group. Sprites belong to a plane via their `plane` property (default: `'default'`). Each plane in the compositor config: - Has its own **resolution** (low-res pixel art, native UI, etc.) - Has its own **camera** - Has its own **layer sorting** rules - Has a **presentation mode** (how it maps to the window) Planes composite in order — later planes draw on top of earlier ones. ## Layer Sorting Within a plane, drawables are sorted by `layer` (integer). Within each layer, you can choose a sorting mode: ```javascript layer_sort: { '0': 'explicit', // engine may reorder for batching efficiency '5': 'y' // sort by Y position (top-down game depth) } ``` Y-sorting is essential for top-down games where objects lower on screen should appear in front. ## Effects Effects are applied to **groups** of sprites. Tag sprites with group names, then define effects for those groups: ```javascript var player = sprite({ image: "player.png", groups: ['glow_objects'] }) var plan = compositor.compile({ planes: [{ name: 'game', plane: 'default', camera: cam, resolution: {width: 320, height: 240} }], group_effects: { glow_objects: { effects: [ {type: 'bloom', threshold: 0.5, intensity: 1.5, blur_passes: 2} ] } } }) ``` ### Available Effects **Bloom** — extracts bright areas, blurs them, composites back: ```javascript {type: 'bloom', threshold: 0.8, intensity: 1.0, blur_passes: 2} ``` **Mask** — uses sprites in a mask group as a stencil: ```javascript {type: 'mask', mask_group: 'mask_shapes', channel: 'alpha', invert: false} ``` Sprites in the `mask_group` are not drawn directly — they only serve as the mask shape. ## Presentation Modes Each plane specifies how its render target maps to the window: | Mode | Behavior | |------|----------| | `stretch` | Fill the window exactly (may distort aspect ratio) | | `letterbox` | Fit inside window, preserving aspect ratio, with black bars | | `integer_scale` | Scale by whole numbers only for pixel-perfect rendering | `integer_scale` automatically uses nearest-neighbor filtering for crisp pixels. ## Execution The compositor produces a **plan** — a list of render passes. The plan is executed by the GPU backend: ```javascript var result = compositor.execute(plan) // result.commands is sent to the GPU backend ``` In practice, `core.start({render})` handles this for you. Your render callback returns the compositor result and the engine executes it. ## Manual Drawables You can inject drawables that aren't registered with film2d by adding them directly to a plane config: ```javascript planes: [{ name: 'game', plane: 'default', camera: cam, drawables: [ {type: 'sprite', image: tex, pos: {x: 0, y: 0}, width: 32, height: 32, layer: 0} ] }] ``` These are merged with the registered drawables for that plane. ## Render Targets The compositor automatically manages intermediate render targets for effects. You don't need to create or manage GPU textures — the compositor allocates and reuses them as needed. ## Debug Pass `debug: 'graph'` to `core.start` config to log the compiled render plan as JSON. Pass `debug: 'cmd'` to log the final command list sent to the GPU.