Creating a pool table game using React, Three JS and react-three-fiber

Part 1

Manan Joshi
Oct 28, 2019 · 5 min read

For a long time, I wanted to learn and get started with WebGL. Having done some work with OpenGL I thought WebGL would be a great addition to know and learn. This is when I came across three.js.

Three.js is an awesome 3D library for working with graphics on the web. It is written in JavaScript but does not have native support for React. Having worked with React a lot I wanted to use the expressiveness of React combined with the power of three js. This is when I found react-three-fiber. It is a lightweight React renderer for three.js and works well.

This is a three-part series of articles where we will see how we can use React, three.js, and react-three-fiber to create a game of pool table.

  • Part 1: Getting started with React, three.js, and react-three-fiber.
  • Part 2: Setting up the basic scene (Coming soon).
  • Part 3: Adding physics and finishing up(Coming soon).

First things first

  • Create a React project. The best way to do this is by using create-react-app
  • The next step is to install the three.js and react-three-fiber modules. Depending on the package manager of your choice go ahead and install them. npm i three react-three-fiber or yarn add three react-three-fiber

Now that our project is set up let’s do the fun part and jump into coding.

Organizing the project

This is a project structure that I like to follow and by no means, you’ve to do this. This is how I like to organize but feel free to move things around.

Inside the src directory let’s create different directories for components, views, utils, and assets. Your directory structure should look something like this

+-- src
| +-- index.js
| +-- App.js
| +-- assets/
| +-- components/
| +-- utils/
| +-- views/

Creating a basic scene

  • Go ahead and create a file called Scene.js inside the views directory.
  • Just copy and paste the code below in the Scene.js file.

This will create a cube mesh for us.

Let’s go and see what each line does.

All the jsx tags that you see are react-three-fiber wrappers around three.js objects

  • The mesh component is the Mesh object from the three js library. The same is true for boxBufferGeometry and meshNormalMaterial.
  • If you check out the docs for the components on the three js website you’ll see BoxBufferGeometry has a constructor with a bunch of parameters.
  • The way you can create a new instance in React with react-three-fiber is by using the args prop for that component and passing in the parameters as an array.
  • So in the above example, <boxBufferGeometry attach='geometry' args={[1, 1, 1]} /> will create a new BoxBufferGeometry (aka cube) with params 1, 1, and 1 for width, height, and depth respectively. The attach prop tells the renderer what kind of object the given component is. You can use all the properties for this given object and from its superclass as props to the component. You can find all the properties in the docs for three js.
  • Similarly, the meshNormalMaterial can be used to color the geometry among many other uses which we will see later.

Congratulations you just created a cube and added it to the scene. The next step is to render the scene inside of a canvas element. You all know how to do this, so bye-bye and happy coding.

I was just kidding. So now, let’s create a canvas.

Creating the Canvas

We are done at this point. Just go and run npm start and you'll be able to see your beautiful cube in the browser.

Your output should look something like this

Basic cube
  • Just one last thing to do here is the canvas doesn’t take the entire height of the screen.
  • So in your index.css just add the following lines

I hope you’re happy with the effort you just put in but as you can see the cube looks more like a square. Don’t panic, believe me, it is a cube. To see it as a 3D object let’s add mouse/track-pad controls so that we can perform pan, rotate and zoom(aka orbit controls).

Adding Orbit Controls

  • The first thing to understand here is, OrbitControls is not part of the main three modules, hence you cannot use it directly as we saw in the previous mesh and geometry code for the cube.
  • To deal with this react-three-fiber provides an extend function which can be used for modules outside of the main three js codebase. Remember to call the extend function in the beginning before the component function and after that, you'll be able to use the extended module like any other three js module.
  • So, now as we saw earlier while using mesh and geometry we can use orbit controls in the same way along with all its properties.
  • Let’s talk about the hooks used above as well useRef, useThree and useFrame.
  • useRef among other things is Reacts’ way of giving us access to the underlying dom node. You can read more about it here
  • useThree is a react-three-fiber hook that essentially gives us access to everything that is added to the scene. This is going to be super helpful to us later on.
  • useFrame also a react-three-fiber hook is called for every frame that is drawn. If you have used RequestAnimationFrame API provided by the browser, this hook is similar to that. It will be formulating the basics of our physics calculation later on in the example.
  • And the final step is adding the newly created controls to the canvas. To do this open the App.js file and replace the current code with the code below.

Start the app and nothing will have changed but now you’ll be able to use your mouse-wheel/track-pad to zoom in and out while holding on to the left click will allow you to rotate and inspect the cube from all sides as well as allow you to pan. You should be able to do something like this shown below.

Cube after adding orbit controls

Before we jump into modeling out our pool table there is just one last thing that we want to do. Let us just adjust our camera a little bit so that we can see how to change the default settings on the camera.

Editing the camera settings

  • You will be able to find all the properties and functions the camera object has here.

This concludes part 1 of the three-part series. I’ll be posting the upcoming parts in the following days.

Also, this is my first blog post ever. It will be great if you could leave some feedback in the comments so that I can understand and improve my content delivery. You can follow me on Twitter and Instagram.

Peace out and happy coding!!!

Originally published at on October 28, 2019.

JavaScript in Plain English

Learn the web's most important programming language.

Manan Joshi

Written by

Passionate web and mobile developer, graduate student, pragmatist, love to cook, and sometimes wondering are we alone in the universe?

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade