Effortlessly use Three.js in your projects using my open-source library
When you start a new Three.js project, you often get tired of copy-pasting all the boilerplate stuff to a single setup of scenes, cameras, and stuff. I get that completely because that’s my story as well. So I start developing my own three.js boilerplate code that feels like home.
I will share the one I am currently using and still perfecting. It might take a little longer to get you started at first, but if you take the time to understand the material and use it a couple more times, you’ll be able to start a new three.js project with ease!
- Have all the usual three.js setup code for you so that you can focus on your own scene and objects.
- Uses async/await to load textures/images such that the scene appears only after all resources have been loaded. You’ll never see suddenly texture-like things on your objects again!
- Uses Parcel with minimal configuration, so you don’t need to care about setting up bundler.
To run the repo locally, execute the following commands in sequence. After creation is finished in a few seconds a new browser tab will be opened for you:
In earlier versions of my three.js boilerplate, I used
webpack As a bundling tool. It is a versatile and popular bundler, but I find it to have slow build times and too complex for simple projects.
Recently I started using the parcel, which is really easy to use. There is almost no admission cost, follow tutorials to build web apps with Parcel; It only takes five minutes to get started!
package.json File and Parcel does all the dirty work for you:
"browserslist": "> 0.5%, last 2 versions, not dead"
It’s going to be a little long. If you are more practical person, just read the docs given in the code and give it a try! Everything I’ll explain is documented in the code anyway.
i won’t spend much time
index.html file because it’s just the standard setup that imports
index.js file. One additional thing I’ve added is the veil which appears only when all the time consuming resources (eg, images/textures) are loaded into the view.
index.js The file is where you put most, if not all, of your scene-building code. The essence of this boilerplate is in the convenience methods I wrote
core-utils.jswhich is used by
index.js The file consists of three main sections, which you should also see in the code for numbered comment sections:
- Initializing Core Three.js Components
- build your scene
- running the app
There’s also section 0, where you define tweakable parameters for your scene, which can also be tuned in the GUI control panel at the top-right. For example, if I want to change a particular color or material roughness/metallicity, I like to group the parameters there so I don’t have to scroll and find them throughout my code.
Here we use the following convenience methods (designed to work with default values if no parameters are passed to them)
core-utils.js To create basic three.js components:
createRenderer(rendererProps, configureRenderer)By default, it sets the pixel ratio and renderer size for you. You can pass additional configuration properties on the 1st param (eg
antialias: true), and pass a callback to configure the renderer on the second parameter.
createCamera(fov, near, far, camPos, camLookAt, aspect)By default, it uses
PerspectiveCameraAnd it sets the camera position and look-at-point for you. If you do not pass any of these parameters, you can also see the default camera value.
createComposer(renderer, scene, camera, extraPasses)By default, it creates
RenderPassfor you, so you just have to focus on which post-processing pass you want to add
We need to define a
app object with a
initScene way. The object structure here is quite tightly coupled with boilerplate code, but once you get used to it I find it fairly easy. and if your scene needs to be animated, define an additional
updateScene Method to host your animation code.
initScene(): This function is called after the native three.js environment is set up so that you can insert your scene-building code (for example, add
OrbitControls, Add Lighting, Spheres or Boxes, GUI Controls, FPS stats, etc.) here. Note that this function has
asyncprefix so that you can use
awaitTo load textures and time consuming material within it. The default boilerplate mechanics here will just unveil your scene and start animating all your stuff at once
initSceneis loaded synchronously. This is important because we don’t want the rendered objects to wait for a second or two before the texture suddenly appears, which looks messy and unprofessional.
updateScene(interval, elapsed): This is where you animate your scene (eg, update OrbitControl, update FPS stats, rotate/move your mesh). Note that you do not need to call
requestAnimationFramemethod that is handled as
core-utils.js, You also have two time-related parameters at your disposal:
interval: elapsed time between two frames
elapsed: the total time elapsed since the app was started
Finally, in section 3, you call
runApp To start the app to display the rendered view in the browser. It sets up the normal HTML container, on-window resize listener, and mouse move/touch listeners for you before moving
app.initScene() And later the animation.
If your scene is static and you don’t want the app to run idle frame redrawing 60 times per second, you can skip defining
app.updateScene and pass
enableAnimation the ultimate