Skip to content
Docs
Open Promoeyes
app-posters

app-posters

APP POSTERS — eleven static app-launch key-art frames (1080 × 1350, 4:5). Nothing moves: no scene has a keyframe; each holds one frame for 3 s. Every poster is a real 3D set — devices, walls, props, light and shadow — with the poster's type laid over it on a PRINT PLANE.

Read the rig's notes
THE PRINT PLANE — flat graphic type registered exactly onto a 3D render
  A `ui3d` stage square to the camera, d mm in front of the lens, sized to fill the frame:
  fov 30 → frame height at d = 2·d·tan 15° = 0.535898·d, width = 0.8 × that. d = 300 → world
  128.62 × 160.77. Its template is a 240 × 300 mm card whose HTML is written at 1318 × 1648 css
  px with a TRANSPARENT background, so the HTML layout IS the poster layout (css x ÷ 1318 =
  frame x). Level cameras keep it rotation-free: position = camera + (0 0 −d). For placing
  world objects: at depth D from a level lens the frame spans ±0.214359·D by ±0.267949·D, so
  a thing meant to land at frame point (X, Y) measured at z 0 sits at (X, Y)·(Z_cam − z)/Z_cam.

FOUR ENGINE FACTS THESE POSTERS DEPEND ON
  · A postprocessing chain has no implicit output transform: `render → aa` alone leaves the
    frame LINEAR — background, lit surfaces and UI alike (#123d29 → #020c06, #5fd38a →
    #1da641) — and the renderer's tone_mapping is ignored once a chain exists (Neutral, None
    and ACESFilmic gave identical pixels). Some step must encode: `step(name=output …)` or
    the house idiom `film_grain … output_transform=1|2` (measured pixel-identical to
    output none). Here: `step(name=output tone_mapping=none)` before the SSAA step — sRGB
    encode only, so UI hexes print exact; lights are set so nothing needs a curve.
  · A device screen overlay is stamped render_order + i and drawn AFTER free-standing ui3d
    panels (depth-slab orders ≤ 1, no depth write), so a phone's screen paints over a panel
    that is nearer the lens. Every screen here is `render_order=-100`: screens draw first,
    nearer panels (print plane, chips, cards) land on top, and opaque bodies still occlude.
  · `g#…(position rotation)` does NOT move its children (an identity container). A rigid
    prop group is a `primitive#id(position rotation)` with `geometry(type=group)` and its
    parts as siblings carrying `parent=id` (ui3d faces included) — the gift, the plus
    blocks, the app icon, the glass cubes and the walnut table are all built that way.
  · `path3d` swept along a 3D `d` built broken, giant geometry (and a NaN-bounds console
    error); the P11 loop is a tipped torus instead.

RESKINNING FOR ANOTHER APP
  1. app-posters.screens.html — rewrite the poster's sections: `pNN-screen` (the phone glass,
     390 × 846), `pNN-print` (the type, 1318 × 1648, transparent), its floating panels.
  2. convert: npx tsx scripts/html-screens.mts with the .screens.html, .sections.json and
     .screens.json in this folder as its three arguments.
  3. paste each block over its `template#t-<id>`. A transparent section's root card comes back
     with NO fill and the engine paints that opaque — add `fill=transparent` to the root line
     of every print layer and floating panel (screens carry their own fill).
  4. recolour the poster's materials (named pNN-…) and its background and haze.
  5. images: `npm run promo:images` with the in flag pointing at this file.
  The sets, lights and cameras do not change with the app.

THE ELEVEN
  p01 locals     orange room corner, the phone standing in it; centred lockup, partner strip
  p02 paybloom   periwinkle field, a giant black phone in close-up, rolled 24°, its side buttons
                 to camera; a huge three-line download call bleeding off the left edge
  p03 billo      deep green; a lighter green slab behind the phone and a slab the colour of the
                 background in FRONT of it, cut on a 5° diagonal — the phone rises out of a slot
  p04 lumo       leaf-green wall, the phone straight on, cropped by the bottom edge, its shadow
                 on the wall; an oversized greeting cropped by the top edge
  p05 tidepay    royal blue announcement; the phone tilted 22° into the bottom-right corner,
                 200 mm nearer the lens than the type, over a dark disc
  p06 kite       a phone face-up on a walnut table, notification cards floating above it facing
                 the lens; window, mug and plant behind, lost in depth of field. No print plane
  p07 sprout     blush wall, a serif announcement; the phone yawed toward a feature list whose
                 icons are modelled props (gift, chat bubble, salad bowl, notebook, heart)
  p08 launch     pale studio agency poster: two phones adrift at different depths, a drawn
                 rounded frame behind them, a glossy sphere with a ring, two plus blocks
  p09 heyo       mint wall, giant 3D "hey" letters standing off it, a silver phone, a modelled
                 app icon in front of the phone, three chips in front of that
  p10 nova labs  navy; a phone tipped into an isometric pose, its UI exploded into six cards
                 that share the screen's plane at different lifts, three glass icon cubes
  p11 fundly     black stage, a tilted violet neon loop behind two phones, problem /
                 solution cards and a home-screen close-up on the print plane

Units mm (1 unit = 1 mm). Preview:
http://localhost:4444/runtime?project=promos/primitives/static/app-posters/app-posters.promo
Topic
static
Scenes
11
Kind
reference rig
//
    APP POSTERS — eleven static app-launch key-art frames (1080 × 1350, 4:5). Nothing moves: no
    scene has a keyframe; each holds one frame for 3 s. Every poster is a real 3D set — devices,
    walls, props, light and shadow — with the poster's type laid over it on a PRINT PLANE.

    THE PRINT PLANE — flat graphic type registered exactly onto a 3D render
      A `ui3d` stage square to the camera, d mm in front of the lens, sized to fill the frame:
      fov 30 → frame height at d = 2·d·tan 15° = 0.535898·d, width = 0.8 × that. d = 300 → world
      128.62 × 160.77. Its template is a 240 × 300 mm card whose HTML is written at 1318 × 1648 css
      px with a TRANSPARENT background, so the HTML layout IS the poster layout (css x ÷ 1318 =
      frame x). Level cameras keep it rotation-free: position = camera + (0 0 −d). For placing
      world objects: at depth D from a level lens the frame spans ±0.214359·D by ±0.267949·D, so
      a thing meant to land at frame point (X, Y) measured at z 0 sits at (X, Y)·(Z_cam − z)/Z_cam.

    FOUR ENGINE FACTS THESE POSTERS DEPEND ON
      · A postprocessing chain has no implicit output transform: `render → aa` alone leaves the
        frame LINEAR — background, lit surfaces and UI alike (#123d29 → #020c06, #5fd38a →
        #1da641) — and the renderer's tone_mapping is ignored once a chain exists (Neutral, None
        and ACESFilmic gave identical pixels). Some step must encode: `step(name=output …)` or
        the house idiom `film_grain … output_transform=1|2` (measured pixel-identical to
        output none). Here: `step(name=output tone_mapping=none)` before the SSAA step — sRGB
        encode only, so UI hexes print exact; lights are set so nothing needs a curve.
      · A device screen overlay is stamped render_order + i and drawn AFTER free-standing ui3d
        panels (depth-slab orders ≤ 1, no depth write), so a phone's screen paints over a panel
        that is nearer the lens. Every screen here is `render_order=-100`: screens draw first,
        nearer panels (print plane, chips, cards) land on top, and opaque bodies still occlude.
      · `g#…(position rotation)` does NOT move its children (an identity container). A rigid
        prop group is a `primitive#id(position rotation)` with `geometry(type=group)` and its
        parts as siblings carrying `parent=id` (ui3d faces included) — the gift, the plus
        blocks, the app icon, the glass cubes and the walnut table are all built that way.
      · `path3d` swept along a 3D `d` built broken, giant geometry (and a NaN-bounds console
        error); the P11 loop is a tipped torus instead.

    RESKINNING FOR ANOTHER APP
      1. app-posters.screens.html — rewrite the poster's sections: `pNN-screen` (the phone glass,
         390 × 846), `pNN-print` (the type, 1318 × 1648, transparent), its floating panels.
      2. convert: npx tsx scripts/html-screens.mts with the .screens.html, .sections.json and
         .screens.json in this folder as its three arguments.
      3. paste each block over its `template#t-<id>`. A transparent section's root card comes back
         with NO fill and the engine paints that opaque — add `fill=transparent` to the root line
         of every print layer and floating panel (screens carry their own fill).
      4. recolour the poster's materials (named pNN-…) and its background and haze.
      5. images: `npm run promo:images` with the in flag pointing at this file.
      The sets, lights and cameras do not change with the app.

    THE ELEVEN
      p01 locals     orange room corner, the phone standing in it; centred lockup, partner strip
      p02 paybloom   periwinkle field, a giant black phone in close-up, rolled 24°, its side buttons
                     to camera; a huge three-line download call bleeding off the left edge
      p03 billo      deep green; a lighter green slab behind the phone and a slab the colour of the
                     background in FRONT of it, cut on a 5° diagonal — th