Three.js – Backgrounds and Skyboxes (2024)

Most of the articles here use a solid color for a background.

Adding as static background can be as simple as setting some CSS. Takingan example from the article on making THREE.js responsivewe only need to change 2 things.

We need to add some CSS to our canvas to set its background to an image

<style>body { margin: 0;}#c { width: 100%; height: 100%; display: block;+ background: url(resources/images/daikanyama.jpg) no-repeat center center;+ background-size: cover;}</style>

and we need to tell the WebGLRenderer to use alpha so places we are notdrawing anything are transparent.

function main() { const canvas = document.querySelector('#c');- const renderer = new THREE.WebGLRenderer({antialias: true, canvas});+ const renderer = new THREE.WebGLRenderer({+ antialias: true,+ canvas,+ alpha: true,+ });

And we get a background.

click here to open in a separate window

If we want the background to be able to be affected by post processingeffects then we need to draw the background usingTHREE.js.

THREE.js makes this some what simple. We can just set the background of the scene toa texture.

const loader = new THREE.TextureLoader();const bgTexture = loader.load('resources/images/daikanyama.jpg');bgTexture.colorSpace = THREE.SRGBColorSpace;scene.background = bgTexture;

which gives us

click here to open in a separate window

This gets us a background image but its stretched to fit the screen.

We can solve this issue by setting the repeat and offset properties ofthe texture to show only a portion of image.

function render(time) { ...+ // Set the repeat and offset properties of the background texture+ // to keep the image's aspect correct.+ // Note the image may not have loaded yet.+ const canvasAspect = canvas.clientWidth / canvas.clientHeight;+ const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;+ const aspect = imageAspect / canvasAspect;++ bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;+ bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;++ bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;+ bgTexture.repeat.y = aspect > 1 ? 1 : aspect; ... renderer.render(scene, camera); requestAnimationFrame(render);}

and now THREE.js drawing the background. There is no visible difference fromthe CSS version at the top but now if we used a post processingeffect the background would be affected too.

click here to open in a separate window

Of course a static background is not usually what we want in a 3D scene. Insteadwe usually want some kind of skybox. A skybox is just that, box with the skydraw on it. We put the camera inside the box and it looks like there is a sky inthe background.

The most common way to implement a skybox is to make a cube, apply a texture toit, draw it from the inside. On each side of the cube put a texture (usingtexture coordinates) that looks like some image of the horizon. It's also oftencommon to use a sky sphere or a sky dome with a texture drawn on it. You canprobably figure that one out on your own. Just make a cube or sphere,apply a texture, mark it as THREE.BackSide so werender the inside instead of the outside, and either put it in your scene directlyor like above, or, make 2 scenes, a special one to draw the skybox/sphere/dome and thenormal one to draw everything else. You'd use your normal PerspectiveCamera todraw. No need for the OrthographicCamera.

Another solution is to use a Cubemap. A Cubemap is a special kind of texturethat has 6 sides, the sides of a cube. Instead of using standard texturecoordinates it uses a direction from the center pointing outward to decide whereto get a color.

Here are the 6 images of a cubemap from the computer history museum in MountainView, California.

Three.js – Backgrounds and Skyboxes (1) Three.js – Backgrounds and Skyboxes (2) Three.js – Backgrounds and Skyboxes (3)

Three.js – Backgrounds and Skyboxes (4) Three.js – Backgrounds and Skyboxes (5) Three.js – Backgrounds and Skyboxes (6)

To use them we use CubeTextureLoader to load them and then use that as a thescene's background.

{ const loader = new THREE.CubeTextureLoader(); const texture = loader.load([ 'resources/images/cubemaps/computer-history-museum/pos-x.jpg', 'resources/images/cubemaps/computer-history-museum/neg-x.jpg', 'resources/images/cubemaps/computer-history-museum/pos-y.jpg', 'resources/images/cubemaps/computer-history-museum/neg-y.jpg', 'resources/images/cubemaps/computer-history-museum/pos-z.jpg', 'resources/images/cubemaps/computer-history-museum/neg-z.jpg', ]); scene.background = texture;}

At render time we don't need to adjust the texture like we did above

function render(time) { ...- // Set the repeat and offset properties of the background texture- // to keep the image's aspect correct.- // Note the image may not have loaded yet.- const canvasAspect = canvas.clientWidth / canvas.clientHeight;- const imageAspect = bgTexture.image ? bgTexture.image.width / bgTexture.image.height : 1;- const aspect = imageAspect / canvasAspect;-- bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;- bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;-- bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;- bgTexture.repeat.y = aspect > 1 ? 1 : aspect; ... renderer.render(scene, camera); requestAnimationFrame(render);}

Let's add some controls in so we can rotate the camera.

import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
const fov = 75;const aspect = 2; // the canvas defaultconst near = 0.1;-const far = 5;+const far = 100;const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);-camera.position.z = 2;+camera.position.z = 3;+const controls = new OrbitControls(camera, canvas);+controls.target.set(0, 0, 0);+controls.update();

and try it out. Drag on the example to rotate the camera and see the cubemapsurrounds us.

click here to open in a separate window

Another option is to use an Equirectangular map. This is the kind of picture a360 camera takes.

Here's one I found fromthis site.

Three.js – Backgrounds and Skyboxes (7)

{- const loader = new THREE.CubeTextureLoader();- const texture = loader.load([- 'resources/images/cubemaps/computer-history-museum/pos-x.jpg',- 'resources/images/cubemaps/computer-history-museum/neg-x.jpg',- 'resources/images/cubemaps/computer-history-museum/pos-y.jpg',- 'resources/images/cubemaps/computer-history-museum/neg-y.jpg',- 'resources/images/cubemaps/computer-history-museum/pos-z.jpg',- 'resources/images/cubemaps/computer-history-museum/neg-z.jpg',- ]);- scene.background = texture;+ const loader = new THREE.TextureLoader();+ const texture = loader.load(+ 'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',+ () => {+ texture.mapping = THREE.EquirectangularReflectionMapping;+ texture.colorSpace = THREE.SRGBColorSpace;+ scene.background = texture;+ });}

And that's all there is to it.

click here to open in a separate window

Rather than do it at load time you can also convert an equirectangular imageto a cubemap beforehand. Here's a site that will do it for you.

Three.js – Backgrounds and Skyboxes (2024)
Top Articles
Latest Posts
Article information

Author: Dong Thiel

Last Updated:

Views: 5792

Rating: 4.9 / 5 (59 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Dong Thiel

Birthday: 2001-07-14

Address: 2865 Kasha Unions, West Corrinne, AK 05708-1071

Phone: +3512198379449

Job: Design Planner

Hobby: Graffiti, Foreign language learning, Gambling, Metalworking, Rowing, Sculling, Sewing

Introduction: My name is Dong Thiel, I am a brainy, happy, tasty, lively, splendid, talented, cooperative person who loves writing and wants to share my knowledge and understanding with you.