Skip to main content

Every prop you've set so far has been just that — a property. position, color, intensity: solid-three takes the value and assigns it to the three.js object. That covers most of what a scene needs, but not all of it.

Some of the things you'd reach for aren't properties — they're methods. three's Object3D has a lookAt(target) method that turns an object to face a point in space. You'd love to write <T.Mesh lookAt={somePoint} /> and have it just work. But it won't: props get assigned, so solid-three would overwrite mesh.lookAt with your point and the method would be gone. Props set properties; they don't call methods.

A plugin closes that gap. It teaches solid-three a new prop — one that runs a function instead of assigning a value.

Writing the plugin

import { plugin } from "solid-three"
const lookAt = plugin([THREE.Object3D], object => ({
lookAt: (target: THREE.Vector3) => object.lookAt(target),
}))

That's the whole thing. plugin([THREE.Object3D], …) matches every element that's an Object3D, and for each one contributes a lookAt method. Now when you set a lookAt prop, solid-three calls this method with the value instead of assigning it — so <T.Mesh lookAt={point} /> runs mesh.lookAt(point), exactly what we wanted.

Registering it

createT takes the plugins as its second argument. The T it hands back understands the props they add:

const T = createT(THREE, [lookAt])

Seeing it work

Move the pointer over the field below — every cone turns to face it.

Each cone is nothing more than <T.Mesh lookAt={target()} />. A wide, invisible backdrop reports the pointer's position with the onPointerMove and intersection.point from the pointer chapter, and that point flows into every cone's lookAt prop. When the signal changes, the prop re-applies and the plugin calls lookAt again — the same reactivity that drives every other prop in the tour, now driving a method.

There's more

lookAt is the simplest shape. Plugins can also match by a type-guard instead of a class, register on a single element with <Entity plugins={…} /> instead of the whole renderer, and the props they contribute are fully typed — pass a wrong one and the type-checker stops you. The Plugins reference covers the rest.

That's the extension seam: when a prop you want isn't a property, a plugin makes it one. For the encore, a peek at where three.js — and this renderer — are heading: WebGPU.

Last updated: 6/8/26, 11:20 AM

solid threeA SolidJS renderer for three.js — learn by reading.
Community
github