Documentation
    Preparing search index...

    Interface SkinnedUnlitRenderItem

    A skinned draw over §57's UnlitMaterial (§54; RFC 0003) — the unlit pipeline's vertex-stage variant. Produced only for a Mesh whose skeleton and geometry agree; see RenderItemKind.

    interface SkinnedUnlitRenderItem {
        castShadow: boolean;
        clip?: RenderItemClip | null;
        frustumCulled: boolean;
        geometry: BufferGeometry;
        jointCount: number;
        jointMatrices: Float32Array;
        kind: "skinned-unlit";
        layers: number;
        material: UnlitMaterial;
        materialId: string;
        morphWeights?: Float32Array<ArrayBufferLike> | null;
        receiveShadow: boolean;
        renderLayer: number;
        renderOrder: number;
        scissor?: ScissorRect | null;
        transformVersion?: number;
        transparent: boolean;
        viewDepth: number;
        worldBounds?: BoundingSphere | null;
        worldMatrix: Matrix4;
    }

    Hierarchy

    • SkinnedRenderItemBase
      • SkinnedUnlitRenderItem
    Index
    castShadow: boolean

    §49's castShadow, snapshotted from the drawable node (§69; R-18, 2026-08-09).

    Read by the backend's depth-only shadow pass, which walks this same list before the view loop and draws the items carrying true — of the three surface kinds only, since a §55 quad would cast its rectangle rather than its texture (see Renderable.castShadow). On the item rather than reached through a node reference for the reason §64 gives for compact render items in the first place — and because a compact item has no node reference to reach through.

    Always false on a particle item: §36's billboards have no surface to project (see ParticleRenderItem).

    clip?: RenderItemClip | null

    §67's clip, or null for a draw no clip touches (R-23, 2026-08-21) — the overwhelmingly common case, and the one every scene had before clipping existed.

    Three things read it. A backend applies clip.stencil in place of the material's own §57 stencil and, when clip.maskPass is set, forces colour writes, depth writes and the depth test off; §65's batcher breaks a run where two consecutive items carry different records, because the same material under two different clips is two different draws; and the comparators below sort mask draws to the front of the list.

    The record is a shared, pooled object — every item under one clip carries the identical reference — which is what makes the batcher's check one !== rather than a seven-field comparison. Like every other field on a pooled item it is rewritten by the next build; see clip.ts for what it means and why it is not a StencilState.

    Optional, and undefined means exactly what null means. The builders always write it (null for the unclipped case), so an item this module produced answers with one property load; the field is optional so that a hand-built item literal or structural double predating §67 — R-38's recorded gotcha, answered structurally this time — still typechecks, and reports undefined, which every reader treats as "no clip". Same move as RendererCapabilities' optional members (R-1): widen a shipped shape additively, and let absence mean the pre-feature behaviour.

    frustumCulled: boolean

    §49's frustumCulled, snapshotted from the drawable node (§87; R-8, 2026-08-09).

    Read by buildViewRenderList, which tests an item's world bounds against the view's frustum only when this is true. On the item rather than reached through a node reference for the reason §64 gives for compact render items in the first place — and because a compact item has no node reference to reach through.

    false on a particle item that has no live-particle bound — the shared instance quad sits at the emitter and says nothing about where the particles are. When the emitter publishes a local AABB via structural computeBounds(outMin, outMax), the builders copy a world sphere onto RenderItemBase.worldBounds and set this true so §87 can cull the system (R-8 follow-up b).

    geometry: BufferGeometry

    Vertex data to draw (§53).

    jointCount: number

    Number of joints in the palette; positive on every skinned item.

    jointMatrices: Float32Array

    The skeleton's palette: 16 floats per joint, in joint-index order (§33).

    kind: "skinned-unlit"
    layers: number

    The drawable node's §46 layer mask, snapshotted at generation time (R-38, 2026-08-08).

    Not a sort key and not read by the comparator — it is what lets one render list serve several views with different masks, which is the shape this engine has: the frame builds one list and view-list.ts's buildViewRenderList derives each view's from it, testing item.layers & effectiveViewMask once per item per view (R-8, 2026-08-09; the WebGL backend tested it inline before that). Filtering at build time is the other half and is buildRenderList's layerMask parameter, for the caller whose views differ so much that a shared list would carry mostly-rejected items; the two compose, since an item that was never generated cannot be drawn into any view.

    On the item rather than reached through a node reference for the reason §64 gives for compact render items in the first place — and because a compact item has no node reference to reach through.

    Confusingly adjacent to renderLayer above, and unrelated: that is §66's ordering ordinal, this is §46's membership set.

    material: UnlitMaterial

    Surface appearance (§57).

    materialId: string

    The item's material's stable id (§57), snapshotted at generation time — the material half of §66's sort key 3 (R-10, 2026-08-09). "" for a particle item, which has no material.

    Key 3 is "pipeline and material compatibility", and this item carries it as two fields rather than one: kind is the pipeline and this is the material. Not one concatenated key, because building ${kind}:${id} would allocate a string per item per frame, which is exactly what the pooled item exists to avoid (plan D7). Not read through material.id inside the comparator either, for the reason §64 gives for compact render items — a comparator runs O(n log n) times and must not chase a reference per call.

    Ids are assigned from Material's monotonic counter in construction order, so ordering by them is a deterministic function of the program that built the scene (§33) — the property groupRenderListByPipeline rests on. They are compared as strings, so the order is lexicographic (material-10 before material-9) rather than numeric: §66 asks for grouping, and any total order that puts equal ids together satisfies it.

    morphWeights?: Float32Array<ArrayBufferLike> | null

    §54's morph-target weights — the node's MorphWeights component array — or null for the overwhelmingly common draw that carries none (RFC 0003, 2026-08-28).

    A reference to the component's own array, snapshotted like frame and instances: the item is pooled and the weights may be rewritten by the next fixed step, so a consumer reads them during the call that built the list. WebGL's one-target morph programs consume morphWeights[0] when the geometry carries positions1 (RFC 0003 WP-SK.4); WebGPU skips those draws. Further targets remain staged.

    Optional, and undefined means exactly what null means — the R-23 move, third application: the builders always write it, the field is optional so a hand-built item literal or structural double predating RFC 0003 still typechecks, and MutableRenderItem re-declares it required so a pooled slot cannot go stale.

    receiveShadow: boolean

    §49's receiveShadow, snapshotted from the drawable node (§69; R-18, 2026-08-09).

    Read by the two shaded pipelines, which switch the shadow comparison off for a draw carrying false; the unlit and sprite pipelines have no lighting term to attenuate and never ask. Always false on a particle item, for the reason above.

    renderLayer: number

    §66 sort key 1, copied from the drawable node.

    renderOrder: number

    §66 sort key 5, copied from the drawable node.

    scissor?: ScissorRect | null

    §67 rectangular scissor, or null for a draw that inherits the view scissor only (2026-09-06).

    Drawing-buffer pixels, bottom-left origin, +Y up — the same space as view.rect after resolveRect. A backend intersects this with the view rectangle and restores the view rect after the draw. Default-off: a scene that never names one issues the same scissor calls it issued before the field existed.

    Optional, and undefined means exactly what null means — the R-23 move: the builders always write it, the field is optional so a hand-built item predating the field still typechecks, and MutableRenderItem re-declares it required so a pooled slot cannot go stale.

    transformVersion?: number

    The drawable node's transform.worldVersion at generation time — the stamp §65's idle batch cache keys on. Absent on a hand-built item, which is what tells the cache "versions unavailable, re-upload".

    transparent: boolean

    §66 sort key 2, read off the item's material (§57's transparent) at generation time: false for an opaque draw, true for a blended one.

    Snapshotted onto the item rather than reached through material.transparent inside the comparator, for the reason §64 gives for compact render items — a comparator runs O(n log n) times and must not chase a reference per call — and because a particle item has no material to ask.

    viewDepth: number

    §66 sort key 4, in view space — written by sortRenderListByDepth and meaningless until it has run (R-8, 2026-08-09).

    Distance from the camera along its forward axis, larger meaning farther. The measurement lives on the item, like every other sort key, because a comparator runs O(n log n) times and must not transform a matrix per call (§64's compact-item rule).

    Reset to 0 by both builders, so the value a pooled slot carries is a fact of the item and not of whatever occupied the slot last frame — the hazard the material and frame resets in collect exist for. A caller reading it without having sorted reads that 0.

    worldBounds?: BoundingSphere | null

    Optional world-space cull sphere, written when the drawable publishes a bound that is not its geometry box — today, a §36 particle system whose node has structural computeBounds. null / absent means "derive from geometry" (the ordinary path). Optional so a hand-built item predating the field still typechecks.

    worldMatrix: Matrix4

    World transform of the drawn node.

    buildRenderList stores a reference to the node's own transform.worldMatrix, so the item costs nothing to fill and always reflects the last resolve. buildInterpolatedRenderList stores a pooled matrix holding the §43 render pose instead. Either way: read it, upload it, do not mutate it.