Documentation
    Preparing search index...

    Class RenderTarget

    An off-screen surface a frame can be rendered into, and sampled from afterwards (§61, §48, §63).

    const target = new RenderTarget({ width: 512, height: 512 });
    renderer.render(scene, [minimapView], undefined, target);
    panelMaterial.map = target.colorTexture;

    id plus version is the cache contract every fourJS GPU resource offers (BufferGeometry, Texture), and a render target offers it for the same reason: a backend keyed on the pair compares one number per frame instead of holding a subscription per target. RenderTarget.resize and RenderTarget.dispose are the only mutations, and both bump the version — so the backend's framebuffer is re-allocated at the new size on the next frame that draws into it, with nothing for the application to call.

    A target is shared, not owned by the materials that sample it — the same rule Texture follows. Whoever created it disposes it; Material.dispose() deliberately does not. Disposal is idempotent and terminal: a disposed target is skipped by a backend rather than drawn into, exactly as a disposed texture is skipped rather than sampled.

    Every target reports its size (RenderTarget.byteLength) to the process-wide §83 totals in resource-memory.ts — at construction, on resize(), and on dispose() — so an off-screen surface that is re-created per resize instead of resized shows up in §84's textureMemory as the leak it is (A-5, 2026-08-07).

    Implements

    Index
    colorTexture: RenderTargetTexture = ...

    The colour attachment, as a texture. Stable for the target's lifetime.

    id: string = ...

    Stable identity (§83), assigned at construction from a monotonic counter and formatted render-target-<n>. Unique within a process, ascending in construction order, never reused.

    • get byteLength(): number

      Bytes this target's attachments describe (§83, §84's textureMemory).

      Four bytes per texel for the "rgba8" colour attachment, plus the depth attachment when RenderTarget.depth is on: two per texel for a DEPTH_COMPONENT16 renderbuffer, four for a DEPTH_COMPONENT24 texture (R-18 — 24-bit depth occupies a 32-bit texel), and four for the packed DEPTH24_STENCIL8 renderbuffer RenderTarget.stencil asks for (R-7 — 24 bits of depth and 8 of stencil in one 32-bit texel, so a stencil is two bytes per texel on top of the plain depth buffer, not one). All three formats are quoted from what @fourjs/render-webgl's gl-render-target.ts actually allocates, which is the difference between accounting and guessing. The constants move together when §62's floating-point formats widen RenderTargetFormat.

      new RenderTarget({ width: 512, height: 512 }).byteLength; // 512*512*6
      new RenderTarget({ width: 512, height: 512, depth: false }).byteLength;
      // 512*512*4
      new RenderTarget({ width: 512, height: 512, depthTexture: true }).byteLength;
      // 512*512*8
      new RenderTarget({ width: 512, height: 512, stencil: true }).byteLength;
      // 512*512*8

      0 once disposed — one rule with Texture.byteLength: a disposed resource holds nothing.

      Returns number

    • get version(): number

      Counter incremented on every mutation. Backends key their framebuffer allocation on RenderTarget.id and validate it against this; treat it as opaque and compare for inequality, exactly like Texture.version.

      Returns number

    • Releases this target (§83). Idempotent and terminal.

      There is nothing CPU-side to free — the framebuffer, its colour texture and its depth buffer all belong to the backend — so this marks the target disposed and bumps the version, which is exactly what makes the backend delete them on the next frame that meets this target. A backend that meets a disposed target skips it: drawing into a released framebuffer, or sampling one, would paint undefined content rather than report the mistake (the same rule Texture.dispose states).

      Materials pointing at RenderTarget.colorTexture are not notified; ownership is explicit and upwards (§83).

      It does remove this target and its bytes from the process-wide §83 totals (textureMemoryBytes, liveRenderTargetCount), exactly once: the idempotence guard above is what makes a double dispose() subtract once rather than twice.

      Returns void

    • Changes the size of the colour (and depth) attachment (§85 validated).

      The backend re-allocates on the next frame that draws into this target, because the version advances — and the old contents are gone, which is the honest description of a re-allocated framebuffer. A pass that must survive a resize re-renders; there is no resize-preserving blit in this tier.

      Resizing to the size it already has still bumps the version, and so still costs a re-allocation. Guard the call if that matters: an application following the canvas usually knows whether the size actually changed, and a no-op here would make "the version advanced" stop meaning "something changed".

      Throws after disposal (§83): disposal is terminal, and silently resizing a dead target would hide the mistake.

      Parameters

      • width: number
      • height: number

      Returns void