The gaming industry is one of the most successful industries. In 2020 alone, the gaming industry was forecast to generate $159 billion.
Among the millions of games produced each year are some extraordinary web-based games. Browsers are becoming more sophisticated and powerful every day, making it more and more possible to create stunningly realistic 3D and 2D games for the web browser.
In this tutorial, we’ll demonstrate how to create geometries and materials for styling geometries in Three.js.
Three.js is one of the powerful game libraries for creating web-based games. It is a cross-browser JavaScript library and API designed to help you build and display 3D animations in the browser using WebGL — anything from simple 3D patterns to photorealistic, real-time scenes.
Three.js enables you to apply textures and materials to your objects. It also provides various light sources to illuminate your scene, advanced postprocessing effects, custom shaders, etc. You can load objects from 3D modeling software to use in your game.
For a deeper dive to help you get started, check out this beginner’s guide to Three.js for game developers.
Three.js is very easy to start with. First, get the minified Three.js file from https://mrdoob.github.com/three.js/build/three.min.js
. Then, add it to the src
attribute in the script
tag:
<script src="https://mrdoob.github.com/three.js/build/three.min.js"></script>
With this, Three.js is initialized and ready to go.
Geometries are used to create and define shapes in Three.js. A geometry is an instance of the Three.Geometry
class.
A shape is defined by faces and vertices. A vertex defines the position of points in space. A face represents the surface of a shape.
For example, a cube has six vertices (edges) and six faces. To draw a cube on a grid, we have to first map out the position of the six vertices and then connect them with a line. This creates the surfaces of the cube and defines the shape/geometry. You can create all kinds of other shapes — polygons, cylinders, pyramids, etc. — with this same method.
A face in Three.js is an instance of the Three.Face3
class and a vertex/surface is an instance of the Three.Vector3
class. We can create geometries with these classes. Three.js has some built-in primitive shapes, including a cube, sphere, polyhedra, torus, and torus knot.
CubeGeometry
To create a Cube in Three.js, use Three.CubeGeometry
.
>var cubeGeometry = new THREE.CubeGeometry(20, 20, 20);
The first param is the width of the cube. The second and third params are the height and depth of the cube, respectively. Here, we gave them the same value: 20
.
The result should look like this:
CubeGeometry
has three other arguments:
>var cubeGeometry = new THREE.CubeGeometry(20, 20, 20, 2, 2, 2);
The segments of the cube are width, height, and depth. These segments divide the surfaces of the cube into smaller sides.
The above sets the width, height, and depth segments to 2
, so they will be split into two sides.
A value of 3
will split the surface into three smaller sides.
>var cubeGeometry = new THREE.CubeGeometry(20, 20, 20, 3, 3, 3);
If you don’t specify the arguments, they have a default value of 1
, so the surface has one side.
SphereGeometry
In Three.js, Three.SphereGeometry
creates a sphere.
>var sphereGeometry = new Three.SphereGeometry(20)
The above will create a sphere with a radius of 20
.
SphereGeometry
has two more args:
>var sphereGeometry = new Three.SphereGeometry(20, 8, 6)
This is the number of horizontal and vertical segments into which the sphere should be divided. The 8
param represents the horizontal segment division. The sphere will be divided into eight segments and its vertical axis into five segments.
CylinderGeometry
To create a cylinder in Three.js, use the Three.CylinderGeometry
.
>var cylinderGeometry = new THREE.CylinderGeometry(15, 15, 30)
The first arg is the radius of the cylinder’s top; the second is the radius of the bottom. The third argument represents the height of the cylinder.
We can set the number of edges connecting the top and bottom faces down the curved surface. This is called the radiusSegments
, and it goes in as the fourth arg. The default value is 8
.
>var cylinderGeometry = new THREE.CylinderGeometry(15, 15, 30, 9)
This will divide the top and down faces into nine segments:
We can also set the number of rings of faces around the curved surface. This is called heightSegments
. It goes as the fifth argument with a default value of 1
.
>var cylinderGeometry = new THREE.CylinderGeometry(15, 15, 30, 9, 2)
This will divide each face of the curved surface into two segments:
You can determine whether the ends of the cylinder are open or closed. It’s a boolean: true
makes it open while false
makes it closed. This goes in as the sixth arg. The default value is false
.
>var cylinderGeometry = new THREE.CylinderGeometry(15, 15, 30, 9, 2, true)
This will render a cylinder with open ends.
TorusGeometry
TorusGeometry
generates a tubelike shape. The Three.TorusGeometry
class is what we use to generate the shape.
>var torusGeo = new THREE.TorusGeometry(10, 3, 16, 100) var meshBasicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD, wireframe: true, wireframeLinewidth: 2 }); var torusMesh = new THREE.Mesh(torusGeo, meshBasicMaterial); scene.add(torusMesh)
The above will generate a torus shape:
new THREE.TorusGeometry(10, 3, 16, 100)
The first argument sets the radius of the torus from the center of the torus to the center of the tube. Its default value is 1
. The second is the radius of the tube, the default value of which is 0.4
.
The third arg represents the radial segments, which are set to 8
by default. The fourth sets the tubular segments to 6
by default.
We have seen basic 3D geometrics. We can also create and render 2D geometry in Threejs.
In addition to 3D geometrics, you can create engaging 2D shapes in Three.js, such as planes, circles, and rings.
PlaneGeometry
To create a plane in Three.js, we’ll use Three.PlaneGeomerty
.
>var planeGeo = new THREE.PlaneGeometry(20, 20)
The first parameter is the width of the plane. The second represents the height.
The above will create a 2D plane with 20 units wide and high.
PlaneGeometry
‘s third and fourth arguments specify the number of segments the width and height of the plane, respectively, can have.
>var planeGeo = new THREE.PlaneGeometry(20, 20, 3, 3)
This will divide the plane into three rows and three columns.
CircleGeometry
To create a circle in Three.js, you can use the THREE.CircleGeometry
class.
>var circleGeo = new THREE.CircleGeometry(20)
The above creates a circle shape with a radius of 20 units.
As you can see, the circle is subdivided into eight sides. A second arg to the THREE.CircleGeometry
constructor allows us to set the number of sides for the circle to be divided into. The default value is 8
.
>var circleGeo = new THREE.CircleGeometry(20, 10)
The above creates a circle divided into 10 parts.
RingGeometry
RingGeometry
creates a 2D ring shape with a hole in the middle. The THREE.RingGeometry
constructor creates the ring shape.
>var ringGeo = new THREE.RingGeometry(20, 20)
The command above creates a ring with an inner and outer radius of 20 units each.
We can set radial segments and ring segments in the ring’s shape.
>var ringGeo = new THREE.RingGeometry(20, 20, 9, 10)
The third param is the number of radial segments the ring will be divided into. The fourth sets the number of ring segments into which the ring will be divided.
Just as we created 3D and 2D geometrics, we can also render text in Three.js. Font .js
files from Three.js must be included in the page before Three.js can render text.
For example, the code below adds the Helvetica font to the page:
<script src="https://raw.github.com/mrdoob/three.js/master/examples/fonts/helvetiker_bold.typeface.js"></script> <script src="https://raw.github.com/mrdoob/three.js/master/examples/fonts/helvetiker_regular.typeface.js"></script>
To create and render text in Three.js, we’ll use THREE.TextGeometry
.
>var myNameGeometry = new THREE.TextGeometry("Nnamdi Chidume", { size: 30, height: 20 font: "Tahoma", });
The first param is the text we want to render. Here, I set my name: “Nnamdi Chidume.”
The second param is an object with options we set on our text. Here, we set the size and height of the text to be 30
and 20
, respectively. We also set the rendering font to be Tahoma.
There are several additional options we can set, including:
weight
, which sets the font weightstyle
, which determines how the text will be styled — normal, bold, or italicbevelEnabled
, which determines whether the text has blunt or sharp edges; its value can be true
or false
Materials manage the texture and color of objects in Three.js. A material covers an object, the colors, or textures on a surface.
To use an analogy, materials are like the clothes we wear. Whether you wake up and choose to put on a polo shirt, jeans, a suit, skirt, blouse, traditional garb, etc., the point is to add some pizazz to your normal appearance. Materials are like snazzy clothes for your objects in Three.js.
Three.js provides a plethora of materials, including:
The above are all child classes of the MeshMaterial
.
MeshBasicMaterial
MeshBasicMaterial
is used to display a solid color or a wireframe.
>var basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD });
The above displays a solid color of blue.
>var meshBasicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD, wireframe: true, wireframeLinewidth: 2 });
This displays a wireframe with a line width of 2
.
Sometimes it’s hard to distinguish between two adjacent, unlit surfaces of the same color. For example, here’s a sphere with a solid display:
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD }); var sphMesh = new THREE.Mesh(sphGeo, meshBasicMaterial);
It would be difficult to see the solid appearance of the sphere; although it appears as 2D, it should be 3D.
Basic materials are not affected by lighting.
MeshPhongMaterial
The Phong material looks glossier and shinier than the basic material. PhongMaterial
is affected by light in the scene. Without lights, the Phong material laced objects would appear black.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var phongMaterial = new THREE.MeshPhongMaterial({ color: 0x0095DD });
Nothing will be shown, everywhere will be black. This is because there is no light in the scene.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var phongMaterial = new THREE.MeshPhongMaterial({ color: 0x0095DD }); var sphMesh = new THREE.Mesh(sphGeo, phongMaterial); var light = new THREE.PointLight(0xFFFFFF); light.position.set(-10, 15, 50); scene.add(light);
Here, we added light to the scene and pointed it toward the sphere object. The sphere with Phong material will be visible.
MeshLambertMaterial
Lambert material is similar to Phong material, but it’s not as glossy. Objects with Lambert material appear black if not under lighting.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var lambertMaterial = new THREE.MeshLambertMaterial({ color: 0x0095DD }); var sphMesh = new THREE.Mesh(sphGeo, lambertMaterial); var light = new THREE.PointLight(0xFFFFFF); light.position.set(-10, 15, 50); scene.add(light);
The sphere with Lambert material will appear but less shiny than the Phong material we saw in the last section.
MeshNormalMaterial
This material is great for distinguishing surfaces in objects or objects’ shapes — especially for objects with solid-colored, unlit surfaces that are difficult to tell apart.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095DD }); var sphMesh = new THREE.Mesh(sphGeo, meshBasicMaterial);
It will be difficult to see the shape of the sphere surface. If we change the material to normal material, the surface will be distinguishable.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var basicMaterial = new THREE.MeshNormalMaterial({ color: 0x0095DD }); var sphMesh = new THREE.Mesh(sphGeo, meshBasicMaterial);
MeshNormalMaterial
uses the magnitude of the x/y/z values of the faces’ normal vectors to calculate and set the red/green/blue values of the colors displayed.
The variations of coloring done by this Normal material enables us to see the shape of an unlit, same-colored object.
MeshDepthMaterial
MeshDepthMaterial
renders the object in shades of grey. Its brightness is dependent on its distance from the camera.
>var sphGeo = new THREE.SphereGeometry(20, 8, 6) var depthMaterial = new THREE.MeshDepthMaterial(); var sphMesh = new THREE.Mesh(sphGeo, depthMaterial);
We covered a lot in this post, including materials and geometries, how to create 3D objects such as spheres and cylinders, etc, how to create 2D objects such as rings and planes, and how to create text. We also learned how to build materials that change the texture and color of shapes.
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.