This is a collection of notes im putting together to better understand how to work with 3D stuff in React. Im writing it as to myself, as that's who it is for, but if others find it useful then that's cool too. But it's not written as a tutorial or anything. Fair warning!
Set whole page to fill 100% width and height
What is all this stuff
The Canvas component renders threejs elements, not DOM elements. It takes the whole height and width of it container, so that is why, if you want to do a whole page 3D rendering of something then you need to set the containers (in our case the actual body, as we are only doing one page) width and height to 100%.
We cant directly use HTML elements within the Canvas though there is a way to do that which I will go over later.
Because the Canvas component renders threejs elements we can use stuff like mesh, sphereGeometry and meshStandardMaterial amongst many others. It provides all these via its context to any children rendered within it, translating the threejs API into React components that can be used as normal so we can also pass props to these elements/components too.
mesh, geometry and material
A mesh is like the base skeleton an object is made from, like a wire frame or modal.
The geometry is the shape the mesh will take and the material is what will cover the mesh, how it will look. You can use different types of materials which change the way you can interact with the object and how it behaves.
There are lots of different geometry and materials that can be used directly in Canvas like a HTML element. Such as meshStandardMaterial or sphereGeometry.
The attach prop on the geometry and material above attaches the element to its parent, in this case the mesh as the set value. So the sphereGeometry is attached to th4e mesh as the geometry and the meshStandardMaterial is attached to the mesh as the material.
Constructor arguments are passed with the args prop. The sphereGeometry takes a number of constructor args, the first three of which are the radius, width and height. See the SphereGeometry docs on threejs for more information. As an example, the constructor args for the sphere are:
If no sources of lights are provided then the object will be black. Which makes sense as without light we wouldn't be able to see ti in real life. A list of the light sources taken from a smashing magazine article:
Spheres with different materials.
The first ball uses the drei helper component Sphere and a wobble material.
The second uses the traditional react-three-fiber mesh and threejs elements.
The third uses a drei Sphere with a distort material attached. A couple of lights are added to give both color to the objects and a sense of space.
The code for all three
Drei (three in german) is a super helpful package that contains loads of helpers and abstractions for react-three-fiber. One thing that I noticed was that using drei with Nextjs (as this site does) will throw an error when trying to import stuff - cannot use import statement outside a module. This is because Nextjs uses common js modules on server side rendering. We can use withTM from next-transpile-modules in the next.config file to transpile the common js stuff in drei. We also need to dynamically import the component using the drei components and disable server side rendering. See this issue and this PR.
If you are using Nextjs....
The main players
The Renderer in react-three-fiber(R3F) is the HTML canvas element which gets added dynamically to the DOM unless specifically added via an id or className.
The scene is the stage where everything plays out. The meshes encompass lights, groups, 3D positions and cameras. A scene can be thought of as a theater scene where the mesh or groups of meshes are the act that will play out, the lights give the mesh and its geometry and materials a purpose on the scene, they light them from angles and provide context to why they are there. The cameras and positions allow us to view them all from different angles.
A handy canvas component
I made a handy canvas component which i use to render any 3D stuff i want. It takes advantage of Chakra-ui but the styles can just as easily be used inline with a style tag or added from a CSS file.
Working with models is very fun, and fairly painless using the tools the the Poimandres team have put together. Generally speaking you are going to be working with GLTF which is a specification for loading 3D content. It accepts both JSON (.gltf) or binary (.glb) formats. Instead of storing a single texture or assets like .jgp or .png, gltf packages up all that is needed to show the 3D content. That could include everything from the mesh, geometry, materials and textures. For more information checkout the Three docs.
You can use a package called gltfjsx which will take a gltf file which has to be stored in your public folder and then read that and create a React component out of it for you. If your gltf model has animations then the package will handle that for you too, creating the animations logic right inside the component. We can take an example, one of the birds from the Three repository examples.
The code for this bird is auto generated for us. It looks like this:
A handy model component
I made a handy gtlf model component too. This component accepts a number of props such as the path to the models .gltf file, the position the model should take up on the canvas, its rotation which is added in the Vector3 array format of [x, y, z] and any additional props to be passed onto the models mesh.
It's then used like this: