¶ Technique · No 3D engine required
The Composite PNG Method.How we'd actually build it.
This is the cheapest path to a configurator that feels 3D. It's how Apple Watch Studio looks so good with no actual 3D engine, and it's what Christopher Ward ships on Shopify Plus. Worth understanding properly before you commission anything.
The core idea
Instead of building a 3D model and rendering it live in the browser, you pre-render every part of the product as a flat 2D image with a transparent background — once, in advance, in a proper renderer like Blender or KeyShot — and then stack those images on top of each other in the browser like layers in Photoshop.
If your layers line up pixel-perfectly and your rendering is good, the result is visually indistinguishable from real-time 3D to the user. They never know the difference.
A concrete CHUUG example
Imagine you want the user to customise: Wood (6 options) × Metal coin (4 options) × Rope (3 options) × Initial engraving (any letter).
The naïve approach (don't do this) — render every combination as one flat image. That's 6 × 4 × 3 × 26 letters = 1,872 images. Insane.
The composite approach (do this) — render each PART separately, transparent, at the same exact camera position:
5engraved-initial-M.pnglive, swappable
4rope-natural-charcoal.png3 variants total
3coin-brass.png4 variants total
2wood-sleeve-midnight.png6 variants total
1steel-core.pngalways there
0shadow-floor.pngalways there
That's only 1 + 6 + 4 + 3 + 26 = 40 images to render once. Instead of 1,872.
Each PNG is, say, 1200×1200 pixels with a transparent background, ~50–80 KB as WebP. The browser layers them at runtime. When the user clicks "Dusk wood", you swap layer 2 from wood-sleeve-midnight.webp → wood-sleeve-dusk.webp and cross-fade. The other layers don't move.
The crucial detail — same camera, same lighting
For this to work, every single PNG must be rendered from the exact same camera position with the exact same lighting setup. That's a few hours of one-off setup in Blender:
- Build the scene once: camera, key light, fill light, rim light, soft floor
- Hide everything except the steel core → render → save as
steel-core.png
- Hide everything except wood-sleeve-midnight → render → save as
wood-sleeve-midnight.png
- Repeat for each part of each variant
Because the camera and lighting never move, the shadows and highlights line up perfectly when layered back together. The brain reads it as one solid object.
How it actually works in the browser
Three ways to implement, in order of complexity.
Method A · simplest, works on Shopify today
Stacked <img> tags
<div class="chuug-composite">
<img class="layer" src="/cdn/shop/files/shadow.webp">
<img class="layer" src="/cdn/shop/files/steel.webp">
<img class="layer" src="/cdn/shop/files/wood-midnight.webp" data-layer="wood">
<img class="layer" src="/cdn/shop/files/coin-brass.webp" data-layer="coin">
<img class="layer" src="/cdn/shop/files/rope-natural.webp" data-layer="rope">
</div>
.chuug-composite { position:relative; aspect-ratio:1/1; }
.chuug-composite .layer {
position:absolute; inset:0; width:100%; height:100%;
transition:opacity .35s ease;
}
// JS to swap
document.querySelector('[data-layer="wood"]').src = '/cdn/.../wood-dusk.webp';
Total page weight: maybe 400 KB. Total JS: under 1 KB. Runs on a Nokia.
Method B · what Apple uses
Single HTML5 <canvas> composite
You load each PNG into JavaScript as an Image object, then draw them onto a <canvas> element in order using ctx.drawImage(). Same result visually, but gives you:
- Cross-fade transitions between variants without a flash
- Shader-based effects like tinting the wood without re-rendering (e.g., "dawn" wood is "midnight" wood + warmth tint)
- Pixel-perfect engraving by drawing live text onto the rope layer
This is what Apple Watch Studio does. ~150 KB of JS total. Mid-senior dev can ship in 2–3 weeks.
Method C · advanced, natural upgrade path
WebGL canvas with shaders
Same composite concept, but you upload the PNGs as WebGL textures and use a fragment shader to blend them. Adds:
- Realistic shadows that update as the rope colour changes
- Material reflections that respond to mouse position (parallax cubemap fake)
- Subtle bloom on the brass coin
Probably overkill for v1, but the natural upgrade path. Same asset library, different renderer.
Why it "feels 3D" — three tricks
The magic isn't that the user thinks they're looking at 3D — it's that they never think about it at all. The product just responds. Three tricks make composite PNGs feel premium:
- Cross-fade, never snap. When swapping a wood variant, both layers exist for 300 ms, opacity fading from one to the other. The brain reads this as "the material is changing", not "the image was replaced".
- Micro-physics on the rope. When the rope colour changes, slide it down 8 px and back up over 250 ms with an ease-out-back curve. That tiny "drop" sells the layer as a physical object.
- Parallax on mouse / device tilt. Move each layer by a different tiny amount (
layer × 2 px) as the user moves their cursor. Suddenly the flat image has depth. Apple does this everywhere.
What you'd need to commission
For a CHUUG v1 launch with the composite-PNG method:
AssetQuantityCost
Hero camera angle render of each part
~15 layers per angle (1 base + 6 woods + 4 coins + 3 ropes + shadow)
£600–1,500
Live engraving render
Algorithmic — JS draws text onto rope layer
in build
36-frame turntable (optional)
Same scene, batch render overnight
+£500
Total in assets
£600–2,000
Compared to a real-time 3D Three.js build: assets alone are typically £3,000–8,000, plus a more expensive dev build (R3F + Draco + KTX2 + shaders).
Build time: 2–3 weeks for v1 (single-angle composite, click to swap, cross-fade, share-URL). Versus 8–12 weeks for full R3F.
When the composite method falls down
Honest disclosure of the limits:
- No free-orbit. The user can't drag to rotate. But: you can fake it with a 36-frame turntable scrubbed on swipe — Porsche does exactly this and it feels great. Same composite approach, just multiplied by N angles.
- No live lighting changes. If you want "see this in the kitchen vs the workshop", you need to pre-render against each environment. That's a 4× multiplier on assets. Not bad.
- Engraving is the one tricky bit. You can't pre-render every letter. So you either (a) draw the letter live on a 2D canvas using a font that mimics the engraved look — works for 95% of cases — or (b) render a displacement map of the engraving area and use a WebGL shader to bake the text in. (a) is what I'd ship first.
Why this is the right play for CHUUG
- Your variant matrix is small. 6 × 4 × 3 = 72 product states. That's renderable overnight. Brands with hundreds of variants can't use this method — Porsche has tens of thousands of combinations, but they still pre-render because they can afford to. You're well within the sweet spot.
- You're on Shopify. Pure-image-stack composite ships as a Liquid section + a tiny JS file + WebPs in your Files area. No headless rebuild, no Hydrogen. Christopher Ward does exactly this and looks expensive doing it.
- The cost-vs-quality ratio is the best in the industry. £600–2,000 in assets + 2–3 weeks of dev work beats 80% of real-time-3D competitors on perceived quality. The Apple Watch Studio team chose this method on purpose, with infinite budget — that should tell you something.
What we ship first
Method A or B, single hero camera angle, ~15 pre-rendered layers, cross-fade transitions, shareable URLs. £600–2,000 in assets + 2–3 weeks of build. Total cost likely well under £5,000 all-in for a v1 launch. The R3F upgrade path is open if and when you want it.