Three.js is a JS graphics library that is used for rendering 3D graphics in browsers. Major graphics organizations use Three.js for creating and rendering 3D scenes for movies, anime, advertisements, and games.
Three.js uses the WebGL engine in the browser for rendering scenes. The API is based on OpenGL (GL stands for graphics library), a desktop graphics API. In this post, we’ll look at types of lights and WebGLRenderer in Three.js.
First, let’s learn how to use lights in Three.js so we know the types of lighting that can be used and the effect each of them presents.
Three.js offers several different types of light. All lights in Three.js are instances of THREE.Light
. They offer us illumination so that we can light up objects in a scene.
Not all material texture in objects in Three.js is affected by lighting. Only objects with MeshLambertMaterial
and MeshPhongMaterial
material texture can be affected by lighting.
Here are the type of lights available in Three.js:
Ambient light is used for the illumination of objects in a scene. It does not point or direct light toward a direction, so it cannot cast shadows.
THREE.AmbientLight(color)
The objects are illuminated by the color
in the AmbientLight
. Ambient light affects all lit objects in the scene equally, and is essentially a light that’s color is added to the color of an object’s material.
var cubeGeometry = new THREE.CubeGeometry(20, 20, 20); var basicMaterial = new THREE.MeshLambertMaterial({ color: 0x0095DD }); var cubeMesh = new THREE.Mesh(cubeGeometry, basicMaterial); var light = new THREE.AmbientLight(0x404040); scene.add(light); scene.add(cubeMesh)
For example, this illuminates the cube object with soft white light:
var light = new THREE.AmbientLight(0xf6e86d);
This code will illuminate the cube object with a green color.
As the name suggests, directional light comes from a specific point and is emitted directly to the target.
This light can cast shadows, and the rays are all parallel and behave as though it is infinitely far away, just like the sun.
THREE.DirectionalLight(color, intensity = 1)
For this type of light, all light is parallel and comes from a given direction, as if the source was very far away.
For directional lights, the direction of the light is the direction from light.position
to light.target.position
; both are vectors that you can change, and the target defaults to the world’s origin.
This is the kind of light we get from the sun down to earth. We know the light source is far away, and the rays are in parallel.
Another example is a torch or lamp in a close hall with a wide range positioned at a far corner of the room. This will direct the rays of light in the hall, illuminating objects in the hall and casting shadows.
The color
is the color of the light, and the intensity
is how intense/bright the light would be. The default value is 1, which indicates the highest intensity.
var light = new THREE.DirectionalLight(0x404040, 0.5); scene.add(light);
Hemisphere light comes directly from above the scene to the ground. The light color fades gradually as it descends from top to the ground, and it does not cast shadows.
THREE.HemisphereLight(skyColor, groundColor, intensity = 1)
Notice that it simulates refractive lighting from the sun, sort of like two opposing directional lights.
The skyColor
is the color from the starting point at the sky. The groundColor
is the color of the light at the ground. intensity
controls the brightness of the color.
var light = new THREE.HemisphereLight(0x404040, 0xFFFFFF, 0.5); scene.add(light);
The light starts from the sky with soft white color and fades to normal light at the ground. See as the top of the cube is illuminated with the soft white color and its sides are in shades of normal light and soft white light.
Here’s another example:
var light = new THREE.HemisphereLight(0xf6e86d, 0x404040, 0.5); scene.add(light);
The light color at the top starts with a greenish color of 0xf6e86d
, which is why the top of the cube has a greenish tint. It then fades to the color of 0x404040
.
Point light is emitted from a single location and shines in all directions. Objects illuminated by this are the ones that are in its line of rays.
THREE.PointLight(color, intensity = 1, distance = 0)
Just like a lightbulb in a room, the light emanates from a point (i.e., a lightbulb) and spreads to all directions, but only illuminated objects within radius. Point light can cast shadows.
The color
arc in the constructor is the color of the light to be emitted. The intensity
is the strength of the light, and its default value is 1. distance
is the distance the emitted light can travel or the maximum range of the light, the default value is 0, meaning there’s no limit.
The type of light from this forms a cone of light from a specific point to a specific direction. The cone light increases in size the further it gets from the source. Objects within the cone of light are illuminated, and it can cast shadows on the objects.
THREE.SpotLight(color, intensity, distance = 0, angle = Math.PI/2)
The color
is the color of the light. intensity
is the strength of the light. distance
is how far the light will travel from its source. angle
is the max angle of light dispersion from its direction.
Three.js now only uses WebGLRRenderer to render 3D objects in our browser, and it uses the WebGL API of the browser to render objects and scenes. This requires browsers that support WebGL to show a scene. In general, most modern desktop browsers have good support for WebGL, but some mobile devices do not yet support WebGL.
WebGL is fast because it uses the client graphics processing unit to the work. The CPU of the client isn’t doing anything and isn’t part of the render. WebGL is highly performant because the CPU is spared while a dedicated GPU built for graphics rendering does the work.
To use THREE.WebGLRenderer, we first create an instance of it:
var renderer = new THREE.WebGLRenderer({ antialias: true });
The antialias
option in the object param passed to the constructor that sets off a very powerful feature in Three.js. Antialiasing in Three.js smoothes out jagged edges in objects rendered in our scenes, making the objects in the scene look life-like.
Next, we can set the size of our rendering window by calling the setSize()
method:
renderer.setSize(window.innerWidth, window.innerHeight);
The first param is the width of the rendering window. We’ll set it to take the width of the client’s browser. The second param is the height of the rendering window, and we set it to take the height of the client’s browser.
Next, we call the render
method on the renderer in order to render our scene.
renderer.render(scene, camera);
A scene contains objects and lights. Here, the first param is the scene we want to render and the second param is the camera we will use to view our objects in the scene.
Finally, the renderer is appended to the page document.
document.body.appendChild(renderer.domElement);
The domElement
prop in the renderer holds the DOM element that we append to the document’s body. This makes our scene visible in the browser.
We covered all the types of lighting available in Three.js, starting from horizontal to point lighting, with examples to show how they work. We also learned about WebGLRenderer in Three.js, showing how performant and useful it is.
Three.js is incredibly powerful and fast, so next time you want to build any graphics for your browser, you should consider using Three.js.
There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.
LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.
LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Build confidently — start monitoring for free.
Hey there, want to help make our blog better?
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.