Skip to content

Add diegetic NPC dialogue demo — interactive HTML in a Three.js scene (#71)#113

Open
Twynzen wants to merge 1 commit into
WICG:mainfrom
Twynzen:demo/diegetic-npc-dialogue
Open

Add diegetic NPC dialogue demo — interactive HTML in a Three.js scene (#71)#113
Twynzen wants to merge 1 commit into
WICG:mainfrom
Twynzen:demo/diegetic-npc-dialogue

Conversation

@Twynzen

@Twynzen Twynzen commented Apr 18, 2026

Copy link
Copy Markdown

Summary

Adds an interactive HTML dialogue panel rendered as a texture on a 3D billboard plane in a Three.js scene, using the new texElementImage2D API. Addresses #71 by providing an interactive
alternative to the existing webGL cube demo.

What it showcases

  • Real DOM controls<select>, <input>, and <button> with full keyboard and
    screen-reader access, painted into the 3D scene.
  • Stable hit-testing under orbit — OrbitControls camera lets the user rotate around the NPC
    while all controls remain responsive, including <input> focus and typing.
  • Three.js integration pattern — the demo documents how to work around the friction between
    texElementImage2D (spec'd like texImage2D) and Three.js' default texStorage2D immutable
    storage, by creating the GL handle manually and injecting it into the library's texture cache.

How to test

  1. Open in Chrome Canary with chrome://flags/#canvas-draw-element enabled.
  2. Serve the repo locally and open Examples/diegetic-npc-dialogue.html.
  3. Try the select dropdown, type in the input, and orbit the camera with mouse drag — interaction
    should remain stable in any viewing angle.
  4. Keyboard: Tab cycles through select → input → button. Arrow keys change the select value. Typing updates the rendered texture.

Notes on integration friction (feedback for #94)

While building the demo I hit three issues worth documenting — I can open a separate comment on #94 with the full analysis, but briefly:

  1. Three.js allocates textures as immutable (texStorage2D), which fails texElementImage2D.
    Workaround: bypass the library's allocation via renderer.properties.get(tex).__webglTexture.
  2. Naively computing the CSS transform from getBoundingClientRect() is self-referential and
    drifts. Measuring a natural-position anchor once and computing absolute transforms fixes it.
  3. Library camera controls (OrbitControls, etc.) attached to the canvas capture pointerdown from
    interactive DOM descendants — stopPropagation() on the panel is required.

Happy to expand on any of these if helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant