Title: Three.js Backgrounds and Skyboxes Description: How to add a background in THREE.js TOC: Add a Background or Skybox Most of the articles here use a solid color for a background. Adding as static background can be as simple as setting some CSS. Taking an example from [the article on making THREE.js responsive](threejs-responsive.html) we only need to change 2 things. We need to add some CSS to our canvas to set its background to an image ```html ``` and we need to tell the `WebGLRenderer` to use `alpha` so places we are not drawing anything are transparent. ```js function main() { const canvas = document.querySelector('#c'); - const renderer = new THREE.WebGLRenderer({canvas}); + const renderer = new THREE.WebGLRenderer({ + canvas, + alpha: true, + }); ``` And we get a background. {{{example url="../threejs-background-css.html" }}} If we want the background to be able to be affected by [post processing effects](threejs-post-processing.html) then we need to draw the background using THREE.js. THREE.js makes this some what simple. We can just set the background of the scene to a texture. ```js const loader = new THREE.TextureLoader(); const bgTexture = loader.load('resources/images/daikanyama.jpg'); scene.background = bgTexture; ``` which gives us {{{example url="../threejs-background-scene-background.html" }}} 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 of the texture to show only a portion of image. ```js 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 from the CSS version at the top but now if we used a [post processing effect](threejs-post-processing.html) the background would be affected too. {{{example url="../threejs-background-scene-background-fixed-aspect.html" }}} Of course a static background is not usually what we want in a 3D scene. Instead we usually want some kind of *skybox*. A skybox is just that, box with the sky draw on it. We put the camera inside the box and it looks like there is a sky in the background. The most common way to implement a skybox is to make a cube, apply a texture to it, draw it from the inside. On each side of the cube put a texture (using texture coordinates) that looks like some image of the horizon. It's also often common to use a sky sphere or a sky dome with a texture drawn on it. You can probably figure that one out on your own. Just make a cube or sphere, [apply a texture](threejs-textures.html), mark it as `THREE.BackSide` so we render the inside instead of the outside, and either put it in your scene directly or like above, or, make 2 scenes, a special one to draw the skybox/sphere/dome and the normal one to draw everything else. You'd use your normal `PerspectiveCamera` to draw. No need for the `OrthographicCamera`. Another solution is to use a *Cubemap*. A Cubemap is a special kind of texture that has 6 sides, the sides of a cube. Instead of using standard texture coordinates it uses a direction from the center pointing outward to decide where to get a color. Here are the 6 images of a cubemap from the computer history museum in Mountain View, California.