Skip to content

Place 3D Content on the Screen

Related references:

It is possible to place 3D content "onto the screen", but more precisely, this is not a dedicated API. The usual method is to attach the object under the camera.

The core idea looks like this:

js
const camera = await api.getDefaultCamera();
await api.addChild(camera, obj);

That makes the object move and rotate together with the camera, which visually feels much closer to "fixed in front of the screen".

If your goal is a typical HUD or fixed UI, it is still better to:

  1. build an HTML / CSS UI in the host page
  2. let the Kivicube iframe focus only on 3D / AR content

This is a better fit for:

  • titles
  • buttons
  • explanatory text
  • guide arrows
  • responsive layouts

The reasons are straightforward:

  • it is easier to adapt across devices
  • it is easier to align with host-page styling
  • it is easier to make clickable, track analytics, and animate
  • you do not need to keep adjusting 3D coordinates

When a Screen-Fixed 3D Object Does Make Sense

This works better for content that:

  • should remain a real 3D object
  • still needs to participate in material, lighting, or transparency effects
  • should feel like a 3D decoration floating in front of the lens
  • should keep reusing existing object animation or model assets

Basic Implementation

1. Get the Camera and Target Object

js
const camera = await api.getDefaultCamera();
const obj = await api.getObject('screen-object');

If the object is created at runtime, you can also use the returned handle directly:

js
const obj = await api.createImage('/assets/tag.png');

2. Attach It Under the Camera

js
await api.addChild(camera, obj);

3. Adjust Its Position in Camera Space

js
await api.setPosition(obj, 0, 0, -2);
await api.setScale(obj, 0.5, 0.5, 0.5);

The most important value here is z:

  • z is usually negative, meaning the object is placed in front of the lens
  • values closer to 0 make it appear closer to the screen
  • smaller values make it appear farther away

x and y determine the horizontal and vertical position on screen.

For example:

js
// Centered but lower
await api.setPosition(obj, 0, -0.6, -2);

// Near the upper-left corner
await api.setPosition(obj, -1.2, 0.8, -2);

4. Adjust Rendering State

js
// Keep the object on top and disable depth testing / depth-buffer writes.
const recursive = true; // Apply the same settings to all child nodes as well. Default is false.
await api.setGLState(obj, "depthTest", false, recursive);
await api.setGLState(obj, "depthWrite", false, recursive);

Complete Example

js
iframe.addEventListener('ready', async (event) => {
  const { api } = event.detail;

  const camera = await api.getDefaultCamera();
  const image = await api.createImage('/assets/floating-badge.png');

  await api.addChild(camera, image);

  await api.setPosition(image, 1.1, -0.8, -2);
  await api.setScale(image, 0.35, 0.35, 0.35);

  const recursive = true;
  await api.setGLState(image, "depthTest", false, recursive);
  await api.setGLState(image, "depthWrite", false, recursive);
});

Remove the Screen-Fixed Behavior

If you no longer want the object attached to the camera, remove that parent-child relationship and attach it elsewhere:

js
await api.removeChild(camera, obj);

If you only want to hide it:

js
await api.setObjectVisible(obj, false);

Adaptation Recommendations

Although this technique can create a "screen-fixed" effect, it still uses 3D coordinates rather than CSS pixels. So:

  • positions may need fine-tuning for different aspect ratios
  • visual placement also changes with different FOV values
  • if the object is too close to the camera, it may appear oversized or get clipped

A safer approach is:

  • start with one baseline coordinate set
  • fine-tune only on key target devices
  • keep real interactive buttons in host-layer HTML
  • when you need precise alignment with host-page buttons
  • when you need complex responsive layout
  • when you need lots of text
  • when you need stable hit areas
  • when the object must coordinate with page scroll, modals, or forms

In those cases, HTML / CSS is usually a better fit than a 3D solution.