b3d
The root 3D scene container. All other components (b3dSun, b3dSkybox, b3dLoader, etc.)
must be children of a b3d element.
Demo
import {
b3d, b3dSun, b3dSkybox, b3dSphere, b3dLoader,
b3dBiped, b3dButton, b3dLight, b3dWater, b3dReflections, b3dCollisions,
gameController, inputFocus, label3d, toggle3d, slider3d,
} from 'tosijs-3d'
import { tosi, elements } from 'tosijs'
const { div, span } = elements
const { demo } = tosi({
demo: {
showColliders: false,
time: 19,
},
})
const scene = '/test-3.glb'
const omnidude = '/omnidude.glb'
const formatTime = (v) => {
const h = Math.floor(v)
const m = Math.round((v % 1) * 60)
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`
}
preview.append(
b3d(
// gamepad: on-screen glass gamepad wired into the input system. XR is on by
// default — Enter VR drives the same player biped through the unified input
// spine (XR controllers → bipedMapping), chase-followed by the XR rig.
{
glowLayerIntensity: 1,
gamepad: true,
scenePanel: () => [
label3d({ text: 'Scene' }),
toggle3d({ label: 'show colliders', value: demo.showColliders }),
slider3d({ label: 'time of day', value: demo.time, min: 0, max: 24, step: 0.1 }),
],
},
b3dSun({ shadowTextureSize: 2048, activeDistance: 20 }),
b3dSkybox({ timeOfDay: demo.time, realtimeScale: 100, latitude: 30, moonIntensity: 1.5 }),
b3dSphere({ meshName: 'ref-sphere', diameter: 1, y: 1, x: -3, z: -3, color: '#aaaaaa' }),
b3dLoader({ url: scene }),
inputFocus(
gameController(),
b3dBiped({ url: omnidude, x: 5, ry: 135, player: true, cameraType: 'follow', initialState: 'look' }),
),
b3dBiped({ url: omnidude, x: -4, z: 3, ry: 45, initialState: 'idle' }),
b3dBiped({ url: omnidude, x: 3, z: -2, initialState: 'dance' }),
b3dLight({ y: 1, z: 0.5, intensity: 0.2, diffuse: '#8080ff' }),
b3dWater({ y: -0.2, twoSided: true, waterSize: 1024 }),
b3dReflections(),
b3dCollisions({ debug: demo.showColliders })
),
div(
{ class: 'debug-panel' },
span({
class: 'time-display',
bind: {
value: demo.time,
binding: (el, v) => { el.textContent = formatTime(v) },
},
})
)
)
setInterval(() => {
const skybox = document.querySelector('tosi-b3d-skybox')
if (skybox) demo.time.value = skybox.timeOfDay
}, 1000)
tosi-b3d {
width: 100%;
height: 100%;
}
.debug-panel {
position: absolute;
top: 10px;
right: 10px;
display: flex;
flex-direction: column;
gap: 16px;
padding: 8px 20px;
background: rgba(0, 0, 0, 0.6);
color: #fff;
border-radius: 6px;
font-size: 14px;
z-index: 10;
}
.debug-panel label {
display: flex;
align-items: center;
gap: 4px;
}
.time-display {
font-family: ui-monospace, monospace;
}
Usage
import { b3d, b3dSun, b3dSkybox, b3dLoader, b3dWater } from 'tosijs-3d'
document.body.append(
b3d(
{ glowLayerIntensity: 1 },
b3dSun(),
b3dSkybox({ timeOfDay: 12 }),
b3dLoader({ url: '/scene.glb' }),
b3dWater({ y: -0.2 })
)
)
Attributes
| Attribute | Default | Description |
|---|---|---|
glowLayerIntensity |
0 |
Glow effect intensity (0 = off) |
frameRate |
30 |
Target frame rate |
no-xr |
false |
Suppress the automatic Enter-VR button (WebXR is offered by default when an immersive-vr session is supported) |
gamepad |
absent | When present, mount the on-screen glass gamepad wired into the input system. Bare/true = full layout; a value like "a,b,left_stick" selects controls |
gamepadScale |
1 |
Scale factor for the glass gamepad clusters |
minElevation / maxElevation |
5 / 70 |
Default orbit-camera elevation limits (degrees above the horizon) |
minDistance / maxDistance |
2 / 50 |
Default orbit-camera zoom limits |