the CSS background color of the parent element that holds the canvas.
Applied during initialization to prevent a white flash before the first render.
Set to "transparent" to disable, or any valid CSS color value.
Optionalbatcher?: new (renderer: any) => WebGLBatchera custom batcher class, riding the quad/primitive slots on either
GPU backend — extend WebGLBatcher under WebGL, WebGPUBatcher
under WebGPU (addBatcher rejects a wrong-backend class loudly)
the default blend mode to use. Both GPU renderers support the full set;
the Canvas fallback supports every mode except "none" — see
CanvasRenderer#setBlendMode for the list.
OptionalcameraClass?: new (minX: number, minY: number, maxX: number, maxY: number) => Camera2dDefault camera class instantiated for any Stage that does not
explicitly provide its own cameras. Set to Camera3d to opt
every stage in the app into perspective rendering by default. Stages
can still override per-instance via super({ cameras: [...] }) or
per-class via super({ cameraClass: Camera2d }). Built-in stages
(e.g. the loader screen) explicitly use Camera2d regardless
of this setting.
GPU-backend requirement. Camera classes whose
static defaultSortOn === "depth" (Camera3d and any subclass) need
a renderer with a depth buffer (renderer.supportsDepthBuffer —
WebGL 2 or WebGPU). Pairing such a cameraClass with
renderer: video.AUTO on a system where AUTO falls back to Canvas
emits a console.warn and produces a non-functional render. Pin
renderer: video.WEBGL (or WEBGPU) to make app.init() reject
instead.
whether 3D objects cast a soft "blob" shadow on the ground by default (#1515).
A ground shadow is what stops a character or prop reading as floating in a 2.5D scene — it answers "where is this standing", not "where is the light". It is deliberately not a simulated shadow; see Mesh#castGroundShadow.
This is the default for every Mesh, Sprite3d and
InstancedMesh; each can override it with its own
castGroundShadow (which wins), and level.load takes the same
option for one glTF scene (which wins over this).
Because it is a blanket opt-in, it skips meshes with no vertical
extent — a flat plane lying on the floor is the floor, and shadowing
it with itself would smear a blob across the whole ground. A per-object
castGroundShadow: true bypasses that safeguard, being an explicit
instruction.
On by default. Requires a GPU backend and a Camera3d, so a
2D game is untouched whatever this says — the Canvas renderer has no
depth buffer and the 2D-camera path draws none. Set it false to opt a
3D game out wholesale (a scene with baked lighting, or one bringing its
own shadows, would otherwise get two).
Optionalcompositor?: new (renderer: any) => WebGLBatchera custom batcher class (extend the active backend's base:
WebGLBatcher / WebGPUBatcher)
whether to display melonJS version and basic device information in the console
If true, treat WebGL as unavailable when the browser warns that a
context would perform dramatically worse than a native application
(a software rasterizer, a blocklisted driver). Note this is stricter
than the WebGL default, which is false.
The WebGPU backend honors it too, by rejecting a fallback
(software) adapter. The effect: under AUTO such a machine
gets the Canvas renderer, and under WEBGL / WEBGPU
app.init() rejects. Set to false to accept a software or
blocklisted context instead.
Enable the GPU procedural shader path for orthogonal tile layers
(backends advertising renderer.supportsShaderTileLayers — WebGL 2
and WebGPU). When true (default), eligible layers render via a
single quad per tileset + a fragment shader doing per-fragment GID
lookup, bypassing the per-tile draw loop entirely. Layers that
don't qualify (Canvas renderer, non-orthogonal,
collection-of-image tilesets, tilerendersize "grid", non-zero
tileoffset, oversampled beyond the shader's overflow window) fall
back to the legacy path automatically.
Set to false to disable globally.
enable high precision shaders (WebGL only). When false, shaders prefer "mediump" precision for better performance on some mobile GPUs, falling back to "lowp" if "mediump" is not supported. When true (default), the highest precision supported by the device is used. This setting is ignored by the Canvas renderer.
How many texture units the WebGL multi-texture batchers may use (#1585).
A batch can draw sprites from this many distinct textures before it has
to flush and start over, so a scene with more textures in flight than
this loses batching sharply. The pool used to be hardcoded to 16 — the
WebGL 2 spec floor for MAX_TEXTURE_IMAGE_UNITS, and roughly half
what current desktop and mobile hardware reports.
"auto" (default) — the device's reported limit, capped at 32.Raising it costs fragment-shader compile time and register pressure, because the batcher's shader unrolls one sampler and one branch per unit. Lowering it is the escape hatch if a driver misbehaves on wide sampler ladders.
Read at initialization only — the batchers compile their shaders
against this value, so unlike textureFilter there is no runtime setter.
WebGL only; the WebGPU backend sizes its own slot budget from its
per-stage binding limits, and the Canvas renderer has no batching.
The physics system to use. Accepts:
"builtin" (default) — the built-in SAT physics adapter"none" — disables physics; World.step skips the simulation,
the world container behaves like a pure scene graphPhysicsAdapter instance — e.g. new MatterAdapter() from
@melonjs/matter-adapter, or any third-party adapter{ adapter: PhysicsAdapter } — explicit form, reserved for
future per-app physics optionsThe adapter's physicLabel becomes world.physic so user code
can branch on the active engine without importing the concrete
adapter class (app.world.physic === "matter", etc.).
A hint to the user agent about which GPU to use on multi-GPU systems (discrete vs integrated). Browsers generally favour the low-power GPU unless asked otherwise, to preserve battery life.
"default" — no hint; let the user agent decide."low-power" — prefer the integrated GPU."high-performance" — prefer the discrete GPU. Note that browsers
only honour this for pages that handle context loss, since switching
GPU can drop the context; melonJS registers those handlers itself,
so the request is respected.The same hint (and the same values, minus "default") is used by
WebGPU's adapter request, so this setting is backend-neutral.
Warm the renderer up during loader.preload(), behind the loading
screen, instead of paying for it on the frame that first draws (GPU
backends — the Canvas renderer has nothing to warm and ignores this).
Today that means the built-in shader programs, which is all Renderer#prewarm does. Named for the intent rather than the current contents: anything else worth doing before the first frame belongs behind the same switch, and should not need a second setting.
A GPU backend does not finish a shader when handed the source; it finishes it the first time something is drawn with it. That puts the whole cost on the frame a scene first appears, which is the moment a level or stage comes up and its geometry arrives a beat late. Warming up moves it to where a progress bar is already on screen.
On by default. The cost is small and it is paid where nothing is
waiting on a frame: a purely 2D game links the mesh-tier programs
it will never bind — both the unlit tier and the lit one that inherits
from it — measured at about 60ms on a fast desktop GPU, inside a preload
that is already showing a progress bar. A tiny 2D game with a near-empty
preload is the one case that pays without any possible benefit. Set it to
false for a target where linking is slow enough that the preload
itself would suffer.
The warm-up is run by loader.preload() — every call, not just the
first — so a game that preloads gets it automatically and a game that
never calls preload() never gets it at all. Call
Renderer#prewarm directly in that case.
Shaders declared as assets ({type: "shader"}) are covered too, so a
level's own effects are warmed by declaring them alongside that level's
assets rather than building them inline when the level starts.
Renderer to use. Four built-in modes (constants from me.video):
await app.init() always
resolves under AUTO; the WebGPU attempt is a full adapter/device
negotiation awaited inside init(), falling through to the
synchronous candidates when it rejects. Under the Canvas tail the
GPU-only subsystems (Camera3d, retained meshes, ShaderEffect,
Light2d/Light3d shading, GPU tilemap) degrade or disable — gate on
the renderer capability flags (supportsDepthBuffer,
shaderLanguage, …) if your scene depends on them.app.init()
rejects when no adapter/device can be acquired — it never
substitutes another backend.app.init() rejects if a WebGL 2
context is unavailable (WebGL-1-only device, driver-blocklisted
GPU, perf-caveat failure, etc.) — fail fast rather than render a
stuck blank canvas.Or pass a custom Renderer subclass instance for full control.
enable scaling of the canvas ('auto' for automatic scaling)
screen scaling modes
the HTML Element to be used as the reference target when using automatic scaling (by default melonJS will use the parent container of the div element containing the canvas)
whether to enable sub-pixel rendering (avoid sprite flickering when using transforms)
Default texture magnification/minification filter, decoupled from
antiAlias (GPU backends — WebGL and WebGPU; the 2D Canvas
renderer has no per-texture filtering and ignores this).
antiAlias conflates two separate concerns: polygon-edge antialiasing
(MSAA) and texture sampling smoothness. This setting separates the
texture half out, so you can choose them independently — e.g. smooth
textures with no MSAA, or crisp pixel-art textures with MSAA edges.
"auto" (default) — follow antiAlias (linear when true, nearest
when false): unchanged behavior."nearest" — crisp/pixelated upscaling, regardless of antiAlias."linear" — smooth, regardless of antiAlias.This is the default for every texture; a Mesh can still override
it per-mesh via its own textureFilter setting (which wins).
// smooth textures but NO polygon-edge MSAA
const app = new Application(1024, 768, {
renderer: video.WEBGL,
antiAlias: false, // MSAA off
textureFilter: "linear", // textures still filtered smooth
});
// crisp pixel-art textures WITH MSAA-smoothed edges
new Application(1024, 768, {
renderer: video.WEBGL,
antiAlias: true, // MSAA on
textureFilter: "nearest", // textures stay crisp
});
whether to allow transparent pixels in the front buffer (screen).
whether to enable verbose mode (additional console output for debugging)
Optionalcanvas?: neverthe DOM parent element (or its string ID) to hold the canvas in the HTML file
an existing canvas element to use as the renderer target (by default melonJS will create its own canvas based on given parameters)
Optionalparent?: never
whether to enable or not video scaling interpolation. On the GPU backends this drives polygon-edge antialiasing (up to 4× MSAA) — on the canvas itself, and equally through post-effect chains, whose scene capture targets are multisampled to match, so adding a camera effect never switches edge smoothing off. Texture sampling smoothness is controlled separately by
textureFilter. Multisampled capture targets cost GPU memory (roughly 30 bytes per pixel at 4×, ~55 MB at 1080p on WebGL) — withantiAlias: falseno multisampled storage is ever allocated.