Presets
Drop your product into a ready-made room, stand it on a pedestal, or use our
materials and HDRIs. Everything in @oeave/bakery3/presets is an ordinary
Three.js object or material.
Put your product in a ready-made room
A room preset is a whole interior chosen by name: walls with windows, a floor, a pedestal, furniture and designed lighting.
import {
createPresetRoom,
applyPresetRoomCamera,
} from '@oeave/bakery3/presets';
const room = createPresetRoom('loft_golden');
scene.add(room);
product.position.copy(room.userData.stand); // the top of the pedestal
applyPresetRoomCamera(camera, room); // the framing the room was designed with
renderer.toneMappingExposure = room.userData.exposure; // as bright as designed
camera.far = 100; // the view outside the windows is 60 m away
camera.updateProjectionMatrix();The rooms are atelier_skylight, beam_loft, conservatory_day,
dining_golden, gallery_day, living_evening, loft_golden,
noir_parlour, plaster_atelier, slat_lounge, studio_night and
walnut_salon. ROOM_PRESETS lists each one with its size, defaults, stand
height and camera.
The room is centered on the origin with its floor at y = 0. Move or rotate the
group freely, and the render follows.
Change the light, the surfaces and the stand
const room = createPresetRoom('loft_golden', {
lighting: 'golden', // day | golden | overcast | night
walls: { material: 'white_plaster', color: '#e9dfd0' },
floor: 'oak_floor',
pedestal: 'pedestal_column', // any pedestal preset, or null for the floor
pedestalMaterial: 'carrara_marble',
});| Option | Default | What it does |
|---|---|---|
lighting | the room's own | day, golden, overcast or night. |
floor, walls, ceiling | the room's own | A material preset, or { material, color } to tint it. |
sill | the room's own | The material of the window sills. |
pedestal | the room's own | What the product stands on: a pedestal preset, or null for the floor. |
pedestalMaterial | the room's own | The material of the pedestal. A room that stands its product on a table keeps the table's finish. |
hdri | the room's own | The HDRI outside the windows. Name one from HDRI_PRESETS, or false for a plain sky. It is only a backdrop: the room keeps its own light. |
lights | true | false removes the viewport lights so you can light the room yourself. |
baked | true | Shows the room's baked version in the viewport, when it has one. See below. |
bake | false | Makes the room itself bakeable. See below. |
prebaked | true | For a room shown as a stand-in: puts its pre-traced lightmaps on, when it has some. |
baseUrl | the preset CDN | Load the room from your own host. |
The group gives you these values on userData:
| Field | What it is |
|---|---|
stand | A Vector3: where the product goes. |
topY | The height of the stand. |
exposure | The toneMappingExposure the room was designed under. |
ready | A promise that resolves when the room has loaded. |
shown | 'baked' or 'standIn': which version of the room the viewport is showing. |
environment | In a baked room: what your product reflects. Give it to scene.environment. |
prebaked | A promise that resolves when the pre-traced light is on, or to null when the room has none. |
The render uses whatever exposure your renderer is set to. With
userData.exposure the viewport and the render are both as bright as the room
was designed. At exposure 1 the picture is about a stop darker.
What the render adds
The viewport shows an optimized version of the room so you can frame your product. The render builds the full room: every piece at full detail, 4k materials, leaves outside the windows that dapple the sun, haze, and the real light fixtures. Expect the render to look richer than the viewport.
- Nothing of the room is uploaded. A product in a room uploads what the product alone would.
- The room lights the render.
scene.environmentis not used while a room preset is in the scene. - The render is lit exactly as the room you see was. A baked room was traced under the same light a render of that lighting mode uses.
- Set
camera.farto 100 or more. The view outside hangs on a dome 60 m out, and a shorterfarclips the sky through the windows to black. The console warns you when that happens. - Keep one room preset in the scene when you render.
The compatibility report notes the rebuilt room and the unused
scene.environment as info items.
When a room is updated, the renderer keeps the version your SDK shows, so an
older @oeave/bakery3 keeps rendering the room you see. If your SDK is newer
than the renderer, the render uses the renderer's version of the room and
carries a RoomPresetBuildFallback warning; the two may differ slightly.
Rooms that arrive already lit
Most rooms have a baked version: one optimized file with the room's traced light already in it. When the room you ask for has one, the viewport shows it, so the room looks like its render the moment it loads. You do nothing to get it.
const room = createPresetRoom('slat_lounge', { lighting: 'night' });
scene.add(room);
await room.userData.ready;
renderer.toneMappingExposure = room.userData.exposure; // the light was traced at this exposure
room.userData.shown; // 'baked'
scene.environment = room.userData.environment ?? null; // optional: the room in your product's reflections- Your product is lit by the room. The baked room carries a light for what
the room throws back at the product, and the product's shadow falls on the
floor. Turn on
renderer.shadowMap.enabledandcastShadowon your product to see it. - A render is the real room. The baked version is only what the page draws. A render builds the full room under the same light.
- A bake covers your product only. See Bake a product in a ready-made room.
ROOM_PRESETS[name].baked lists the lighting modes that have a baked version.
The viewport shows a lighter stand-in instead when:
- the room has no baked version for that lighting,
- you changed the room: a surface, the sill, the stand or its material, the HDRI outside, or a picture of your own,
- you passed
bake: true,lights: falseorbaked: false.
The stand-in is lit by ordinary viewport lights, scaled per room so the
preview is about as bright as the render. If the room also has pre-traced
lightmaps (ROOM_PRESETS[name].prebaked), they go on once the stand-in has
loaded. await room.userData.prebaked resolves when they are on,
setPresetRoomPrebaked(room, false) turns them off, and prebaked: false
never downloads them.
Hang your own pictures
Rooms with a frame on the wall take your image in it.
const room = createPresetRoom('living_evening', {
pictures: ['/art/campaign-01.jpg'],
});Pass a URL the page can fetch, or a Blob if your shopper just uploaded one.
One entry per picture the room hangs, in the order it hangs them. Use null to
leave one as it came, and a short list leaves the rest.
ROOM_PRESETS[name].pictures says how many there are and which wall each is on:
ROOM_PRESETS.living_evening.pictures; // [{ wall: 'north', size: 0.7 }]The frame does not move. Its moulding and its passepartout were built to the
shape of the image the room was published with, so your picture is cropped to
fill the opening, centered, the way object-fit: cover fills a box. A portrait
photograph in a landscape frame is cropped top and bottom, not letterboxed.
The image is uploaded with your scene and cached by content, so hanging the same picture again uploads nothing new.
Bake the room itself
Pass bake: true and the room's floor, walls, ceiling, sills, stand and
furniture are sent with your scene like any other mesh.
A bake then includes them, so the shadow under your product
and the bounce on the walls are baked onto the room. The renderer still provides
the light. It is off by default, so a plain render uploads only the product.
const room = createPresetRoom('living_evening', { bake: true });Build a room of your own
createRoom() builds an empty room from your sizes, materials and windows. The
floor is at y = 0 and the room is centered on the origin.
import { createRoom } from '@oeave/bakery3/presets';
scene.add(
createRoom({
width: 4, // meters. defaults are 4 × 4 × 2.7
depth: 4,
height: 2.7,
floor: 'oak_floor',
walls: 'white_plaster',
ceiling: 'matte_paint', // null for an open ceiling, studio light from above
wallThickness: 0.15, // the depth of the window reveals
windows: {
north: [{ width: 1.6 }],
west: [{ width: 0.9, offset: -1.2 }],
},
sun: { elevation: 32, azimuth: 0, intensity: 3.5 },
}),
);North is the −z wall. A window's offset is measured to your right as you face
the wall from inside. A window also takes height, sill, frame, glass
and foliage.
From outside you see straight through the walls, which makes orbiting easy. They still block light.
Everything is named, so you can restyle or remove it.
floor, ceiling meshes
wall-north (−z), wall-south, wall-west, wall-east groups
└ face mesh
└ window-N group (reveal-*, frame, glass, foliage)
sun group (sun-light + aim target)Let the sun in
sun: true puts a shadow-casting DirectionalLight outside the room, aimed
through a window. You see the shafts of light in the viewport and in the
render.
Shadows are as crisp as real sunlight by default (angleDeg: 0.53). Raise
angleDeg for an overcast look. It is stored as userData.bakery3.angleDeg on
the light, so you can set it on a DirectionalLight of your own too.
Every window grows leaves outside it by default, so the sun lands dappled
instead of as one hard rectangle. foliage: false on a window turns them off.
Put a sky outside the windows
A studio HDRI seen through a window looks wrong, and its light is too neutral
for daylight. createSkyEnvironment() makes a sky: blue overhead, pale at the
horizon, warm ground below. Nothing is downloaded, and the render gets the same
sky as the viewport.
import { createRoom, createSkyEnvironment } from '@oeave/bakery3/presets';
scene.environment = createSkyEnvironment(); // { zenith, horizon, ground, intensity }
scene.add(
createRoom({ windows: { east: { width: 2.4 } }, sun: { azimuth: 110 } }),
);If your configurator shows the product on white, you can keep a studio HDRI in the live view and use the sky only for the render. See render-only set dressing.
Stand your product on a pedestal
import { createPedestal } from '@oeave/bakery3/presets';
const pedestal = createPedestal('pedestal_column', {
material: 'carrara_marble',
});
scene.add(pedestal);
product.position.y = pedestal.userData.topY;
await pedestal.userData.ready; // wait for the model before you renderThe pedestals are pedestal_block (the default), pedestal_plinth,
pedestal_cylinder and pedestal_column. createPedestal({ type, material })
takes the same options as one object. Each loads at its real size in meters and takes any preset
material. The furniture, plants and decor in the room presets come with the
rooms and are not offered on their own.
Use a preset material
Every material comes with albedo, normal, roughness, AO and height maps, and tiles without a visible seam.
import {
createPresetMaterial,
loadPresetMaterial,
} from '@oeave/bakery3/presets';
const marble = createPresetMaterial('carrara_marble', {
size: '4k', // '2k' is the default; '4k' for close-ups
repeat: 2, // extra multiplier on the physical repeat
ao: false, // skip the AO map
anisotropy: 8,
});
// Or wait until every map has loaded:
const oak = await loadPresetMaterial('oak_floor');The fifteen materials are oak_floor, walnut_floor, white_plaster,
matte_paint, polished_concrete, carrara_marble, terrazzo, travertine,
white_brick, coated_pine, laminate_floor, oak_veneer_05,
plank_flooring_04, synthetic_wood and wooden_floor_02.
createPresetMaterial() returns a MeshStandardMaterial at once and fills in
as the textures arrive. Tint any material through material.color.
matte_paint is made for it.
Textures repeat at their real size. Preset rooms and pedestals have UVs in
meters, and each texture repeats at 1 / tileMeters, so an oak plank is
plank-sized on a 6 m floor and on a 0.4 m pedestal. Give your own geometry UVs
in meters to get the same.
Light with a preset HDRI
import { loadPresetEnvironment } from '@oeave/bakery3/presets';
scene.environment = await loadPresetEnvironment('ferndale_studio_11');The browser loads a small 1k preview. The render uses the 4k original, which
your page never downloads or uploads. To show the HDRI behind the product,
render with background: { type: 'environment' }. See
Environment & lighting for backgrounds and your own HDRIs.
category | Names |
|---|---|
studio | ferndale_studio_11, ferndale_studio_12, monochrome_studio_02, studio_kontrast_04, studio_small_03 |
day | sunny_country_road, horn-koppe_spring, grasslands_sunset, je_gray_02 |
golden | qwantani_sunset, venice_sunset, bambanani_sunset, umhlanga_sunrise, flamingo_pan, minedump_flats, sunset_fairway, the_sky_is_on_fire |
overcast | dalkey_view, afrikaans_church_exterior, quarry_cloudy |
night | moonless_golf, preller_drive, satara_night |
The studio HDRIs are for product shots. The outdoor ones are what a room preset shows outside its windows in each lighting mode.
Read the catalog
import {
MATERIAL_PRESETS,
PEDESTAL_PRESETS,
HDRI_PRESETS,
ROOM_PRESETS,
} from '@oeave/bakery3/presets';
MATERIAL_PRESETS.oak_floor.tileMeters; // physical tile size
PEDESTAL_PRESETS.pedestal_column.size; // { x, y, z } in meters
HDRI_PRESETS.ferndale_studio_11.category; // 'studio'
ROOM_PRESETS.loft_golden.size; // { width, height, depth } in metersHost the presets yourself
Presets are served from https://cdn.bakery3.com/presets by default.
import { setPresetBaseUrl } from '@oeave/bakery3/presets';
setPresetBaseUrl('https://cdn.example.com/bakery3-presets');createPresetMaterial(), createPedestal(), createPresetRoom() and
loadPresetEnvironment() also take a baseUrl option for one call.
Where the presets come from
The HDRIs, six of the materials and some of the models in the rooms come from Poly Haven under the CC0 license: free for any use, no attribution needed. We made the pedestals and the other materials. Some of the furniture and plants in the rooms are licensed models. You see them in your renders and as a lighter stand-in in the viewport, but they are not available to download.
