Publishing gate

Run the WebGL scene health check

Use the checklist to score assets, camera behavior, rendering, mobile performance, loading states, and fallback content before publishing.

Run Scene Check Compare lab tools

Most picking bugs start with coordinates

Raycaster expects normalized device coordinates where x and y are between -1 and 1. Many examples compute them from `window.innerWidth` and `window.innerHeight`, which works only when the canvas fills the window. If your canvas sits inside a layout, sidebar, or article card, use the canvas bounding rectangle.

Pointer coordinates also need to be measured after CSS transforms and responsive resizing. If a click feels offset, log the canvas rectangle and the computed normalized values. The raycaster may be correct while your coordinate conversion is wrong.

Pick against a deliberate list

Raycasting the whole scene is convenient for a demo but noisy for production. Grids, helpers, invisible bounds, particles, and background meshes may all receive intersections. Keep a `pickables` array and add only objects that should respond to the pointer.

For imported GLB scenes, traverse the model and mark meshes that should be interactive with userData. That makes the decision visible in code. A product part selector, for example, can attach part ids or labels to pickable meshes while leaving decorative nodes alone.

Sort intent after intersection

Raycaster returns intersections sorted by distance. The nearest hit is often what you want, but not always. A transparent cover, highlight shell, or helper mesh may sit in front of the actual object. Filter intersections by material visibility, object userData, or layers before choosing.

Hover states should also be reversible. Store the last hovered object, clear its material state when the pointer leaves, and avoid creating new materials on every mousemove. Interaction bugs often become performance bugs when hover logic allocates objects repeatedly.

Make mobile picking forgiving

Touch input is less precise than a cursor. Small meshes can be frustrating to select on mobile. Consider larger invisible hit targets, part-level grouping, or a list-based fallback when touch selection needs to be reliable. A viewer can still use raycasting internally while presenting simpler choices in the UI.

If picking is the core of the tool, show the selected object name or id in a small status area. Clear feedback makes users trust that the scene is responding.

When this guide is the right tool

Use this guide when the problem is specific enough that a broad Three.js tutorial would waste time. The focus here is Raycaster in a real browser page: what to check first, what to measure, and what to avoid before the scene becomes harder to reason about.

The practical rule is simple: Convert pointer coordinates from the canvas bounds, not always from the window. If that sentence describes the scene in front of you, treat the article as a checklist. Read the explanation, copy the smallest useful code pattern, then test the result in a narrow mobile viewport and a wide desktop viewport before adding more polish.

Common mistake to avoid

The common mistake is treating Three.js Raycaster picking checklist as a visual tweak instead of a scene-system decision. Three.js problems often look like one broken line of code, but the actual issue is usually a chain: asset assumptions, renderer settings, camera math, material setup, interaction state, and page layout all meet inside the canvas.

That is why the safest fix is incremental. Start from a known-good scene, change one variable, and keep a visible diagnostic while testing. Raycast against an explicit pickable list instead of the entire scene when possible. When the scene works, remove temporary helpers and leave behind only the checks that make sense for users.

Publishing check

Before publishing, run the scene through three questions. Does the page remain useful if WebGL fails or the asset loads slowly? Does the same scene still read clearly on a phone? Can another developer understand the important settings without reverse-engineering the whole file?

The last pass should be boring on purpose: verify canvas size, console errors, mobile performance, source links, internal links, and the related guide path. Use intersection distance and object metadata to decide what the user meant. If any answer is fuzzy, fix that before introducing a new effect or a larger asset.

Canvas-relative raycast

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
const pickables = [];

canvas.addEventListener('pointerdown', (event) => {
  const rect = canvas.getBoundingClientRect();
  pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
  pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

  raycaster.setFromCamera(pointer, camera);
  const [hit] = raycaster.intersectObjects(pickables, true)
    .filter((item) => item.object.visible);

  if (hit) selectPart(hit.object);
});

FAQ

When should I use Three.js Raycaster picking checklist?

Use it when your Three.js scene has a focused Raycaster problem and you need a practical checklist before adding more visual polish.

Is the code snippet production-ready?

Treat the snippet as a clear starting point. Test it in your scene, adapt naming and paths, and verify behavior on mobile hardware before publishing.

What should I check after applying this guide?

Run the scene through mobile sizing, console errors, loading states, source links, and related guide paths so the page remains useful even when assets or WebGL fail.

Sources and further reading

Related guides