Parcourir la source

Manual: Honor latest changes. (#26353)

Michael Herzog il y a 2 ans
Parent
commit
9acdace9be
68 fichiers modifiés avec 6109 ajouts et 6121 suppressions
  1. 4 8
      manual/en/backgrounds.html
  2. 1 2
      manual/en/custom-buffergeometry.html
  3. 1 1
      manual/en/fundamentals.html
  4. 78 53
      manual/examples/3dlut-base-cube-maker.html
  5. 158 125
      manual/examples/align-html-elements-to-3d-globe-too-many-labels.html
  6. 221 184
      manual/examples/align-html-elements-to-3d-globe.html
  7. 130 108
      manual/examples/align-html-to-3d-w-hiding.html
  8. 133 111
      manual/examples/align-html-to-3d-w-sorting.html
  9. 104 86
      manual/examples/align-html-to-3d.html
  10. 85 67
      manual/examples/background-css.html
  11. 100 80
      manual/examples/background-cubemap.html
  12. 100 78
      manual/examples/background-equirectangularmap.html
  13. 97 78
      manual/examples/background-scene-background-fixed-aspect.html
  14. 87 68
      manual/examples/background-scene-background.html
  15. 109 89
      manual/examples/background-separate-scene-bad-aspect.html
  16. 119 99
      manual/examples/background-separate-scene.html
  17. 144 117
      manual/examples/background-v01.html
  18. 181 149
      manual/examples/background.html
  19. 158 139
      manual/examples/billboard-labels-w-sprites-adjust-height.html
  20. 159 140
      manual/examples/billboard-labels-w-sprites.html
  21. 118 95
      manual/examples/billboard-trees-no-billboards.html
  22. 179 150
      manual/examples/billboard-trees-static-billboards.html
  23. 151 116
      manual/examples/cameras-logarithmic-depth-buffer.html
  24. 208 170
      manual/examples/cameras-orthographic-2-scenes.html
  25. 96 80
      manual/examples/cameras-orthographic-canvas-top-left-origin.html
  26. 208 170
      manual/examples/cameras-perspective-2-scenes.html
  27. 153 117
      manual/examples/cameras-perspective.html
  28. 147 112
      manual/examples/cameras-z-fighting.html
  29. 43 31
      manual/examples/canvas-random-dots.html
  30. 151 112
      manual/examples/canvas-textured-cube-qix.html
  31. 98 77
      manual/examples/canvas-textured-cube.html
  32. 181 158
      manual/examples/canvas-textured-labels-one-canvas.html
  33. 162 143
      manual/examples/canvas-textured-labels-scale-to-fit.html
  34. 154 135
      manual/examples/canvas-textured-labels.html
  35. 240 167
      manual/examples/cleanup-loaded-files.html
  36. 146 98
      manual/examples/cleanup-simple.html
  37. 150 129
      manual/examples/custom-buffergeometry-cube-indexed.html
  38. 157 136
      manual/examples/custom-buffergeometry-cube-typedarrays.html
  39. 159 138
      manual/examples/custom-buffergeometry-cube.html
  40. 176 145
      manual/examples/custom-buffergeometry-dynamic.html
  41. 0 163
      manual/examples/custom-geometry-cube-face-colors.html
  42. 0 158
      manual/examples/custom-geometry-cube-face-normals.html
  43. 0 182
      manual/examples/custom-geometry-cube-texcoords.html
  44. 0 166
      manual/examples/custom-geometry-cube-vertex-colors.html
  45. 0 158
      manual/examples/custom-geometry-cube-vertex-normals.html
  46. 0 156
      manual/examples/custom-geometry-cube.html
  47. 0 195
      manual/examples/custom-geometry-heightmap.html
  48. 119 86
      manual/examples/debug-js-clearing-logger.html
  49. 63 51
      manual/examples/debug-js-html-elements.html
  50. 145 102
      manual/examples/debug-js-params.html
  51. 134 117
      manual/examples/debugging-mcve.html
  52. 145 109
      manual/examples/fog-gui.html
  53. 90 70
      manual/examples/fog.html
  54. 58 47
      manual/examples/fundamentals-3-cubes.html
  55. 29 24
      manual/examples/fundamentals-with-animation.html
  56. 41 34
      manual/examples/fundamentals-with-light.html
  57. 20 17
      manual/examples/fundamentals.html
  58. 1 2
      manual/fr/custom-buffergeometry.html
  59. 1 1
      manual/fr/fundamentals.html
  60. 4 3
      manual/ja/backgrounds.html
  61. 1 1
      manual/ja/fundamentals.html
  62. 4 3
      manual/ko/backgrounds.html
  63. 1 1
      manual/ko/fundamentals.html
  64. 0 7
      manual/ru/custom-buffergeometry.html
  65. 1 1
      manual/ru/fundamentals.html
  66. 4 3
      manual/zh/backgrounds.html
  67. 1 2
      manual/zh/custom-buffergeometry.html
  68. 1 1
      manual/zh/fundamentals.html

+ 4 - 8
manual/en/backgrounds.html

@@ -73,6 +73,7 @@ THREE.js.</p>
 a texture.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const bgTexture = loader.load('resources/images/daikanyama.jpg');
+bgTexture.colorSpace = THREE.SRGBColorSpace;
 scene.background = bgTexture;
 </pre>
 <p>which gives us</p>
@@ -219,11 +220,6 @@ surrounds us.</p>
 <a href="https://hdrihaven.com">this site</a>.</p>
 <div class="threejs_center"><img src="../examples/resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg" style="width: 600px"></div>
 
-<p>It's not much different. First we load the equirectangular image as a texture
-and then, in the callback after it has loaded, we can call <a href="/docs/#api/en/renderers/WebGLCubeRenderTarget.fromEquirectangularTexture"><code class="notranslate" translate="no">WebGLCubeRenderTarget.fromEquirectangularTexture</code></a>
-which will generate a cubemap from the equirectangular texture for us.
-We pass in the size we want the cubemap to be to <a href="/docs/#api/en/renderers/WebGLCubeRenderTarget"><code class="notranslate" translate="no">WebGLCubeRenderTarget</code></a>.
-Passing in the height of the equirectangular image seems like a good bet.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
 -  const loader = new THREE.CubeTextureLoader();
 -  const texture = loader.load([
@@ -239,9 +235,9 @@ Passing in the height of the equirectangular image seems like a good bet.</p>
 +  const texture = loader.load(
 +    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
 +    () =&gt; {
-+      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-+      rt.fromEquirectangularTexture(renderer, texture);
-+      scene.background = rt.texture;
++      texture.mapping = THREE.EquirectangularReflectionMapping;
++      texture.colorSpace = THREE.SRGBColorSpace;
++      scene.background = texture;
 +    });
 }
 </pre>

+ 1 - 2
manual/en/custom-buffergeometry.html

@@ -436,8 +436,7 @@ positionAttribute.needsUpdate = true;
 make your own geometry and how to dynamically update the contents of a
 <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>.</p>
 <!-- needed in English only to prevent warning from outdated translations -->
-<p><a href="resources/threejs-geometry.svg"></a>
-<a href="custom-geometry.html"></a></p>
+<p><a href="resources/threejs-geometry.svg"></a></p>
 <p><canvas id="c"></canvas></p>
 <script type="module" src="../resources/threejs-custom-buffergeometry.js"></script>
 

+ 1 - 1
manual/en/fundamentals.html

@@ -273,7 +273,7 @@ add some lighting so let's add a light. There are many kinds of lights in
 three.js which we'll go over in <a href="lights.html">a future article</a>. For now let's create a directional light.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);

+ 78 - 53
manual/examples/3dlut-base-cube-maker.html

@@ -26,63 +26,88 @@ canvas {
 </body>
 <script type="module">
 
-const ctx = document.querySelector('canvas').getContext('2d');
-
-function drawColorCubeImage(ctx, size) {
-  const canvas = ctx.canvas;
-  canvas.width = size * size;
-  canvas.height = size;
-
-  for (let zz = 0; zz < size; ++zz) {
-    for (let yy = 0; yy < size; ++yy) {
-      for (let xx = 0; xx < size; ++xx) {
-        const r = Math.floor(xx / (size - 1) * 255);
-        const g = Math.floor(yy / (size - 1) * 255);
-        const b = Math.floor(zz / (size - 1) * 255);
-        ctx.fillStyle = `rgb(${r},${g},${b})`;
-        ctx.fillRect(zz * size + xx, yy, 1, 1);
-      }
-    }
-  }
-  document.querySelector('#width').textContent = canvas.width;
-  document.querySelector('#height').textContent = canvas.height;
+const ctx = document.querySelector( 'canvas' ).getContext( '2d' );
+
+function drawColorCubeImage( ctx, size ) {
+
+	const canvas = ctx.canvas;
+	canvas.width = size * size;
+	canvas.height = size;
+
+	for ( let zz = 0; zz < size; ++ zz ) {
+
+		for ( let yy = 0; yy < size; ++ yy ) {
+
+			for ( let xx = 0; xx < size; ++ xx ) {
+
+				const r = Math.floor( xx / ( size - 1 ) * 255 );
+				const g = Math.floor( yy / ( size - 1 ) * 255 );
+				const b = Math.floor( zz / ( size - 1 ) * 255 );
+				ctx.fillStyle = `rgb(${r},${g},${b})`;
+				ctx.fillRect( zz * size + xx, yy, 1, 1 );
+
+			}
+
+		}
+
+	}
+
+	document.querySelector( '#width' ).textContent = canvas.width;
+	document.querySelector( '#height' ).textContent = canvas.height;
+
 }
 
-drawColorCubeImage(ctx, 8);
-
-function handleSizeChange(event) {
-  const elem = event.target;
-  elem.style.background = '';
-  try {
-    const size = parseInt(elem.value);
-    if (size >= 2 && size <= 64) {
-      drawColorCubeImage(ctx, size);
-    }
-  } catch (e) {
-    elem.style.background = 'red';
-  }
+drawColorCubeImage( ctx, 8 );
+
+function handleSizeChange( event ) {
+
+	const elem = event.target;
+	elem.style.background = '';
+	try {
+
+		const size = parseInt( elem.value );
+		if ( size >= 2 && size <= 64 ) {
+
+			drawColorCubeImage( ctx, size );
+
+		}
+
+	} catch ( e ) {
+
+		elem.style.background = 'red';
+
+	}
+
 }
 
-const sizeElem = document.querySelector('#size');
-sizeElem.addEventListener('change', handleSizeChange, true);
-
-const saveData = (function() {
-  const a = document.createElement('a');
-  document.body.appendChild(a);
-  a.style.display = 'none';
-  return function saveData(blob, fileName) {
-    const url = window.URL.createObjectURL(blob);
-    a.href = url;
-    a.download = fileName;
-    a.click();
-  };
-}());
-
-document.querySelector('button').addEventListener('click', () => {
-  ctx.canvas.toBlob((blob) => {
-    saveData(blob, `identity-lut-s${ctx.canvas.height}.png`);
-  });
-});
+const sizeElem = document.querySelector( '#size' );
+sizeElem.addEventListener( 'change', handleSizeChange, true );
+
+const saveData = ( function () {
+
+	const a = document.createElement( 'a' );
+	document.body.appendChild( a );
+	a.style.display = 'none';
+	return function saveData( blob, fileName ) {
+
+		const url = window.URL.createObjectURL( blob );
+		a.href = url;
+		a.download = fileName;
+		a.click();
+
+	};
+
+}() );
+
+document.querySelector( 'button' ).addEventListener( 'click', () => {
+
+	ctx.canvas.toBlob( ( blob ) => {
+
+		saveData( blob, `identity-lut-s${ctx.canvas.height}.png` );
+
+	} );
+
+} );
 
 </script>
 </html>

+ 158 - 125
manual/examples/align-html-elements-to-3d-globe-too-many-labels.html

@@ -73,151 +73,184 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 60;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 10;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2.5;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.enableDamping = true;
-  controls.enablePan = false;
-  controls.minDistance = 1.2;
-  controls.maxDistance = 4;
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('#236');
-
-  {
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-    const geometry = new THREE.SphereGeometry(1, 64, 32);
-    const material = new THREE.MeshBasicMaterial({map: texture});
-    scene.add(new THREE.Mesh(geometry, material));
-  }
 
-  async function loadJSON(url) {
-    const req = await fetch(url);
-    return req.json();
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  let countryInfos;
-  async function loadCountryData() {
-    countryInfos = await loadJSON('resources/data/world/country-info.json');  /* threejs.org: url */
-
-    const lonFudge = Math.PI * 1.5;
-    const latFudge = Math.PI;
-    // these helpers will make it easy to position the boxes
-    // We can rotate the lon helper on its Y axis to the longitude
-    const lonHelper = new THREE.Object3D();
-    // We rotate the latHelper on its X axis to the latitude
-    const latHelper = new THREE.Object3D();
-    lonHelper.add(latHelper);
-    // The position helper moves the object to the edge of the sphere
-    const positionHelper = new THREE.Object3D();
-    positionHelper.position.z = 1;
-    latHelper.add(positionHelper);
-
-    const labelParentElem = document.querySelector('#labels');
-    for (const countryInfo of countryInfos) {
-      const {lat, lon, name} = countryInfo;
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-      // get the position of the lat/lon
-      positionHelper.updateWorldMatrix(true, false);
-      const position = new THREE.Vector3();
-      positionHelper.getWorldPosition(position);
-      countryInfo.position = position;
-
-      // add an element for each country
-      const elem = document.createElement('div');
-      elem.textContent = name;
-      labelParentElem.appendChild(elem);
-      countryInfo.elem = elem;
-    }
-    requestRenderIfNotRequested();
-  }
-  loadCountryData();
+	const fov = 60;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 10;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2.5;
 
-  const tempV = new THREE.Vector3();
+	const controls = new OrbitControls( camera, canvas );
+	controls.enableDamping = true;
+	controls.enablePan = false;
+	controls.minDistance = 1.2;
+	controls.maxDistance = 4;
+	controls.update();
 
-  function updateLabels() {
-    // exit if we have not yet loaded the JSON file
-    if (!countryInfos) {
-      return;
-    }
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( '#236' );
 
-    for (const countryInfo of countryInfos) {
-      const {position, elem} = countryInfo;
+	{
 
-      // get the normalized screen coordinate of that position
-      // x and y will be in the -1 to +1 range with x = -1 being
-      // on the left and y = -1 being on the bottom
-      tempV.copy(position);
-      tempV.project(camera);
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/data/world/country-outlines-4k.png', render );
+		const geometry = new THREE.SphereGeometry( 1, 64, 32 );
+		const material = new THREE.MeshBasicMaterial( { map: texture } );
+		scene.add( new THREE.Mesh( geometry, material ) );
 
-      // convert the normalized position to CSS coordinates
-      const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-      const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
+	}
 
-      // move the elem to that position
-      elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+	async function loadJSON( url ) {
 
-      // set the zIndex for sorting
-      elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-    }
-  }
+		const req = await fetch( url );
+		return req.json();
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  let renderRequested = false;
+	let countryInfos;
+	async function loadCountryData() {
 
-  function render() {
-    renderRequested = undefined;
+		countryInfos = await loadJSON( 'resources/data/world/country-info.json' ); /* threejs.org: url */
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const lonFudge = Math.PI * 1.5;
+		const latFudge = Math.PI;
+		// these helpers will make it easy to position the boxes
+		// We can rotate the lon helper on its Y axis to the longitude
+		const lonHelper = new THREE.Object3D();
+		// We rotate the latHelper on its X axis to the latitude
+		const latHelper = new THREE.Object3D();
+		lonHelper.add( latHelper );
+		// The position helper moves the object to the edge of the sphere
+		const positionHelper = new THREE.Object3D();
+		positionHelper.position.z = 1;
+		latHelper.add( positionHelper );
 
-    controls.update();
+		const labelParentElem = document.querySelector( '#labels' );
+		for ( const countryInfo of countryInfos ) {
 
-    updateLabels();
+			const { lat, lon, name } = countryInfo;
 
-    renderer.render(scene, camera);
-  }
-  render();
+			// adjust the helpers to point to the latitude and longitude
+			lonHelper.rotation.y = THREE.MathUtils.degToRad( lon ) + lonFudge;
+			latHelper.rotation.x = THREE.MathUtils.degToRad( lat ) + latFudge;
 
-  function requestRenderIfNotRequested() {
-    if (!renderRequested) {
-      renderRequested = true;
-      requestAnimationFrame(render);
-    }
-  }
+			// get the position of the lat/lon
+			positionHelper.updateWorldMatrix( true, false );
+			const position = new THREE.Vector3();
+			positionHelper.getWorldPosition( position );
+			countryInfo.position = position;
+
+			// add an element for each country
+			const elem = document.createElement( 'div' );
+			elem.textContent = name;
+			labelParentElem.appendChild( elem );
+			countryInfo.elem = elem;
+
+		}
+
+		requestRenderIfNotRequested();
+
+	}
+
+	loadCountryData();
+
+	const tempV = new THREE.Vector3();
+
+	function updateLabels() {
+
+		// exit if we have not yet loaded the JSON file
+		if ( ! countryInfos ) {
+
+			return;
+
+		}
+
+		for ( const countryInfo of countryInfos ) {
+
+			const { position, elem } = countryInfo;
+
+			// get the normalized screen coordinate of that position
+			// x and y will be in the -1 to +1 range with x = -1 being
+			// on the left and y = -1 being on the bottom
+			tempV.copy( position );
+			tempV.project( camera );
+
+			// convert the normalized position to CSS coordinates
+			const x = ( tempV.x * .5 + .5 ) * canvas.clientWidth;
+			const y = ( tempV.y * - .5 + .5 ) * canvas.clientHeight;
+
+			// move the elem to that position
+			elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+
+			// set the zIndex for sorting
+			elem.style.zIndex = ( - tempV.z * .5 + .5 ) * 100000 | 0;
+
+		}
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	let renderRequested = false;
+
+	function render() {
+
+		renderRequested = undefined;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		controls.update();
+
+		updateLabels();
+
+		renderer.render( scene, camera );
+
+	}
+
+	render();
+
+	function requestRenderIfNotRequested() {
+
+		if ( ! renderRequested ) {
+
+			renderRequested = true;
+			requestAnimationFrame( render );
+
+		}
+
+	}
+
+	controls.addEventListener( 'change', requestRenderIfNotRequested );
+	window.addEventListener( 'resize', requestRenderIfNotRequested );
 
-  controls.addEventListener('change', requestRenderIfNotRequested);
-  window.addEventListener('resize', requestRenderIfNotRequested);
 }
 
 main();

+ 221 - 184
manual/examples/align-html-elements-to-3d-globe.html

@@ -73,204 +73,241 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 60;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 10;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2.5;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.enableDamping = true;
-  controls.enablePan = false;
-  controls.minDistance = 1.2;
-  controls.maxDistance = 4;
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('#246');
-
-  {
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/data/world/country-outlines-4k.png', render);
-    const geometry = new THREE.SphereGeometry(1, 64, 32);
-    const material = new THREE.MeshBasicMaterial({map: texture});
-    scene.add(new THREE.Mesh(geometry, material));
-  }
 
-  async function loadJSON(url) {
-    const req = await fetch(url);
-    return req.json();
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  let countryInfos;
-  async function loadCountryData() {
-    countryInfos = await loadJSON('resources/data/world/country-info.json');  /* threejs.org: url */
-
-    const lonFudge = Math.PI * 1.5;
-    const latFudge = Math.PI;
-    // these helpers will make it easy to position the boxes
-    // We can rotate the lon helper on its Y axis to the longitude
-    const lonHelper = new THREE.Object3D();
-    // We rotate the latHelper on its X axis to the latitude
-    const latHelper = new THREE.Object3D();
-    lonHelper.add(latHelper);
-    // The position helper moves the object to the edge of the sphere
-    const positionHelper = new THREE.Object3D();
-    positionHelper.position.z = 1;
-    latHelper.add(positionHelper);
-
-    const labelParentElem = document.querySelector('#labels');
-    for (const countryInfo of countryInfos) {
-      const {lat, lon, min, max, name} = countryInfo;
-
-      // adjust the helpers to point to the latitude and longitude
-      lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge;
-      latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge;
-
-      // get the position of the lat/lon
-      positionHelper.updateWorldMatrix(true, false);
-      const position = new THREE.Vector3();
-      positionHelper.getWorldPosition(position);
-      countryInfo.position = position;
-
-      // compute the area for each country
-      const width = max[0] - min[0];
-      const height = max[1] - min[1];
-      const area = width * height;
-      countryInfo.area = area;
-
-      // add an element for each country
-      const elem = document.createElement('div');
-      elem.textContent = name;
-      labelParentElem.appendChild(elem);
-      countryInfo.elem = elem;
-    }
-    requestRenderIfNotRequested();
-  }
-  loadCountryData();
-
-  const tempV = new THREE.Vector3();
-  const cameraToPoint = new THREE.Vector3();
-  const cameraPosition = new THREE.Vector3();
-  const normalMatrix = new THREE.Matrix3();
-
-  const settings = {
-    minArea: 20,
-    maxVisibleDot: -0.2,
-  };
-  const gui = new GUI({width: 300});
-  gui.add(settings, 'minArea', 0, 50).onChange(requestRenderIfNotRequested);
-  gui.add(settings, 'maxVisibleDot', -1, 1, 0.01).onChange(requestRenderIfNotRequested);
-
-  function updateLabels() {
-    if (!countryInfos) {
-      return;
-    }
+	const fov = 60;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 10;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2.5;
 
-    const large = settings.minArea * settings.minArea;
-    // get a matrix that represents a relative orientation of the camera
-    normalMatrix.getNormalMatrix(camera.matrixWorldInverse);
-    // get the camera's position
-    camera.getWorldPosition(cameraPosition);
-    for (const countryInfo of countryInfos) {
-      const {position, elem, area} = countryInfo;
-      // large enough?
-      if (area < large) {
-        elem.style.display = 'none';
-        continue;
-      }
-
-      // Orient the position based on the camera's orientation.
-      // Since the sphere is at the origin and the sphere is a unit sphere
-      // this gives us a camera relative direction vector for the position.
-      tempV.copy(position);
-      tempV.applyMatrix3(normalMatrix);
-
-      // compute the direction to this position from the camera
-      cameraToPoint.copy(position);
-      cameraToPoint.applyMatrix4(camera.matrixWorldInverse).normalize();
-
-      // get the dot product of camera relative direction to this position
-      // on the globe with the direction from the camera to that point.
-      // -1 = facing directly towards the camera
-      // 0 = exactly on tangent of the sphere from the camera
-      // > 0 = facing away
-      const dot = tempV.dot(cameraToPoint);
-
-      // if the orientation is not facing us hide it.
-      if (dot > settings.maxVisibleDot) {
-        elem.style.display = 'none';
-        continue;
-      }
-
-      // restore the element to its default display style
-      elem.style.display = '';
-
-      // get the normalized screen coordinate of that position
-      // x and y will be in the -1 to +1 range with x = -1 being
-      // on the left and y = -1 being on the bottom
-      tempV.copy(position);
-      tempV.project(camera);
-
-      // convert the normalized position to CSS coordinates
-      const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-      const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-      // move the elem to that position
-      elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-      // set the zIndex for sorting
-      elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-    }
-  }
+	const controls = new OrbitControls( camera, canvas );
+	controls.enableDamping = true;
+	controls.enablePan = false;
+	controls.minDistance = 1.2;
+	controls.maxDistance = 4;
+	controls.update();
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( '#246' );
 
-  let renderRequested = false;
+	{
 
-  function render() {
-    renderRequested = undefined;
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/data/world/country-outlines-4k.png', render );
+		const geometry = new THREE.SphereGeometry( 1, 64, 32 );
+		const material = new THREE.MeshBasicMaterial( { map: texture } );
+		scene.add( new THREE.Mesh( geometry, material ) );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	}
 
-    controls.update();
+	async function loadJSON( url ) {
 
-    updateLabels();
+		const req = await fetch( url );
+		return req.json();
 
-    renderer.render(scene, camera);
-  }
-  render();
+	}
 
-  function requestRenderIfNotRequested() {
-    if (!renderRequested) {
-      renderRequested = true;
-      requestAnimationFrame(render);
-    }
-  }
+	let countryInfos;
+	async function loadCountryData() {
+
+		countryInfos = await loadJSON( 'resources/data/world/country-info.json' ); /* threejs.org: url */
+
+		const lonFudge = Math.PI * 1.5;
+		const latFudge = Math.PI;
+		// these helpers will make it easy to position the boxes
+		// We can rotate the lon helper on its Y axis to the longitude
+		const lonHelper = new THREE.Object3D();
+		// We rotate the latHelper on its X axis to the latitude
+		const latHelper = new THREE.Object3D();
+		lonHelper.add( latHelper );
+		// The position helper moves the object to the edge of the sphere
+		const positionHelper = new THREE.Object3D();
+		positionHelper.position.z = 1;
+		latHelper.add( positionHelper );
+
+		const labelParentElem = document.querySelector( '#labels' );
+		for ( const countryInfo of countryInfos ) {
+
+			const { lat, lon, min, max, name } = countryInfo;
+
+			// adjust the helpers to point to the latitude and longitude
+			lonHelper.rotation.y = THREE.MathUtils.degToRad( lon ) + lonFudge;
+			latHelper.rotation.x = THREE.MathUtils.degToRad( lat ) + latFudge;
+
+			// get the position of the lat/lon
+			positionHelper.updateWorldMatrix( true, false );
+			const position = new THREE.Vector3();
+			positionHelper.getWorldPosition( position );
+			countryInfo.position = position;
+
+			// compute the area for each country
+			const width = max[ 0 ] - min[ 0 ];
+			const height = max[ 1 ] - min[ 1 ];
+			const area = width * height;
+			countryInfo.area = area;
+
+			// add an element for each country
+			const elem = document.createElement( 'div' );
+			elem.textContent = name;
+			labelParentElem.appendChild( elem );
+			countryInfo.elem = elem;
+
+		}
+
+		requestRenderIfNotRequested();
+
+	}
+
+	loadCountryData();
+
+	const tempV = new THREE.Vector3();
+	const cameraToPoint = new THREE.Vector3();
+	const cameraPosition = new THREE.Vector3();
+	const normalMatrix = new THREE.Matrix3();
+
+	const settings = {
+		minArea: 20,
+		maxVisibleDot: - 0.2,
+	};
+	const gui = new GUI( { width: 300 } );
+	gui.add( settings, 'minArea', 0, 50 ).onChange( requestRenderIfNotRequested );
+	gui.add( settings, 'maxVisibleDot', - 1, 1, 0.01 ).onChange( requestRenderIfNotRequested );
+
+	function updateLabels() {
+
+		if ( ! countryInfos ) {
+
+			return;
+
+		}
+
+		const large = settings.minArea * settings.minArea;
+		// get a matrix that represents a relative orientation of the camera
+		normalMatrix.getNormalMatrix( camera.matrixWorldInverse );
+		// get the camera's position
+		camera.getWorldPosition( cameraPosition );
+		for ( const countryInfo of countryInfos ) {
+
+			const { position, elem, area } = countryInfo;
+			// large enough?
+			if ( area < large ) {
+
+				elem.style.display = 'none';
+				continue;
+
+			}
+
+			// Orient the position based on the camera's orientation.
+			// Since the sphere is at the origin and the sphere is a unit sphere
+			// this gives us a camera relative direction vector for the position.
+			tempV.copy( position );
+			tempV.applyMatrix3( normalMatrix );
+
+			// compute the direction to this position from the camera
+			cameraToPoint.copy( position );
+			cameraToPoint.applyMatrix4( camera.matrixWorldInverse ).normalize();
+
+			// get the dot product of camera relative direction to this position
+			// on the globe with the direction from the camera to that point.
+			// -1 = facing directly towards the camera
+			// 0 = exactly on tangent of the sphere from the camera
+			// > 0 = facing away
+			const dot = tempV.dot( cameraToPoint );
+
+			// if the orientation is not facing us hide it.
+			if ( dot > settings.maxVisibleDot ) {
+
+				elem.style.display = 'none';
+				continue;
+
+			}
+
+			// restore the element to its default display style
+			elem.style.display = '';
+
+			// get the normalized screen coordinate of that position
+			// x and y will be in the -1 to +1 range with x = -1 being
+			// on the left and y = -1 being on the bottom
+			tempV.copy( position );
+			tempV.project( camera );
+
+			// convert the normalized position to CSS coordinates
+			const x = ( tempV.x * .5 + .5 ) * canvas.clientWidth;
+			const y = ( tempV.y * - .5 + .5 ) * canvas.clientHeight;
+
+			// move the elem to that position
+			elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+
+			// set the zIndex for sorting
+			elem.style.zIndex = ( - tempV.z * .5 + .5 ) * 100000 | 0;
+
+		}
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	let renderRequested = false;
+
+	function render() {
+
+		renderRequested = undefined;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		controls.update();
+
+		updateLabels();
+
+		renderer.render( scene, camera );
+
+	}
+
+	render();
+
+	function requestRenderIfNotRequested() {
+
+		if ( ! renderRequested ) {
+
+			renderRequested = true;
+			requestAnimationFrame( render );
+
+		}
+
+	}
+
+	controls.addEventListener( 'change', requestRenderIfNotRequested );
+	window.addEventListener( 'resize', requestRenderIfNotRequested );
 
-  controls.addEventListener('change', requestRenderIfNotRequested);
-  window.addEventListener('resize', requestRenderIfNotRequested);
 }
 
 main();

+ 130 - 108
manual/examples/align-html-to-3d-w-hiding.html

@@ -70,129 +70,151 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 1.1;
-  const far = 20;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 7;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const labelContainerElem = document.querySelector('#labels');
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 1.1;
+	const far = 20;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 7;
 
-  function makeInstance(geometry, color, x, name) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 0, 0 );
+	controls.update();
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    const elem = document.createElement('div');
-    elem.textContent = name;
-    labelContainerElem.appendChild(elem);
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-    return {cube, elem};
-  }
+	}
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
-    makeInstance(geometry, 0x8844aa, -2, 'Purple'),
-    makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  const tempV = new THREE.Vector3();
-  const raycaster = new THREE.Raycaster();
+	const labelContainerElem = document.querySelector( '#labels' );
 
-  function render(time) {
-    time *= 0.001;
+	function makeInstance( geometry, color, x, name ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    cubes.forEach((cubeInfo, ndx) => {
-      const {cube, elem} = cubeInfo;
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-
-      // get the position of the center of the cube
-      cube.updateWorldMatrix(true, false);
-      cube.getWorldPosition(tempV);
-
-      // get the normalized screen coordinate of that position
-      // x and y will be in the -1 to +1 range with x = -1 being
-      // on the left and y = -1 being on the bottom
-      tempV.project(camera);
-
-      // ask the raycaster for all the objects that intersect
-      // from the eye toward this object's position
-      raycaster.setFromCamera(tempV, camera);
-      const intersectedObjects = raycaster.intersectObjects(scene.children);
-      // We're visible if the first intersection is this object.
-      const show = intersectedObjects.length && cube === intersectedObjects[0].object;
-
-      if (!show || Math.abs(tempV.z) > 1) {
-        // hide the label
-        elem.style.display = 'none';
-      } else {
-        // unhide the label
-        elem.style.display = '';
-
-        // convert the normalized position to CSS coordinates
-        const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-        const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-        // move the elem to that position
-        elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-      }
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		const elem = document.createElement( 'div' );
+		elem.textContent = name;
+		labelContainerElem.appendChild( elem );
+
+		return { cube, elem };
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0, 'Aqua' ),
+		makeInstance( geometry, 0x8844aa, - 2, 'Purple' ),
+		makeInstance( geometry, 0xaa8844, 2, 'Gold' ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const tempV = new THREE.Vector3();
+	const raycaster = new THREE.Raycaster();
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cubeInfo, ndx ) => {
+
+			const { cube, elem } = cubeInfo;
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+			// get the position of the center of the cube
+			cube.updateWorldMatrix( true, false );
+			cube.getWorldPosition( tempV );
+
+			// get the normalized screen coordinate of that position
+			// x and y will be in the -1 to +1 range with x = -1 being
+			// on the left and y = -1 being on the bottom
+			tempV.project( camera );
+
+			// ask the raycaster for all the objects that intersect
+			// from the eye toward this object's position
+			raycaster.setFromCamera( tempV, camera );
+			const intersectedObjects = raycaster.intersectObjects( scene.children );
+			// We're visible if the first intersection is this object.
+			const show = intersectedObjects.length && cube === intersectedObjects[ 0 ].object;
+
+			if ( ! show || Math.abs( tempV.z ) > 1 ) {
+
+				// hide the label
+				elem.style.display = 'none';
+
+			} else {
+
+				// unhide the label
+				elem.style.display = '';
+
+				// convert the normalized position to CSS coordinates
+				const x = ( tempV.x * .5 + .5 ) * canvas.clientWidth;
+				const y = ( tempV.y * - .5 + .5 ) * canvas.clientHeight;
+
+				// move the elem to that position
+				elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+
+			}
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 133 - 111
manual/examples/align-html-to-3d-w-sorting.html

@@ -72,132 +72,154 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 1.1;
-  const far = 20;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 7;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const labelContainerElem = document.querySelector('#labels');
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 1.1;
+	const far = 20;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 7;
 
-  function makeInstance(geometry, color, x, name) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 0, 0 );
+	controls.update();
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    const elem = document.createElement('div');
-    elem.textContent = name;
-    labelContainerElem.appendChild(elem);
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-    return {cube, elem};
-  }
+	}
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0, 'Aqua Colored Box'),
-    makeInstance(geometry, 0x8844aa, -2, 'Purple Colored Box'),
-    makeInstance(geometry, 0xaa8844,  2, 'Gold Colored Box'),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  const tempV = new THREE.Vector3();
-  const raycaster = new THREE.Raycaster();
+	const labelContainerElem = document.querySelector( '#labels' );
 
-  function render(time) {
-    time *= 0.001;
+	function makeInstance( geometry, color, x, name ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    cubes.forEach((cubeInfo, ndx) => {
-      const {cube, elem} = cubeInfo;
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-
-      // get the position of the center of the cube
-      cube.updateWorldMatrix(true, false);
-      cube.getWorldPosition(tempV);
-
-      // get the normalized screen coordinate of that position
-      // x and y will be in the -1 to +1 range with x = -1 being
-      // on the left and y = -1 being on the bottom
-      tempV.project(camera);
-
-      // ask the raycaster for all the objects that intersect
-      // from the eye toward this object's position
-      raycaster.setFromCamera(tempV, camera);
-      const intersectedObjects = raycaster.intersectObjects(scene.children);
-      // We're visible if the first intersection is this object.
-      const show = intersectedObjects.length && cube === intersectedObjects[0].object;
-
-      if (!show || Math.abs(tempV.z) > 1) {
-        // hide the label
-        elem.style.display = 'none';
-      } else {
-        // unhide the label
-        elem.style.display = '';
-
-        // convert the normalized position to CSS coordinates
-        const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-        const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
-
-        // move the elem to that position
-        elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-
-        // set the zIndex for sorting
-        elem.style.zIndex = (-tempV.z * .5 + .5) * 100000 | 0;
-      }
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		const elem = document.createElement( 'div' );
+		elem.textContent = name;
+		labelContainerElem.appendChild( elem );
+
+		return { cube, elem };
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0, 'Aqua Colored Box' ),
+		makeInstance( geometry, 0x8844aa, - 2, 'Purple Colored Box' ),
+		makeInstance( geometry, 0xaa8844, 2, 'Gold Colored Box' ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const tempV = new THREE.Vector3();
+	const raycaster = new THREE.Raycaster();
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cubeInfo, ndx ) => {
+
+			const { cube, elem } = cubeInfo;
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+			// get the position of the center of the cube
+			cube.updateWorldMatrix( true, false );
+			cube.getWorldPosition( tempV );
+
+			// get the normalized screen coordinate of that position
+			// x and y will be in the -1 to +1 range with x = -1 being
+			// on the left and y = -1 being on the bottom
+			tempV.project( camera );
+
+			// ask the raycaster for all the objects that intersect
+			// from the eye toward this object's position
+			raycaster.setFromCamera( tempV, camera );
+			const intersectedObjects = raycaster.intersectObjects( scene.children );
+			// We're visible if the first intersection is this object.
+			const show = intersectedObjects.length && cube === intersectedObjects[ 0 ].object;
+
+			if ( ! show || Math.abs( tempV.z ) > 1 ) {
+
+				// hide the label
+				elem.style.display = 'none';
+
+			} else {
+
+				// unhide the label
+				elem.style.display = '';
+
+				// convert the normalized position to CSS coordinates
+				const x = ( tempV.x * .5 + .5 ) * canvas.clientWidth;
+				const y = ( tempV.y * - .5 + .5 ) * canvas.clientHeight;
+
+				// move the elem to that position
+				elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+
+				// set the zIndex for sorting
+				elem.style.zIndex = ( - tempV.z * .5 + .5 ) * 100000 | 0;
+
+			}
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 104 - 86
manual/examples/align-html-to-3d.html

@@ -70,113 +70,131 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 1.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 7;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const labelContainerElem = document.querySelector('#labels');
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 1.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 7;
 
-  function makeInstance(geometry, color, x, name) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 0, 0 );
+	controls.update();
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    const elem = document.createElement('div');
-    elem.textContent = name;
-    labelContainerElem.appendChild(elem);
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-    return {cube, elem};
-  }
+	}
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0, 'Aqua'),
-    makeInstance(geometry, 0x8844aa, -2, 'Purple'),
-    makeInstance(geometry, 0xaa8844,  2, 'Gold'),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  const tempV = new THREE.Vector3();
+	const labelContainerElem = document.querySelector( '#labels' );
 
-  function render(time) {
-    time *= 0.001;
+	function makeInstance( geometry, color, x, name ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    cubes.forEach((cubeInfo, ndx) => {
-      const {cube, elem} = cubeInfo;
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-      // get the position of the center of the cube
-      cube.updateWorldMatrix(true, false);
-      cube.getWorldPosition(tempV);
+		cube.position.x = x;
 
-      // get the normalized screen coordinate of that position
-      // x and y will be in the -1 to +1 range with x = -1 being
-      // on the left and y = -1 being on the bottom
-      tempV.project(camera);
+		const elem = document.createElement( 'div' );
+		elem.textContent = name;
+		labelContainerElem.appendChild( elem );
 
-      // convert the normalized position to CSS coordinates
-      const x = (tempV.x *  .5 + .5) * canvas.clientWidth;
-      const y = (tempV.y * -.5 + .5) * canvas.clientHeight;
+		return { cube, elem };
 
-      // move the elem to that position
-      elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
-    });
+	}
 
-    renderer.render(scene, camera);
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0, 'Aqua' ),
+		makeInstance( geometry, 0x8844aa, - 2, 'Purple' ),
+		makeInstance( geometry, 0xaa8844, 2, 'Gold' ),
+	];
 
-    requestAnimationFrame(render);
-  }
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const tempV = new THREE.Vector3();
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cubeInfo, ndx ) => {
+
+			const { cube, elem } = cubeInfo;
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+			// get the position of the center of the cube
+			cube.updateWorldMatrix( true, false );
+			cube.getWorldPosition( tempV );
+
+			// get the normalized screen coordinate of that position
+			// x and y will be in the -1 to +1 range with x = -1 being
+			// on the left and y = -1 being on the bottom
+			tempV.project( camera );
+
+			// convert the normalized position to CSS coordinates
+			const x = ( tempV.x * .5 + .5 ) * canvas.clientWidth;
+			const y = ( tempV.y * - .5 + .5 ) * canvas.clientHeight;
+
+			// move the elem to that position
+			elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 85 - 67
manual/examples/background-css.html

@@ -38,85 +38,103 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({
-    canvas,
-    alpha: true,
-    antialias: true
-  });
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( {
+		canvas,
+		alpha: true,
+		antialias: true
+	} );
+	renderer.useLegacyLights = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeInstance( geometry, color, x ) {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    renderer.render(scene, camera);
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    requestAnimationFrame(render);
-  }
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 100 - 80
manual/examples/background-cubemap.html

@@ -35,101 +35,121 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 3;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 3;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 0, 0 );
+	controls.update();
 
-    cube.position.x = x;
+	const scene = new THREE.Scene();
 
-    return cube;
-  }
+	{
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  {
-    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 color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeInstance( geometry, color, x ) {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    renderer.render(scene, camera);
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    requestAnimationFrame(render);
-  }
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	{
+
+		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;
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 100 - 78
manual/examples/background-equirectangularmap.html

@@ -35,99 +35,121 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 3;
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 3;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 0, 0 );
+	controls.update();
 
-    cube.position.x = x;
+	const scene = new THREE.Scene();
 
-    return cube;
-  }
+	{
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  {
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load(
-      'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
-      () => {
-        const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-        rt.fromEquirectangularTexture(renderer, texture);
-        scene.background = rt.texture;
-      });
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeInstance( geometry, color, x ) {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    renderer.render(scene, camera);
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    requestAnimationFrame(render);
-  }
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	{
+
+		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;
+
+			} );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 97 - 78
manual/examples/background-scene-background-fixed-aspect.html

@@ -36,99 +36,118 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	renderer.autoClearColor = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  const loader = new THREE.TextureLoader();
-  const bgTexture = loader.load('resources/images/daikanyama.jpg');
-  scene.background = bgTexture;
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeInstance( geometry, color, x ) {
 
-    // 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;
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    bgTexture.offset.x = aspect > 1 ? (1 - 1 / aspect) / 2 : 0;
-    bgTexture.repeat.x = aspect > 1 ? 1 / aspect : 1;
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    bgTexture.offset.y = aspect > 1 ? 0 : (1 - aspect) / 2;
-    bgTexture.repeat.y = aspect > 1 ? 1 : aspect;
+		cube.position.x = x;
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		return cube;
 
-    renderer.render(scene, camera);
+	}
 
-    requestAnimationFrame(render);
-  }
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	const loader = new THREE.TextureLoader();
+	const bgTexture = loader.load( 'resources/images/daikanyama.jpg' );
+	bgTexture.colorSpace = THREE.SRGBColorSpace;
+	scene.background = bgTexture;
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		// 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;
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 87 - 68
manual/examples/background-scene-background.html

@@ -36,86 +36,105 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	renderer.autoClearColor = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  const loader = new THREE.TextureLoader();
-  const bgTexture = loader.load('resources/images/daikanyama.jpg');
-  scene.background = bgTexture;
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	}
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeInstance( geometry, color, x ) {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    renderer.render(scene, camera);
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    requestAnimationFrame(render);
-  }
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	const loader = new THREE.TextureLoader();
+	const bgTexture = loader.load( 'resources/images/daikanyama.jpg' );
+	bgTexture.colorSpace = THREE.SRGBColorSpace;
+	scene.background = bgTexture;
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 109 - 89
manual/examples/background-separate-scene-bad-aspect.html

@@ -36,108 +36,128 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	renderer.autoClearColor = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  const bgCamera = new THREE.OrthographicCamera(
-    -1, // left
-     1, // right
-     1, // top
-    -1, // bottom
-    -1, // near,
-     1, // far
-  );
-
-  const bgScene = new THREE.Scene();
-
-  const loader = new THREE.TextureLoader();
-  const bgTexture = loader.load('resources/images/daikanyama.jpg');
-  let bgMesh;
-  {
-    const plane = new THREE.PlaneGeometry(2, 2);
-    const material = new THREE.MeshBasicMaterial({
-      map: bgTexture,
-      depthTest: false,
-    });
-    bgMesh = new THREE.Mesh(plane, material);
-    bgScene.add(bgMesh);
-  }
+	}
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  function render(time) {
-    time *= 0.001;
+	function makeInstance( geometry, color, x ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      const canvasAspect = canvas.clientWidth / canvas.clientHeight;
-      camera.aspect = canvasAspect;
-      camera.updateProjectionMatrix();
-    }
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
 
-    renderer.render(bgScene, bgCamera);
-    renderer.render(scene, camera);
+		cube.position.x = x;
 
-    requestAnimationFrame(render);
-  }
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	const bgCamera = new THREE.OrthographicCamera(
+		- 1, // left
+		1, // right
+		1, // top
+		- 1, // bottom
+		- 1, // near,
+		1, // far
+	);
+
+	const bgScene = new THREE.Scene();
+
+	const loader = new THREE.TextureLoader();
+	const bgTexture = loader.load( 'resources/images/daikanyama.jpg' );
+	let bgMesh;
+	{
+
+		const plane = new THREE.PlaneGeometry( 2, 2 );
+		const material = new THREE.MeshBasicMaterial( {
+			map: bgTexture,
+			depthTest: false,
+		} );
+		bgMesh = new THREE.Mesh( plane, material );
+		bgScene.add( bgMesh );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			const canvasAspect = canvas.clientWidth / canvas.clientHeight;
+			camera.aspect = canvasAspect;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( bgScene, bgCamera );
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 119 - 99
manual/examples/background-separate-scene.html

@@ -36,116 +36,136 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.autoClearColor = false;
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	renderer.autoClearColor = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  const bgCamera = new THREE.OrthographicCamera(
-    -1, // left
-     1, // right
-     1, // top
-    -1, // bottom
-    -1, // near,
-     1, // far
-  );
-
-  const bgScene = new THREE.Scene();
-
-  const loader = new THREE.TextureLoader();
-  const bgTexture = loader.load('resources/images/daikanyama.jpg');
-  let bgMesh;
-  {
-    const plane = new THREE.PlaneGeometry(2, 2);
-    const material = new THREE.MeshBasicMaterial({
-      map: bgTexture,
-      depthTest: false,
-    });
-    bgMesh = new THREE.Mesh(plane, material);
-    bgScene.add(bgMesh);
-  }
+	}
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  function render(time) {
-    time *= 0.001;
+	function makeInstance( geometry, color, x ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    // Scale the background plane to cover and 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;
-    // choose an axis to have a scale of 1 and the other >= 1
-    bgMesh.scale.x = aspect > 1 ? aspect : 1;
-    bgMesh.scale.y = aspect > 1 ? 1 : 1 / aspect;
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(bgScene, bgCamera);
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	const bgCamera = new THREE.OrthographicCamera(
+		- 1, // left
+		1, // right
+		1, // top
+		- 1, // bottom
+		- 1, // near,
+		1, // far
+	);
+
+	const bgScene = new THREE.Scene();
+
+	const loader = new THREE.TextureLoader();
+	const bgTexture = loader.load( 'resources/images/daikanyama.jpg' );
+	let bgMesh;
+	{
+
+		const plane = new THREE.PlaneGeometry( 2, 2 );
+		const material = new THREE.MeshBasicMaterial( {
+			map: bgTexture,
+			depthTest: false,
+		} );
+		bgMesh = new THREE.Mesh( plane, material );
+		bgScene.add( bgMesh );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		// Scale the background plane to cover and 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;
+		// choose an axis to have a scale of 1 and the other >= 1
+		bgMesh.scale.x = aspect > 1 ? aspect : 1;
+		bgMesh.scale.y = aspect > 1 ? 1 : 1 / aspect;
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( bgScene, bgCamera );
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 144 - 117
manual/examples/background-v01.html

@@ -36,89 +36,104 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  const scene = new THREE.Scene();
-
-  const aspect = 2;  // the canvas default
-  const fov = 35;
-  const near = 0.1;
-  const far = 5000;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.x = -0.;
-  camera.position.y = 350;
-  camera.position.z = 40.;
-
-  const useFog = true;
-  const useOrbitCamera = false;
-  const showHelpers = false;
-  const camSpeed = 0.2;
-
-  if (useOrbitCamera) {
-    const controls = new OrbitControls(camera, canvas);
-    controls.target.set(0, 100.01, 0.2);
-    controls.update();
-  }
 
-  renderer.outputColorSpace = THREE.SRGBColorSpace;
-  renderer.shadowMap.enabled = true;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	const scene = new THREE.Scene();
 
-  const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
-  hemiLight.color.setHSL(0.6, 1, 0.6);
-  hemiLight.groundColor.setHSL(0.095, 1, 0.75);
-  hemiLight.position.set(0, 50, 0);
-  scene.add(hemiLight);
+	const aspect = 2; // the canvas default
+	const fov = 35;
+	const near = 0.1;
+	const far = 5000;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.x = - 0.;
+	camera.position.y = 350;
+	camera.position.z = 40.;
 
-  if (showHelpers) {
-    const hemiLightHelper = new THREE.HemisphereLightHelper(hemiLight, 10);
-    scene.add(hemiLightHelper);
-  }
+	const useFog = true;
+	const useOrbitCamera = false;
+	const showHelpers = false;
+	const camSpeed = 0.2;
 
-  const dirLight = new THREE.DirectionalLight(0xffffff, 1);
-  dirLight.color.setHSL(0.1, 1, 0.95);
-  dirLight.position.set(-300, 220, 245);
-  scene.add(dirLight);
-  dirLight.castShadow = true;
-  dirLight.shadow.mapSize.width = 2048;
-  dirLight.shadow.mapSize.height = 2048;
-  const d = 350;
-  dirLight.shadow.camera.left = -d;
-  dirLight.shadow.camera.right = d;
-  dirLight.shadow.camera.top = d;
-  dirLight.shadow.camera.bottom = -d;
-  dirLight.shadow.camera.near = 100;
-  dirLight.shadow.camera.far = 950;
-  dirLight.shadow.bias = -0.005;
-
-  if (showHelpers) {
-    const dirLightHeper = new THREE.DirectionalLightHelper(dirLight, 10);
-    scene.add(dirLightHeper);
-  }
+	if ( useOrbitCamera ) {
+
+		const controls = new OrbitControls( camera, canvas );
+		controls.target.set( 0, 100.01, 0.2 );
+		controls.update();
+
+	}
+
+	renderer.outputColorSpace = THREE.SRGBColorSpace;
+	renderer.shadowMap.enabled = true;
+
+	const hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 2 );
+	hemiLight.color.setHSL( 0.6, 1, 0.6 );
+	hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
+	hemiLight.position.set( 0, 50, 0 );
+	scene.add( hemiLight );
+
+	if ( showHelpers ) {
+
+		const hemiLightHelper = new THREE.HemisphereLightHelper( hemiLight, 10 );
+		scene.add( hemiLightHelper );
+
+	}
+
+	const dirLight = new THREE.DirectionalLight( 0xffffff, 3 );
+	dirLight.color.setHSL( 0.1, 1, 0.95 );
+	dirLight.position.set( - 300, 220, 245 );
+	scene.add( dirLight );
+	dirLight.castShadow = true;
+	dirLight.shadow.mapSize.width = 2048;
+	dirLight.shadow.mapSize.height = 2048;
+	const d = 350;
+	dirLight.shadow.camera.left = - d;
+	dirLight.shadow.camera.right = d;
+	dirLight.shadow.camera.top = d;
+	dirLight.shadow.camera.bottom = - d;
+	dirLight.shadow.camera.near = 100;
+	dirLight.shadow.camera.far = 950;
+	dirLight.shadow.bias = - 0.005;
+
+	if ( showHelpers ) {
+
+		const dirLightHeper = new THREE.DirectionalLightHelper( dirLight, 10 );
+		scene.add( dirLightHeper );
+
+	}
+
+	const loader = new GLTFLoader();
+	const camRadius = 600;
+	const camHeight = 160;
+	const camTarget = [ 0, 30, 0 ];
+	const fogNear = 1350;
+	const fogFar = 1500;
+	loader.load( 'resources/models/mountain_landscape/scene.gltf', ( gltf ) => {
+
+		gltf.scene.traverse( ( child ) => {
+
+			if ( child.isMesh ) {
+
+				child.castShadow = true;
+				child.receiveShadow = true;
+
+			}
+
+		} );
+		scene.add( gltf.scene );
+
+	} );
 
-  const loader = new GLTFLoader();
-  const camRadius = 600;
-  const camHeight = 160;
-  const camTarget = [0, 30, 0];
-  const fogNear = 1350;
-  const fogFar = 1500;
-  loader.load('resources/models/mountain_landscape/scene.gltf', (gltf) => {
-    gltf.scene.traverse((child) => {
-      if ( child.isMesh ) {
-        child.castShadow = true;
-        child.receiveShadow = true;
-      }
-    });
-    scene.add(gltf.scene);
-  });
-
-  window.s = scene;
-
-  if (useFog) {
-    const vertexShader = `
+	window.s = scene;
+
+	if ( useFog ) {
+
+		const vertexShader = `
     varying vec3 vWorldPosition;
     void main() {
       vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
@@ -127,7 +142,7 @@ function main() {
     }
     `;
 
-    const fragmentShader = `
+		const fragmentShader = `
     uniform vec3 topColor;
     uniform vec3 bottomColor;
     uniform float offset;
@@ -139,54 +154,66 @@ function main() {
     }
     `;
 
-    const uniforms = {
-      topColor:    { value: new THREE.Color(0x88AABB) },
-      bottomColor: { value: new THREE.Color(0xEFCB7F) },
-      offset:      { value: 730 },
-      exponent:    { value: 0.3 },
-    };
-    uniforms.topColor.value.copy(hemiLight.color);
-    scene.fog = new THREE.Fog(scene.background, fogNear, fogFar);
-    scene.fog.color.copy(uniforms.bottomColor.value);
-    const skyGeo = new THREE.SphereGeometry(4000, 32, 15);
-    const skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
-    const sky = new THREE.Mesh( skyGeo, skyMat );
-    scene.add(sky);
-  }
+		const uniforms = {
+			topColor: { value: new THREE.Color( 0x88AABB ) },
+			bottomColor: { value: new THREE.Color( 0xEFCB7F ) },
+			offset: { value: 730 },
+			exponent: { value: 0.3 },
+		};
+		uniforms.topColor.value.copy( hemiLight.color );
+		scene.fog = new THREE.Fog( scene.background, fogNear, fogFar );
+		scene.fog.color.copy( uniforms.bottomColor.value );
+		const skyGeo = new THREE.SphereGeometry( 4000, 32, 15 );
+		const skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
+		const sky = new THREE.Mesh( skyGeo, skyMat );
+		scene.add( sky );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    if (width === canvas.width && height === canvas.height) {
-      return false;
-    }
+	}
 
-    renderer.setSize(width, height, false);
-    return true;
-  }
+	function resizeRendererToDisplaySize( renderer ) {
 
-  function render(time) {
-    time *= 0.001;
-    time += 80;
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		if ( width === canvas.width && height === canvas.height ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+			return false;
 
-    if (!useOrbitCamera) {
-      const angle = Math.sin(time * camSpeed) + Math.PI * .75;
-      camera.position.set(Math.cos(angle) * camRadius, camHeight, Math.sin(angle) * camRadius);
-      camera.lookAt(...camTarget);
-    }
+		}
 
-    renderer.render(scene, camera);
+		renderer.setSize( width, height, false );
+		return true;
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+		time += 80;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		if ( ! useOrbitCamera ) {
+
+			const angle = Math.sin( time * camSpeed ) + Math.PI * .75;
+			camera.position.set( Math.cos( angle ) * camRadius, camHeight, Math.sin( angle ) * camRadius );
+			camera.lookAt( ...camTarget );
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 181 - 149
manual/examples/background.html

@@ -36,118 +36,138 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  const scene = new THREE.Scene();
-
-  const aspect = 2;  // the canvas default
-  const fov = 35;
-  const near = 0.1;
-  const far = 5000;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(-580, 55, 390);
-
-  const maxFovX = 40;
-  const numBirds = 40;
-  const minMax = 700;
-  const birdSpeed = 100;
-  const useFog = true;
-  const useOrbitCamera = true;
-  const showHelpers = false;
-
-  if (useOrbitCamera) {
-    const controls = new OrbitControls(camera, canvas);
-    controls.target.set(0, 0, 0);
-    controls.update();
-  }
 
-  renderer.outputColorSpace = THREE.SRGBColorSpace;
-  renderer.shadowMap.enabled = true;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	const scene = new THREE.Scene();
 
-  const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
-  hemiLight.color.setHSL(0.6, 1, 0.5);
-  hemiLight.groundColor.setHSL(0.095, 1, 0.5);
-  hemiLight.position.set(0, 50, 0);
-  scene.add(hemiLight);
+	const aspect = 2; // the canvas default
+	const fov = 35;
+	const near = 0.1;
+	const far = 5000;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( - 580, 55, 390 );
 
-  if (showHelpers) {
-    const hemiLightHelper = new THREE.HemisphereLightHelper(hemiLight, 10);
-    scene.add(hemiLightHelper);
-  }
+	const maxFovX = 40;
+	const numBirds = 40;
+	const minMax = 700;
+	const birdSpeed = 100;
+	const useFog = true;
+	const useOrbitCamera = true;
+	const showHelpers = false;
 
-  const dirLight = new THREE.DirectionalLight(0xffffff, 1);
-  dirLight.color.setHSL(0.1, 1, 0.95);
-  dirLight.position.set(-300, 220, 245);
-  scene.add(dirLight);
-  dirLight.castShadow = true;
-  dirLight.shadow.mapSize.width = 2048;
-  dirLight.shadow.mapSize.height = 2048;
-  const d = 350;
-  dirLight.shadow.camera.left = -d;
-  dirLight.shadow.camera.right = d;
-  dirLight.shadow.camera.top = d;
-  dirLight.shadow.camera.bottom = -d;
-  dirLight.shadow.camera.near = 100;
-  dirLight.shadow.camera.far = 950;
-  dirLight.shadow.bias = -0.005;
-
-  if (showHelpers) {
-    const dirLightHeper = new THREE.DirectionalLightHelper(dirLight, 10);
-    scene.add(dirLightHeper);
-  }
+	if ( useOrbitCamera ) {
 
-  const birds = [];
-  const loader = new GLTFLoader();
-  const fogNear = 1350;
-  const fogFar = 1500;
-
-  function rand(min, max) {
-    if (min === undefined) {
-      min = 0;
-      max = 1;
-    } else if (max === undefined) {
-      max = min;
-      min = 0;
-    }
-    return min + Math.random() * (max - min);
-  }
+		const controls = new OrbitControls( camera, canvas );
+		controls.target.set( 0, 0, 0 );
+		controls.update();
 
-  loader.load( 'resources/models/flamingo/Flamingo.glb', (gltf) => {
-    const orig = gltf.scene.children[0];
-    orig.castShadow = true;
-    orig.receiveShadow = true;
-
-    for (let i = 0; i < numBirds; ++i) {
-      const u = i / (numBirds - 1);
-      const mesh = orig.clone();
-      mesh.position.set(
-        rand(-150, 150),
-        (u * 2 - 1) * 200,
-        (minMax * 2 * i * 1.7) % (minMax * 2) - minMax / 2,
-      );
-      scene.add(mesh);
-      mesh.material = mesh.material.clone();
-      mesh.material.color.setHSL(rand(), 1, 0.8);
-
-      const mixer = new THREE.AnimationMixer(mesh);
-      mixer.clipAction(gltf.animations[0]).setDuration(1).play();
-      mixer.update(rand(10));
-      mixer.timeScale = rand(0.9, 1.1);
-      birds.push({
-        mixer,
-        mesh,
-      });
-    }
-  });
+	}
+
+	renderer.outputColorSpace = THREE.SRGBColorSpace;
+	renderer.shadowMap.enabled = true;
+
+	const hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 2 );
+	hemiLight.color.setHSL( 0.6, 1, 0.5 );
+	hemiLight.groundColor.setHSL( 0.095, 1, 0.5 );
+	hemiLight.position.set( 0, 50, 0 );
+	scene.add( hemiLight );
+
+	if ( showHelpers ) {
+
+		const hemiLightHelper = new THREE.HemisphereLightHelper( hemiLight, 10 );
+		scene.add( hemiLightHelper );
+
+	}
+
+	const dirLight = new THREE.DirectionalLight( 0xffffff, 3 );
+	dirLight.color.setHSL( 0.1, 1, 0.95 );
+	dirLight.position.set( - 300, 220, 245 );
+	scene.add( dirLight );
+	dirLight.castShadow = true;
+	dirLight.shadow.mapSize.width = 2048;
+	dirLight.shadow.mapSize.height = 2048;
+	const d = 350;
+	dirLight.shadow.camera.left = - d;
+	dirLight.shadow.camera.right = d;
+	dirLight.shadow.camera.top = d;
+	dirLight.shadow.camera.bottom = - d;
+	dirLight.shadow.camera.near = 100;
+	dirLight.shadow.camera.far = 950;
+	dirLight.shadow.bias = - 0.005;
+
+	if ( showHelpers ) {
+
+		const dirLightHeper = new THREE.DirectionalLightHelper( dirLight, 10 );
+		scene.add( dirLightHeper );
+
+	}
+
+	const birds = [];
+	const loader = new GLTFLoader();
+	const fogNear = 1350;
+	const fogFar = 1500;
+
+	function rand( min, max ) {
+
+		if ( min === undefined ) {
+
+			min = 0;
+			max = 1;
+
+		} else if ( max === undefined ) {
+
+			max = min;
+			min = 0;
+
+		}
+
+		return min + Math.random() * ( max - min );
+
+	}
+
+	loader.load( 'resources/models/flamingo/Flamingo.glb', ( gltf ) => {
+
+		const orig = gltf.scene.children[ 0 ];
+		orig.castShadow = true;
+		orig.receiveShadow = true;
 
-  window.s = scene;
+		for ( let i = 0; i < numBirds; ++ i ) {
 
-  if (useFog) {
-    const vertexShader = `
+			const u = i / ( numBirds - 1 );
+			const mesh = orig.clone();
+			mesh.position.set(
+				rand( - 150, 150 ),
+				( u * 2 - 1 ) * 200,
+				( minMax * 2 * i * 1.7 ) % ( minMax * 2 ) - minMax / 2,
+			);
+			scene.add( mesh );
+			mesh.material = mesh.material.clone();
+			mesh.material.color.setHSL( rand(), 1, 0.8 );
+
+			const mixer = new THREE.AnimationMixer( mesh );
+			mixer.clipAction( gltf.animations[ 0 ] ).setDuration( 1 ).play();
+			mixer.update( rand( 10 ) );
+			mixer.timeScale = rand( 0.9, 1.1 );
+			birds.push( {
+				mixer,
+				mesh,
+			} );
+
+		}
+
+	} );
+
+	window.s = scene;
+
+	if ( useFog ) {
+
+		const vertexShader = `
     varying vec3 vWorldPosition;
     void main() {
       vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
@@ -156,7 +176,7 @@ function main() {
     }
     `;
 
-    const fragmentShader = `
+		const fragmentShader = `
     uniform vec3 topColor;
     uniform vec3 bottomColor;
     uniform float offset;
@@ -168,59 +188,71 @@ function main() {
     }
     `;
 
-    const uniforms = {
-      topColor:    { value: new THREE.Color(0x88AABB) },
-      bottomColor: { value: new THREE.Color(0xEFCB7F) },
-      offset:      { value: 730 },
-      exponent:    { value: 0.3 },
-    };
-    uniforms.topColor.value.copy(hemiLight.color);
-    scene.fog = new THREE.Fog(scene.background, fogNear, fogFar);
-    scene.fog.color.copy(uniforms.bottomColor.value);
-    const skyGeo = new THREE.SphereGeometry(3000, 32, 15);
-    const skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
-    const sky = new THREE.Mesh( skyGeo, skyMat );
-    scene.add(sky);
-  }
+		const uniforms = {
+			topColor: { value: new THREE.Color( 0x88AABB ) },
+			bottomColor: { value: new THREE.Color( 0xEFCB7F ) },
+			offset: { value: 730 },
+			exponent: { value: 0.3 },
+		};
+		uniforms.topColor.value.copy( hemiLight.color );
+		scene.fog = new THREE.Fog( scene.background, fogNear, fogFar );
+		scene.fog.color.copy( uniforms.bottomColor.value );
+		const skyGeo = new THREE.SphereGeometry( 3000, 32, 15 );
+		const skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
+		const sky = new THREE.Mesh( skyGeo, skyMat );
+		scene.add( sky );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    if (width === canvas.width && height === canvas.height) {
-      return false;
-    }
+	}
 
-    renderer.setSize(width, height, false);
-    return true;
-  }
+	function resizeRendererToDisplaySize( renderer ) {
 
-  let then = 0;
-  function render(now) {
-    now *= 0.001;
-    const deltaTime = now - then;
-    then = now;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const aspect = canvas.clientWidth / canvas.clientHeight;
-      const fovX = THREE.MathUtils.radToDeg(2 * Math.atan(Math.tan(THREE.MathUtils.degToRad(fov) * 0.5) * aspect));
-      const newFovY = THREE.MathUtils.radToDeg(2 * Math.atan(Math.tan(THREE.MathUtils.degToRad(maxFovX) * .5) / aspect));
-      camera.fov = fovX > maxFovX ? newFovY : fov;
-      camera.aspect = aspect;
-      camera.updateProjectionMatrix();
-    }
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		if ( width === canvas.width && height === canvas.height ) {
 
-    for (const {mesh, mixer} of birds) {
-      mixer.update(deltaTime);
-      mesh.position.z = (mesh.position.z + minMax + mixer.timeScale * birdSpeed * deltaTime) % (minMax * 2) - minMax;
-    }
+			return false;
 
-    renderer.render(scene, camera);
+		}
 
-    requestAnimationFrame(render);
-  }
+		renderer.setSize( width, height, false );
+		return true;
+
+	}
+
+	let then = 0;
+	function render( now ) {
+
+		now *= 0.001;
+		const deltaTime = now - then;
+		then = now;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const aspect = canvas.clientWidth / canvas.clientHeight;
+			const fovX = THREE.MathUtils.radToDeg( 2 * Math.atan( Math.tan( THREE.MathUtils.degToRad( fov ) * 0.5 ) * aspect ) );
+			const newFovY = THREE.MathUtils.radToDeg( 2 * Math.atan( Math.tan( THREE.MathUtils.degToRad( maxFovX ) * .5 ) / aspect ) );
+			camera.fov = fovX > maxFovX ? newFovY : fov;
+			camera.aspect = aspect;
+			camera.updateProjectionMatrix();
+
+		}
+
+		for ( const { mesh, mixer } of birds ) {
+
+			mixer.update( deltaTime );
+			mesh.position.z = ( mesh.position.z + minMax + mixer.timeScale * birdSpeed * deltaTime ) % ( minMax * 2 ) - minMax;
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 158 - 139
manual/examples/billboard-labels-w-sprites-adjust-height.html

@@ -35,153 +35,172 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('white');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const bodyRadiusTop = .4;
-  const bodyRadiusBottom = .2;
-  const bodyHeight = 2;
-  const bodyRadialSegments = 6;
-  const bodyGeometry = new THREE.CylinderGeometry(
-      bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-
-  const headRadius = bodyRadiusTop * 0.8;
-  const headLonSegments = 12;
-  const headLatSegments = 5;
-  const headGeometry = new THREE.SphereGeometry(
-      headRadius, headLonSegments, headLatSegments);
-
-  function makeLabelCanvas(baseWidth, size, name) {
-    const borderSize = 2;
-    const ctx = document.createElement('canvas').getContext('2d');
-    const font =  `${size}px bold sans-serif`;
-    ctx.font = font;
-    // measure how long the name will be
-    const textWidth = ctx.measureText(name).width;
-
-    const doubleBorderSize = borderSize * 2;
-    const width = baseWidth + doubleBorderSize;
-    const height = size + doubleBorderSize;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-
-    // need to set font again after resizing canvas
-    ctx.font = font;
-    ctx.textBaseline = 'middle';
-    ctx.textAlign = 'center';
-
-    ctx.fillStyle = 'blue';
-    ctx.fillRect(0, 0, width, height);
-
-    // scale to fit but don't stretch
-    const scaleFactor = Math.min(1, baseWidth / textWidth);
-    ctx.translate(width / 2, height / 2);
-    ctx.scale(scaleFactor, 1);
-    ctx.fillStyle = 'white';
-    ctx.fillText(name, 0, 0);
-
-    return ctx.canvas;
-  }
 
-  function makePerson(x, labelWidth, size, name, color) {
-    const canvas = makeLabelCanvas(labelWidth, size, name);
-    const texture = new THREE.CanvasTexture(canvas);
-    // because our canvas is likely not a power of 2
-    // in both dimensions set the filtering appropriately.
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = THREE.ClampToEdgeWrapping;
-    texture.wrapT = THREE.ClampToEdgeWrapping;
-
-    const labelMaterial = new THREE.SpriteMaterial({
-      map: texture,
-      transparent: true,
-    });
-    const bodyMaterial = new THREE.MeshPhongMaterial({
-      color,
-      flatShading: true,
-    });
-
-    const root = new THREE.Object3D();
-    root.position.x = x;
-
-    const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-    root.add(body);
-    body.position.y = bodyHeight / 2;
-
-    const head = new THREE.Mesh(headGeometry, bodyMaterial);
-    root.add(head);
-    head.position.y = bodyHeight + headRadius * 1.1;
-
-    // if units are meters then 0.01 here makes size
-    // of the label into centimeters.
-    const labelBaseScale = 0.01;
-    const label = new THREE.Sprite(labelMaterial);
-    root.add(label);
-    label.position.y = head.position.y + headRadius + size * labelBaseScale;
-
-    label.scale.x = canvas.width  * labelBaseScale;
-    label.scale.y = canvas.height * labelBaseScale;
-
-    scene.add(root);
-    return root;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'white' );
+
+	function addLight( position ) {
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const bodyRadiusTop = .4;
+	const bodyRadiusBottom = .2;
+	const bodyHeight = 2;
+	const bodyRadialSegments = 6;
+	const bodyGeometry = new THREE.CylinderGeometry(
+		bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments );
+
+	const headRadius = bodyRadiusTop * 0.8;
+	const headLonSegments = 12;
+	const headLatSegments = 5;
+	const headGeometry = new THREE.SphereGeometry(
+		headRadius, headLonSegments, headLatSegments );
 
-  makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-  makePerson(-0, 150, 32, 'Green Machine', 'green');
-  makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	function makeLabelCanvas( baseWidth, size, name ) {
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const borderSize = 2;
+		const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+		const font = `${size}px bold sans-serif`;
+		ctx.font = font;
+		// measure how long the name will be
+		const textWidth = ctx.measureText( name ).width;
 
-    renderer.render(scene, camera);
+		const doubleBorderSize = borderSize * 2;
+		const width = baseWidth + doubleBorderSize;
+		const height = size + doubleBorderSize;
+		ctx.canvas.width = width;
+		ctx.canvas.height = height;
 
-    requestAnimationFrame(render);
-  }
+		// need to set font again after resizing canvas
+		ctx.font = font;
+		ctx.textBaseline = 'middle';
+		ctx.textAlign = 'center';
+
+		ctx.fillStyle = 'blue';
+		ctx.fillRect( 0, 0, width, height );
+
+		// scale to fit but don't stretch
+		const scaleFactor = Math.min( 1, baseWidth / textWidth );
+		ctx.translate( width / 2, height / 2 );
+		ctx.scale( scaleFactor, 1 );
+		ctx.fillStyle = 'white';
+		ctx.fillText( name, 0, 0 );
+
+		return ctx.canvas;
+
+	}
+
+	function makePerson( x, labelWidth, size, name, color ) {
+
+		const canvas = makeLabelCanvas( labelWidth, size, name );
+		const texture = new THREE.CanvasTexture( canvas );
+		// because our canvas is likely not a power of 2
+		// in both dimensions set the filtering appropriately.
+		texture.minFilter = THREE.LinearFilter;
+		texture.wrapS = THREE.ClampToEdgeWrapping;
+		texture.wrapT = THREE.ClampToEdgeWrapping;
+
+		const labelMaterial = new THREE.SpriteMaterial( {
+			map: texture,
+			transparent: true,
+		} );
+		const bodyMaterial = new THREE.MeshPhongMaterial( {
+			color,
+			flatShading: true,
+		} );
+
+		const root = new THREE.Object3D();
+		root.position.x = x;
+
+		const body = new THREE.Mesh( bodyGeometry, bodyMaterial );
+		root.add( body );
+		body.position.y = bodyHeight / 2;
+
+		const head = new THREE.Mesh( headGeometry, bodyMaterial );
+		root.add( head );
+		head.position.y = bodyHeight + headRadius * 1.1;
+
+		// if units are meters then 0.01 here makes size
+		// of the label into centimeters.
+		const labelBaseScale = 0.01;
+		const label = new THREE.Sprite( labelMaterial );
+		root.add( label );
+		label.position.y = head.position.y + headRadius + size * labelBaseScale;
+
+		label.scale.x = canvas.width * labelBaseScale;
+		label.scale.y = canvas.height * labelBaseScale;
+
+		scene.add( root );
+		return root;
+
+	}
+
+	makePerson( - 3, 150, 32, 'Purple People Eater', 'purple' );
+	makePerson( - 0, 150, 32, 'Green Machine', 'green' );
+	makePerson( + 3, 150, 32, 'Red Menace', 'red' );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 159 - 140
manual/examples/billboard-labels-w-sprites.html

@@ -35,154 +35,173 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('white');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const bodyRadiusTop = .4;
-  const bodyRadiusBottom = .2;
-  const bodyHeight = 2;
-  const bodyRadialSegments = 6;
-  const bodyGeometry = new THREE.CylinderGeometry(
-      bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-
-  const headRadius = bodyRadiusTop * 0.8;
-  const headLonSegments = 12;
-  const headLatSegments = 5;
-  const headGeometry = new THREE.SphereGeometry(
-      headRadius, headLonSegments, headLatSegments);
-
-  function makeLabelCanvas(baseWidth, size, name) {
-    const borderSize = 2;
-    const ctx = document.createElement('canvas').getContext('2d');
-    const font =  `${size}px bold sans-serif`;
-    ctx.font = font;
-    // measure how long the name will be
-    const textWidth = ctx.measureText(name).width;
-
-    const doubleBorderSize = borderSize * 2;
-    const width = baseWidth + doubleBorderSize;
-    const height = size + doubleBorderSize;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-
-    // need to set font again after resizing canvas
-    ctx.font = font;
-    ctx.textBaseline = 'middle';
-    ctx.textAlign = 'center';
-
-    ctx.fillStyle = 'blue';
-    ctx.fillRect(0, 0, width, height);
-
-    // scale to fit but don't stretch
-    const scaleFactor = Math.min(1, baseWidth / textWidth);
-    ctx.translate(width / 2, height / 2);
-    ctx.scale(scaleFactor, 1);
-    ctx.fillStyle = 'white';
-    ctx.fillText(name, 0, 0);
-
-    return ctx.canvas;
-  }
 
-  function makePerson(x, labelWidth, size, name, color) {
-    const canvas = makeLabelCanvas(labelWidth, size, name);
-    const texture = new THREE.CanvasTexture(canvas);
-    // because our canvas is likely not a power of 2
-    // in both dimensions set the filtering appropriately.
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = THREE.ClampToEdgeWrapping;
-    texture.wrapT = THREE.ClampToEdgeWrapping;
-
-    const labelMaterial = new THREE.SpriteMaterial({
-      map: texture,
-      transparent: true,
-    });
-    const bodyMaterial = new THREE.MeshPhongMaterial({
-      color,
-      flatShading: true,
-    });
-
-    const root = new THREE.Object3D();
-    root.position.x = x;
-
-    const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-    root.add(body);
-    body.position.y = bodyHeight / 2;
-
-    const head = new THREE.Mesh(headGeometry, bodyMaterial);
-    root.add(head);
-    head.position.y = bodyHeight + headRadius * 1.1;
-
-    const label = new THREE.Sprite(labelMaterial);
-    root.add(label);
-    label.position.y = bodyHeight * 4 / 5;
-    label.position.z = bodyRadiusTop * 1.01;
-
-    // if units are meters then 0.01 here makes size
-    // of the label into centimeters.
-    const labelBaseScale = 0.01;
-    label.scale.x = canvas.width  * labelBaseScale;
-    label.scale.y = canvas.height * labelBaseScale;
-
-    scene.add(root);
-    return root;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'white' );
+
+	function addLight( position ) {
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const bodyRadiusTop = .4;
+	const bodyRadiusBottom = .2;
+	const bodyHeight = 2;
+	const bodyRadialSegments = 6;
+	const bodyGeometry = new THREE.CylinderGeometry(
+		bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments );
+
+	const headRadius = bodyRadiusTop * 0.8;
+	const headLonSegments = 12;
+	const headLatSegments = 5;
+	const headGeometry = new THREE.SphereGeometry(
+		headRadius, headLonSegments, headLatSegments );
 
-  makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-  makePerson(-0, 150, 32, 'Green Machine', 'green');
-  makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	function makeLabelCanvas( baseWidth, size, name ) {
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const borderSize = 2;
+		const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+		const font = `${size}px bold sans-serif`;
+		ctx.font = font;
+		// measure how long the name will be
+		const textWidth = ctx.measureText( name ).width;
 
-    renderer.render(scene, camera);
+		const doubleBorderSize = borderSize * 2;
+		const width = baseWidth + doubleBorderSize;
+		const height = size + doubleBorderSize;
+		ctx.canvas.width = width;
+		ctx.canvas.height = height;
 
-    requestAnimationFrame(render);
-  }
+		// need to set font again after resizing canvas
+		ctx.font = font;
+		ctx.textBaseline = 'middle';
+		ctx.textAlign = 'center';
+
+		ctx.fillStyle = 'blue';
+		ctx.fillRect( 0, 0, width, height );
+
+		// scale to fit but don't stretch
+		const scaleFactor = Math.min( 1, baseWidth / textWidth );
+		ctx.translate( width / 2, height / 2 );
+		ctx.scale( scaleFactor, 1 );
+		ctx.fillStyle = 'white';
+		ctx.fillText( name, 0, 0 );
+
+		return ctx.canvas;
+
+	}
+
+	function makePerson( x, labelWidth, size, name, color ) {
+
+		const canvas = makeLabelCanvas( labelWidth, size, name );
+		const texture = new THREE.CanvasTexture( canvas );
+		// because our canvas is likely not a power of 2
+		// in both dimensions set the filtering appropriately.
+		texture.minFilter = THREE.LinearFilter;
+		texture.wrapS = THREE.ClampToEdgeWrapping;
+		texture.wrapT = THREE.ClampToEdgeWrapping;
+
+		const labelMaterial = new THREE.SpriteMaterial( {
+			map: texture,
+			transparent: true,
+		} );
+		const bodyMaterial = new THREE.MeshPhongMaterial( {
+			color,
+			flatShading: true,
+		} );
+
+		const root = new THREE.Object3D();
+		root.position.x = x;
+
+		const body = new THREE.Mesh( bodyGeometry, bodyMaterial );
+		root.add( body );
+		body.position.y = bodyHeight / 2;
+
+		const head = new THREE.Mesh( headGeometry, bodyMaterial );
+		root.add( head );
+		head.position.y = bodyHeight + headRadius * 1.1;
+
+		const label = new THREE.Sprite( labelMaterial );
+		root.add( label );
+		label.position.y = bodyHeight * 4 / 5;
+		label.position.z = bodyRadiusTop * 1.01;
+
+		// if units are meters then 0.01 here makes size
+		// of the label into centimeters.
+		const labelBaseScale = 0.01;
+		label.scale.x = canvas.width * labelBaseScale;
+		label.scale.y = canvas.height * labelBaseScale;
+
+		scene.add( root );
+		return root;
+
+	}
+
+	makePerson( - 3, 150, 32, 'Purple People Eater', 'purple' );
+	makePerson( - 0, 150, 32, 'Green Machine', 'green' );
+	makePerson( + 3, 150, 32, 'Red Menace', 'red' );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 118 - 95
manual/examples/billboard-trees-no-billboards.html

@@ -35,110 +35,133 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 1000;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.minPolarAngle = 0;
-  controls.maxPolarAngle = Math.PI / 2;
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('lightblue');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const trunkRadius = .2;
-  const trunkHeight = 1;
-  const trunkRadialSegments = 12;
-  const trunkGeometry = new THREE.CylinderGeometry(
-      trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments);
-
-  const topRadius = trunkRadius * 4;
-  const topHeight = trunkHeight * 2;
-  const topSegments = 12;
-  const topGeometry = new THREE.ConeGeometry(
-      topRadius, topHeight, topSegments);
-
-  const trunkMaterial = new THREE.MeshPhongMaterial({color: 'brown'});
-  const topMaterial = new THREE.MeshPhongMaterial({color: 'green'});
-
-  function makeTree(x, z) {
-    const root = new THREE.Object3D();
-    const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
-    trunk.position.y = trunkHeight / 2;
-    root.add(trunk);
-
-    const top = new THREE.Mesh(topGeometry, topMaterial);
-    top.position.y = trunkHeight + topHeight / 2;
-    root.add(top);
-
-    root.position.set(x, 0, z);
-    scene.add(root);
-
-    return root;
-  }
 
-  for (let z = -50; z <= 50; z += 10) {
-    for (let x = -50; x <= 50; x += 10) {
-      makeTree(x, z);
-    }
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  // add ground
-  {
-    const size = 400;
-    const geometry = new THREE.PlaneGeometry(size, size);
-    const material = new THREE.MeshPhongMaterial({color: 'gray'});
-    const mesh = new THREE.Mesh(geometry, material);
-    mesh.rotation.x = Math.PI * -0.5;
-    scene.add(mesh);
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 1000;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.minPolarAngle = 0;
+	controls.maxPolarAngle = Math.PI / 2;
+	controls.update();
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'lightblue' );
 
-    renderer.render(scene, camera);
+	function addLight( position ) {
 
-    requestAnimationFrame(render);
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const trunkRadius = .2;
+	const trunkHeight = 1;
+	const trunkRadialSegments = 12;
+	const trunkGeometry = new THREE.CylinderGeometry(
+		trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments );
+
+	const topRadius = trunkRadius * 4;
+	const topHeight = trunkHeight * 2;
+	const topSegments = 12;
+	const topGeometry = new THREE.ConeGeometry(
+		topRadius, topHeight, topSegments );
+
+	const trunkMaterial = new THREE.MeshPhongMaterial( { color: 'brown' } );
+	const topMaterial = new THREE.MeshPhongMaterial( { color: 'green' } );
+
+	function makeTree( x, z ) {
+
+		const root = new THREE.Object3D();
+		const trunk = new THREE.Mesh( trunkGeometry, trunkMaterial );
+		trunk.position.y = trunkHeight / 2;
+		root.add( trunk );
+
+		const top = new THREE.Mesh( topGeometry, topMaterial );
+		top.position.y = trunkHeight + topHeight / 2;
+		root.add( top );
+
+		root.position.set( x, 0, z );
+		scene.add( root );
+
+		return root;
+
+	}
+
+	for ( let z = - 50; z <= 50; z += 10 ) {
+
+		for ( let x = - 50; x <= 50; x += 10 ) {
+
+			makeTree( x, z );
+
+		}
+
+	}
+
+	// add ground
+	{
+
+		const size = 400;
+		const geometry = new THREE.PlaneGeometry( size, size );
+		const material = new THREE.MeshPhongMaterial( { color: 'gray' } );
+		const mesh = new THREE.Mesh( geometry, material );
+		mesh.rotation.x = Math.PI * - 0.5;
+		scene.add( mesh );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 179 - 150
manual/examples/billboard-trees-static-billboards.html

@@ -35,180 +35,209 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 1000;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.minPolarAngle = 0;
-  controls.maxPolarAngle = Math.PI / 2;
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const trunkRadius = .2;
-  const trunkHeight = 1;
-  const trunkRadialSegments = 12;
-  const trunkGeometry = new THREE.CylinderGeometry(
-      trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments);
-
-  const topRadius = trunkRadius * 4;
-  const topHeight = trunkHeight * 2;
-  const topSegments = 12;
-  const topGeometry = new THREE.ConeGeometry(
-      topRadius, topHeight, topSegments);
-
-  const trunkMaterial = new THREE.MeshPhongMaterial({color: 'brown'});
-  const topMaterial = new THREE.MeshPhongMaterial({color: 'green'});
-
-  function makeTree(x, z) {
-    const root = new THREE.Object3D();
-    const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
-    trunk.position.y = trunkHeight / 2;
-    root.add(trunk);
-
-    const top = new THREE.Mesh(topGeometry, topMaterial);
-    top.position.y = trunkHeight + topHeight / 2;
-    root.add(top);
-
-    root.position.set(x, 0, z);
-    scene.add(root);
-
-    return root;
-  }
 
-  function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-    const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-    const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-    const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-    camera.position.copy(boxCenter);
-    camera.position.z += distance;
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 1000;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
 
-    // pick some near and far values for the frustum that
-    // will contain the box.
-    camera.near = boxSize / 100;
-    camera.far = boxSize * 100;
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.minPolarAngle = 0;
+	controls.maxPolarAngle = Math.PI / 2;
+	controls.update();
 
-    camera.updateProjectionMatrix();
-  }
+	const scene = new THREE.Scene();
 
-  function makeSpriteTexture(textureSize, obj) {
-    const rt = new THREE.WebGLRenderTarget(textureSize, textureSize);
+	function addLight( position ) {
 
-    const aspect = 1;  // because the render target is square
-    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
 
-    scene.add(obj);
+	}
 
-    // compute the box that contains obj
-    const box = new THREE.Box3().setFromObject(obj);
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
 
-    const boxSize = box.getSize(new THREE.Vector3());
-    const boxCenter = box.getCenter(new THREE.Vector3());
+	const trunkRadius = .2;
+	const trunkHeight = 1;
+	const trunkRadialSegments = 12;
+	const trunkGeometry = new THREE.CylinderGeometry(
+		trunkRadius, trunkRadius, trunkHeight, trunkRadialSegments );
 
-    // set the camera to frame the box
-    const fudge = 1.1;
-    const size = Math.max(...boxSize.toArray()) * fudge;
-    frameArea(size, size, boxCenter, camera);
+	const topRadius = trunkRadius * 4;
+	const topHeight = trunkHeight * 2;
+	const topSegments = 12;
+	const topGeometry = new THREE.ConeGeometry(
+		topRadius, topHeight, topSegments );
 
-    renderer.autoClear = false;
-    renderer.setRenderTarget(rt);
-    renderer.render(scene, camera);
-    renderer.setRenderTarget(null);
-    renderer.autoClear = true;
+	const trunkMaterial = new THREE.MeshPhongMaterial( { color: 'brown' } );
+	const topMaterial = new THREE.MeshPhongMaterial( { color: 'green' } );
 
-    scene.remove(obj);
+	function makeTree( x, z ) {
 
-    return {
-      offset: boxCenter.multiplyScalar(fudge),
-      scale: size,
-      texture: rt.texture,
-    };
-  }
+		const root = new THREE.Object3D();
+		const trunk = new THREE.Mesh( trunkGeometry, trunkMaterial );
+		trunk.position.y = trunkHeight / 2;
+		root.add( trunk );
 
-  // make billboard texture
-  const tree = makeTree(0, 0);
-  const facadeSize = 64;
-  const treeSpriteInfo = makeSpriteTexture(facadeSize, tree);
-
-  function makeSprite(spriteInfo, x, z) {
-    const {texture, offset, scale} = spriteInfo;
-    const mat = new THREE.SpriteMaterial({
-      map: texture,
-      transparent: true,
-    });
-    const sprite = new THREE.Sprite(mat);
-    scene.add(sprite);
-    sprite.position.set(
-        offset.x + x,
-        offset.y,
-        offset.z + z);
-    sprite.scale.set(scale, scale, scale);
-  }
+		const top = new THREE.Mesh( topGeometry, topMaterial );
+		top.position.y = trunkHeight + topHeight / 2;
+		root.add( top );
 
-  for (let z = -50; z <= 50; z += 10) {
-    for (let x = -50; x <= 50; x += 10) {
-      makeSprite(treeSpriteInfo, x, z);
-    }
-  }
+		root.position.set( x, 0, z );
+		scene.add( root );
 
-  scene.background = new THREE.Color('lightblue');
+		return root;
 
-  {
-    const size = 400;
-    const geometry = new THREE.PlaneGeometry(size, size);
-    const material = new THREE.MeshPhongMaterial({color: 'gray'});
-    const mesh = new THREE.Mesh(geometry, material);
-    mesh.rotation.x = Math.PI * -0.5;
-    scene.add(mesh);
-  }
+	}
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	function frameArea( sizeToFitOnScreen, boxSize, boxCenter, camera ) {
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
+		const halfFovY = THREE.MathUtils.degToRad( camera.fov * .5 );
+		const distance = halfSizeToFitOnScreen / Math.tan( halfFovY );
 
-    renderer.render(scene, camera);
+		camera.position.copy( boxCenter );
+		camera.position.z += distance;
 
-    requestAnimationFrame(render);
-  }
+		// pick some near and far values for the frustum that
+		// will contain the box.
+		camera.near = boxSize / 100;
+		camera.far = boxSize * 100;
+
+		camera.updateProjectionMatrix();
+
+	}
+
+	function makeSpriteTexture( textureSize, obj ) {
+
+		const rt = new THREE.WebGLRenderTarget( textureSize, textureSize );
+
+		const aspect = 1; // because the render target is square
+		const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+
+		scene.add( obj );
+
+		// compute the box that contains obj
+		const box = new THREE.Box3().setFromObject( obj );
+
+		const boxSize = box.getSize( new THREE.Vector3() );
+		const boxCenter = box.getCenter( new THREE.Vector3() );
+
+		// set the camera to frame the box
+		const fudge = 1.1;
+		const size = Math.max( ...boxSize.toArray() ) * fudge;
+		frameArea( size, size, boxCenter, camera );
+
+		renderer.autoClear = false;
+		renderer.setRenderTarget( rt );
+		renderer.render( scene, camera );
+		renderer.setRenderTarget( null );
+		renderer.autoClear = true;
+
+		scene.remove( obj );
+
+		return {
+			offset: boxCenter.multiplyScalar( fudge ),
+			scale: size,
+			texture: rt.texture,
+		};
+
+	}
+
+	// make billboard texture
+	const tree = makeTree( 0, 0 );
+	const facadeSize = 64;
+	const treeSpriteInfo = makeSpriteTexture( facadeSize, tree );
+
+	function makeSprite( spriteInfo, x, z ) {
+
+		const { texture, offset, scale } = spriteInfo;
+		const mat = new THREE.SpriteMaterial( {
+			map: texture,
+			transparent: true,
+		} );
+		const sprite = new THREE.Sprite( mat );
+		scene.add( sprite );
+		sprite.position.set(
+			offset.x + x,
+			offset.y,
+			offset.z + z );
+		sprite.scale.set( scale, scale, scale );
+
+	}
+
+	for ( let z = - 50; z <= 50; z += 10 ) {
+
+		for ( let x = - 50; x <= 50; x += 10 ) {
+
+			makeSprite( treeSpriteInfo, x, z );
+
+		}
+
+	}
+
+	scene.background = new THREE.Color( 'lightblue' );
+
+	{
+
+		const size = 400;
+		const geometry = new THREE.PlaneGeometry( size, size );
+		const material = new THREE.MeshPhongMaterial( { color: 'gray' } );
+		const mesh = new THREE.Mesh( geometry, material );
+		mesh.rotation.x = Math.PI * - 0.5;
+		scene.add( mesh );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 151 - 116
manual/examples/cameras-logarithmic-depth-buffer.html

@@ -35,133 +35,168 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({
-    canvas,
-    logarithmicDepthBuffer: true,
-    antialias: true
-  });
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.00001;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(10, 6, 10);
-
-  class MinMaxGUIHelper {
-    constructor(obj, minProp, maxProp, minDif) {
-      this.obj = obj;
-      this.minProp = minProp;
-      this.maxProp = maxProp;
-      this.minDif = minDif;
-    }
-    get min() {
-      return this.obj[this.minProp];
-    }
-    set min(v) {
-      this.obj[this.minProp] = v;
-      this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-    }
-    get max() {
-      return this.obj[this.maxProp];
-    }
-    set max(v) {
-      this.obj[this.maxProp] = v;
-      this.min = this.min;  // this will call the min setter
-    }
-  }
 
-  function updateCamera() {
-    camera.updateProjectionMatrix();
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( {
+		canvas,
+		logarithmicDepthBuffer: true,
+		antialias: true
+	} );
+	renderer.useLegacyLights = false;
+	const fov = 45;
+	const aspect = 2; // the canvas default
+	const near = 0.00001;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 10, 6, 10 );
 
-  const gui = new GUI();
-  gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-  const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-  gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-  gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-
-  {
-    const planeSize = 40;
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/checker.png');
-    texture.wrapS = THREE.RepeatWrapping;
-    texture.wrapT = THREE.RepeatWrapping;
-    texture.magFilter = THREE.NearestFilter;
-    const repeats = planeSize / 2;
-    texture.repeat.set(repeats, repeats);
-
-    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-    const planeMat = new THREE.MeshPhongMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    mesh.rotation.x = Math.PI * -.5;
-    scene.add(mesh);
-  }
-  {
-    const sphereRadius = 3;
-    const sphereWidthDivisions = 32;
-    const sphereHeightDivisions = 16;
-    const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-    const numSpheres = 20;
-    for (let i = 0; i < numSpheres; ++i) {
-      const sphereMat = new THREE.MeshPhongMaterial();
-      sphereMat.color.setHSL(i * .73, 1, 0.5);
-      const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-      mesh.position.set(-sphereRadius - 1, sphereRadius + 2, i * sphereRadius * -2.2);
-      scene.add(mesh);
-    }
-  }
+	class MinMaxGUIHelper {
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(0, 10, 0);
-    light.target.position.set(-5, 0, 0);
-    scene.add(light);
-    scene.add(light.target);
-  }
+		constructor( obj, minProp, maxProp, minDif ) {
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+			this.obj = obj;
+			this.minProp = minProp;
+			this.maxProp = maxProp;
+			this.minDif = minDif;
 
-  function render() {
+		}
+		get min() {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+			return this.obj[ this.minProp ];
 
-    renderer.render(scene, camera);
+		}
+		set min( v ) {
 
-    requestAnimationFrame(render);
-  }
+			this.obj[ this.minProp ] = v;
+			this.obj[ this.maxProp ] = Math.max( this.obj[ this.maxProp ], v + this.minDif );
+
+		}
+		get max() {
+
+			return this.obj[ this.maxProp ];
+
+		}
+		set max( v ) {
+
+			this.obj[ this.maxProp ] = v;
+			this.min = this.min; // this will call the min setter
+
+		}
+
+	}
+
+	function updateCamera() {
+
+		camera.updateProjectionMatrix();
+
+	}
+
+	const gui = new GUI();
+	gui.add( camera, 'fov', 1, 180 ).onChange( updateCamera );
+	const minMaxGUIHelper = new MinMaxGUIHelper( camera, 'near', 'far', 0.1 );
+	gui.add( minMaxGUIHelper, 'min', 0.00001, 50, 0.00001 ).name( 'near' ).onChange( updateCamera );
+	gui.add( minMaxGUIHelper, 'max', 0.1, 50, 0.1 ).name( 'far' ).onChange( updateCamera );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+
+	{
+
+		const planeSize = 40;
+
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/checker.png' );
+		texture.wrapS = THREE.RepeatWrapping;
+		texture.wrapT = THREE.RepeatWrapping;
+		texture.magFilter = THREE.NearestFilter;
+		texture.colorSpace = THREE.SRGBColorSpace;
+		const repeats = planeSize / 2;
+		texture.repeat.set( repeats, repeats );
+
+		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+		const planeMat = new THREE.MeshPhongMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		mesh.rotation.x = Math.PI * - .5;
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const sphereRadius = 3;
+		const sphereWidthDivisions = 32;
+		const sphereHeightDivisions = 16;
+		const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
+		const numSpheres = 20;
+		for ( let i = 0; i < numSpheres; ++ i ) {
+
+			const sphereMat = new THREE.MeshPhongMaterial();
+			sphereMat.color.setHSL( i * .73, 1, 0.5 );
+			const mesh = new THREE.Mesh( sphereGeo, sphereMat );
+			mesh.position.set( - sphereRadius - 1, sphereRadius + 2, i * sphereRadius * - 2.2 );
+			scene.add( mesh );
+
+		}
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( 0, 10, 0 );
+		light.target.position.set( - 5, 0, 0 );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 208 - 170
manual/examples/cameras-orthographic-2-scenes.html

@@ -51,199 +51,237 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const view1Elem = document.querySelector('#view1');
-  const view2Elem = document.querySelector('#view2');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const size = 1;
-  const near = 5;
-  const far = 50;
-  const camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far);
-  camera.zoom = 0.2;
-  camera.position.set(0, 10, 20);
-
-  const cameraHelper = new THREE.CameraHelper(camera);
-
-  class MinMaxGUIHelper {
-    constructor(obj, minProp, maxProp, minDif) {
-      this.obj = obj;
-      this.minProp = minProp;
-      this.maxProp = maxProp;
-      this.minDif = minDif;
-    }
-    get min() {
-      return this.obj[this.minProp];
-    }
-    set min(v) {
-      this.obj[this.minProp] = v;
-      this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-    }
-    get max() {
-      return this.obj[this.maxProp];
-    }
-    set max(v) {
-      this.obj[this.maxProp] = v;
-      this.min = this.min;  // this will call the min setter
-    }
-  }
 
-  const gui = new GUI();
-  gui.add(camera, 'zoom', 0.01, 1, 0.01).listen();
-  const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-  gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
-  gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-
-  const controls = new OrbitControls(camera, view1Elem);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const camera2 = new THREE.PerspectiveCamera(
-    60,  // fov
-    2,   // aspect
-    0.1, // near
-    500, // far
-  );
-  camera2.position.set(16, 28, 40);
-  camera2.lookAt(0, 5, 0);
-
-  const controls2 = new OrbitControls(camera2, view2Elem);
-  controls2.target.set(0, 5, 0);
-  controls2.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-  scene.add(cameraHelper);
-
-  {
-    const planeSize = 40;
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/checker.png');
-    texture.wrapS = THREE.RepeatWrapping;
-    texture.wrapT = THREE.RepeatWrapping;
-    texture.magFilter = THREE.NearestFilter;
-    const repeats = planeSize / 2;
-    texture.repeat.set(repeats, repeats);
-
-    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-    const planeMat = new THREE.MeshPhongMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    mesh.rotation.x = Math.PI * -.5;
-    scene.add(mesh);
-  }
-  {
-    const cubeSize = 4;
-    const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-    const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-    const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-    mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-    scene.add(mesh);
-  }
-  {
-    const sphereRadius = 3;
-    const sphereWidthDivisions = 32;
-    const sphereHeightDivisions = 16;
-    const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-    const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-    scene.add(mesh);
-  }
+	const canvas = document.querySelector( '#c' );
+	const view1Elem = document.querySelector( '#view1' );
+	const view2Elem = document.querySelector( '#view2' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(0, 10, 0);
-    light.target.position.set(-5, 0, 0);
-    scene.add(light);
-    scene.add(light.target);
-  }
+	const size = 1;
+	const near = 5;
+	const far = 50;
+	const camera = new THREE.OrthographicCamera( - size, size, size, - size, near, far );
+	camera.zoom = 0.2;
+	camera.position.set( 0, 10, 20 );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const cameraHelper = new THREE.CameraHelper( camera );
 
-  function setScissorForElement(elem) {
-    const canvasRect = canvas.getBoundingClientRect();
-    const elemRect = elem.getBoundingClientRect();
+	class MinMaxGUIHelper {
 
-    // compute a canvas relative rectangle
-    const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
-    const left = Math.max(0, elemRect.left - canvasRect.left);
-    const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
-    const top = Math.max(0, elemRect.top - canvasRect.top);
+		constructor( obj, minProp, maxProp, minDif ) {
 
-    const width = Math.min(canvasRect.width, right - left);
-    const height = Math.min(canvasRect.height, bottom - top);
+			this.obj = obj;
+			this.minProp = minProp;
+			this.maxProp = maxProp;
+			this.minDif = minDif;
 
-    // setup the scissor to only render to that part of the canvas
-    const positiveYUpBottom = canvasRect.height - bottom;
-    renderer.setScissor(left, positiveYUpBottom, width, height);
-    renderer.setViewport(left, positiveYUpBottom, width, height);
+		}
+		get min() {
 
-    // return the aspect
-    return width / height;
-  }
+			return this.obj[ this.minProp ];
 
-  function render() {
+		}
+		set min( v ) {
 
-    resizeRendererToDisplaySize(renderer);
+			this.obj[ this.minProp ] = v;
+			this.obj[ this.maxProp ] = Math.max( this.obj[ this.maxProp ], v + this.minDif );
 
-    // turn on the scissor
-    renderer.setScissorTest(true);
+		}
+		get max() {
 
-    // render the original view
-    {
-      const aspect = setScissorForElement(view1Elem);
+			return this.obj[ this.maxProp ];
 
-      // update the camera for this aspect
-      camera.left   = -aspect;
-      camera.right  =  aspect;
-      camera.updateProjectionMatrix();
-      cameraHelper.update();
+		}
+		set max( v ) {
 
-      // don't draw the camera helper in the original view
-      cameraHelper.visible = false;
+			this.obj[ this.maxProp ] = v;
+			this.min = this.min; // this will call the min setter
 
-      scene.background.set(0x000000);
-      renderer.render(scene, camera);
-    }
+		}
 
-    // render from the 2nd camera
-    {
-      const aspect = setScissorForElement(view2Elem);
+	}
 
-      // update the camera for this aspect
-      camera2.aspect = aspect;
-      camera2.updateProjectionMatrix();
+	const gui = new GUI();
+	gui.add( camera, 'zoom', 0.01, 1, 0.01 ).listen();
+	const minMaxGUIHelper = new MinMaxGUIHelper( camera, 'near', 'far', 0.1 );
+	gui.add( minMaxGUIHelper, 'min', 0.1, 50, 0.1 ).name( 'near' );
+	gui.add( minMaxGUIHelper, 'max', 0.1, 50, 0.1 ).name( 'far' );
 
-      // draw the camera helper in the 2nd view
-      cameraHelper.visible = true;
+	const controls = new OrbitControls( camera, view1Elem );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
 
-      scene.background.set(0x000040);
-      renderer.render(scene, camera2);
-    }
+	const camera2 = new THREE.PerspectiveCamera(
+		60, // fov
+		2, // aspect
+		0.1, // near
+		500, // far
+	);
+	camera2.position.set( 16, 28, 40 );
+	camera2.lookAt( 0, 5, 0 );
 
-    requestAnimationFrame(render);
-  }
+	const controls2 = new OrbitControls( camera2, view2Elem );
+	controls2.target.set( 0, 5, 0 );
+	controls2.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+	scene.add( cameraHelper );
+
+	{
+
+		const planeSize = 40;
+
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/checker.png' );
+		texture.wrapS = THREE.RepeatWrapping;
+		texture.wrapT = THREE.RepeatWrapping;
+		texture.magFilter = THREE.NearestFilter;
+		texture.colorSpace = THREE.SRGBColorSpace;
+		const repeats = planeSize / 2;
+		texture.repeat.set( repeats, repeats );
+
+		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+		const planeMat = new THREE.MeshPhongMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		mesh.rotation.x = Math.PI * - .5;
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const cubeSize = 4;
+		const cubeGeo = new THREE.BoxGeometry( cubeSize, cubeSize, cubeSize );
+		const cubeMat = new THREE.MeshPhongMaterial( { color: '#8AC' } );
+		const mesh = new THREE.Mesh( cubeGeo, cubeMat );
+		mesh.position.set( cubeSize + 1, cubeSize / 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const sphereRadius = 3;
+		const sphereWidthDivisions = 32;
+		const sphereHeightDivisions = 16;
+		const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
+		const sphereMat = new THREE.MeshPhongMaterial( { color: '#CA8' } );
+		const mesh = new THREE.Mesh( sphereGeo, sphereMat );
+		mesh.position.set( - sphereRadius - 1, sphereRadius + 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( 0, 10, 0 );
+		light.target.position.set( - 5, 0, 0 );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function setScissorForElement( elem ) {
+
+		const canvasRect = canvas.getBoundingClientRect();
+		const elemRect = elem.getBoundingClientRect();
+
+		// compute a canvas relative rectangle
+		const right = Math.min( elemRect.right, canvasRect.right ) - canvasRect.left;
+		const left = Math.max( 0, elemRect.left - canvasRect.left );
+		const bottom = Math.min( elemRect.bottom, canvasRect.bottom ) - canvasRect.top;
+		const top = Math.max( 0, elemRect.top - canvasRect.top );
+
+		const width = Math.min( canvasRect.width, right - left );
+		const height = Math.min( canvasRect.height, bottom - top );
+
+		// setup the scissor to only render to that part of the canvas
+		const positiveYUpBottom = canvasRect.height - bottom;
+		renderer.setScissor( left, positiveYUpBottom, width, height );
+		renderer.setViewport( left, positiveYUpBottom, width, height );
+
+		// return the aspect
+		return width / height;
+
+	}
+
+	function render() {
+
+		resizeRendererToDisplaySize( renderer );
+
+		// turn on the scissor
+		renderer.setScissorTest( true );
+
+		// render the original view
+		{
+
+			const aspect = setScissorForElement( view1Elem );
+
+			// update the camera for this aspect
+			camera.left = - aspect;
+			camera.right = aspect;
+			camera.updateProjectionMatrix();
+			cameraHelper.update();
+
+			// don't draw the camera helper in the original view
+			cameraHelper.visible = false;
+
+			scene.background.set( 0x000000 );
+			renderer.render( scene, camera );
+
+		}
+
+		// render from the 2nd camera
+		{
+
+			const aspect = setScissorForElement( view2Elem );
+
+			// update the camera for this aspect
+			camera2.aspect = aspect;
+			camera2.updateProjectionMatrix();
+
+			// draw the camera helper in the 2nd view
+			cameraHelper.visible = true;
+
+			scene.background.set( 0x000040 );
+			renderer.render( scene, camera2 );
+
+		}
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 96 - 80
manual/examples/cameras-orthographic-canvas-top-left-origin.html

@@ -48,97 +48,113 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const left = 0;
-  const right = 300;  // default canvas size
-  const top = 0;
-  const bottom = 150;  // defautl canvas size
-  const near = -1;
-  const far = 1;
-  const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
-  camera.zoom = 1;
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-
-  const loader = new THREE.TextureLoader();
-  const textures = [
-    loader.load('resources/images/flower-1.jpg'),
-    loader.load('resources/images/flower-2.jpg'),
-    loader.load('resources/images/flower-3.jpg'),
-    loader.load('resources/images/flower-4.jpg'),
-    loader.load('resources/images/flower-5.jpg'),
-    loader.load('resources/images/flower-6.jpg'),
-  ];
-  const planeSize = 256;
-  const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-  const planes = textures.map((texture) => {
-    const planePivot = new THREE.Object3D();
-    scene.add(planePivot);
-    texture.magFilter = THREE.NearestFilter;
-    const planeMat = new THREE.MeshBasicMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    planePivot.add(mesh);
-    // move plane so top left corner is origin
-    mesh.position.set(planeSize / 2, planeSize / 2, 0);
-    return planePivot;
-  });
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
 
-  function render(time) {
-    time *= 0.001;  // convert to seconds;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      camera.right = canvas.width;
-      camera.bottom = canvas.height;
-      camera.updateProjectionMatrix();
-    }
+	const left = 0;
+	const right = 300; // default canvas size
+	const top = 0;
+	const bottom = 150; // defautl canvas size
+	const near = - 1;
+	const far = 1;
+	const camera = new THREE.OrthographicCamera( left, right, top, bottom, near, far );
+	camera.zoom = 1;
 
-    const distAcross = Math.max(20, canvas.width - planeSize);
-    const distDown = Math.max(20, canvas.height - planeSize);
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
 
-    // total distance to move across and back
-    const xRange = distAcross * 2;
-    const yRange = distDown * 2;
-    const speed = 180;
+	const loader = new THREE.TextureLoader();
+	const textures = [
+		loader.load( 'resources/images/flower-1.jpg' ),
+		loader.load( 'resources/images/flower-2.jpg' ),
+		loader.load( 'resources/images/flower-3.jpg' ),
+		loader.load( 'resources/images/flower-4.jpg' ),
+		loader.load( 'resources/images/flower-5.jpg' ),
+		loader.load( 'resources/images/flower-6.jpg' ),
+	];
+	const planeSize = 256;
+	const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+	const planes = textures.map( ( texture ) => {
 
-    planes.forEach((plane, ndx) => {
-      // compute a unique time for each plane
-      const t = time * speed + ndx * 300;
+		const planePivot = new THREE.Object3D();
+		scene.add( planePivot );
+		texture.magFilter = THREE.NearestFilter;
+		const planeMat = new THREE.MeshBasicMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		planePivot.add( mesh );
+		// move plane so top left corner is origin
+		mesh.position.set( planeSize / 2, planeSize / 2, 0 );
+		return planePivot;
 
-      // get a value between 0 and range
-      const xt = t % xRange;
-      const yt = t % yRange;
+	} );
 
-      // set our position going forward if 0 to half of range
-      // and backward if half of range to range
-      const x = xt < distAcross ? xt : xRange - xt;
-      const y = yt < distDown   ? yt : yRange - yt;
+	function resizeRendererToDisplaySize( renderer ) {
 
-      plane.position.set(x, y, 0);
-    });
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
 
-    renderer.render(scene, camera);
+			renderer.setSize( width, height, false );
 
-    requestAnimationFrame(render);
-  }
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001; // convert to seconds;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			camera.right = canvas.width;
+			camera.bottom = canvas.height;
+			camera.updateProjectionMatrix();
+
+		}
+
+		const distAcross = Math.max( 20, canvas.width - planeSize );
+		const distDown = Math.max( 20, canvas.height - planeSize );
+
+		// total distance to move across and back
+		const xRange = distAcross * 2;
+		const yRange = distDown * 2;
+		const speed = 180;
+
+		planes.forEach( ( plane, ndx ) => {
+
+			// compute a unique time for each plane
+			const t = time * speed + ndx * 300;
+
+			// get a value between 0 and range
+			const xt = t % xRange;
+			const yt = t % yRange;
+
+			// set our position going forward if 0 to half of range
+			// and backward if half of range to range
+			const x = xt < distAcross ? xt : xRange - xt;
+			const y = yt < distDown ? yt : yRange - yt;
+
+			plane.position.set( x, y, 0 );
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 208 - 170
manual/examples/cameras-perspective-2-scenes.html

@@ -51,201 +51,239 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const view1Elem = document.querySelector('#view1');
-  const view2Elem = document.querySelector('#view2');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 5;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 10, 20);
-
-  const cameraHelper = new THREE.CameraHelper(camera);
-
-  class MinMaxGUIHelper {
-    constructor(obj, minProp, maxProp, minDif) {
-      this.obj = obj;
-      this.minProp = minProp;
-      this.maxProp = maxProp;
-      this.minDif = minDif;
-    }
-    get min() {
-      return this.obj[this.minProp];
-    }
-    set min(v) {
-      this.obj[this.minProp] = v;
-      this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-    }
-    get max() {
-      return this.obj[this.maxProp];
-    }
-    set max(v) {
-      this.obj[this.maxProp] = v;
-      this.min = this.min;  // this will call the min setter
-    }
-  }
 
-  const gui = new GUI();
-  gui.add(camera, 'fov', 1, 180);
-  const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-  gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near');
-  gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far');
-
-  const controls = new OrbitControls(camera, view1Elem);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const camera2 = new THREE.PerspectiveCamera(
-    60,  // fov
-    2,   // aspect
-    0.1, // near
-    500, // far
-  );
-  camera2.position.set(40, 10, 30);
-  camera2.lookAt(0, 5, 0);
-
-  const controls2 = new OrbitControls(camera2, view2Elem);
-  controls2.target.set(0, 5, 0);
-  controls2.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-  scene.add(cameraHelper);
-
-  {
-    const planeSize = 40;
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/checker.png');
-    texture.wrapS = THREE.RepeatWrapping;
-    texture.wrapT = THREE.RepeatWrapping;
-    texture.magFilter = THREE.NearestFilter;
-    const repeats = planeSize / 2;
-    texture.repeat.set(repeats, repeats);
-
-    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-    const planeMat = new THREE.MeshPhongMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    mesh.rotation.x = Math.PI * -.5;
-    scene.add(mesh);
-  }
-  {
-    const cubeSize = 4;
-    const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-    const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-    const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-    mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-    scene.add(mesh);
-  }
-  {
-    const sphereRadius = 3;
-    const sphereWidthDivisions = 32;
-    const sphereHeightDivisions = 16;
-    const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-    const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-    scene.add(mesh);
-  }
+	const canvas = document.querySelector( '#c' );
+	const view1Elem = document.querySelector( '#view1' );
+	const view2Elem = document.querySelector( '#view2' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(0, 10, 0);
-    light.target.position.set(-5, 0, 0);
-    scene.add(light);
-    scene.add(light.target);
-  }
+	const fov = 45;
+	const aspect = 2; // the canvas default
+	const near = 5;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 10, 20 );
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const cameraHelper = new THREE.CameraHelper( camera );
 
-  function setScissorForElement(elem) {
-    const canvasRect = canvas.getBoundingClientRect();
-    const elemRect = elem.getBoundingClientRect();
+	class MinMaxGUIHelper {
 
-    // compute a canvas relative rectangle
-    const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
-    const left = Math.max(0, elemRect.left - canvasRect.left);
-    const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
-    const top = Math.max(0, elemRect.top - canvasRect.top);
+		constructor( obj, minProp, maxProp, minDif ) {
 
-    const width = Math.min(canvasRect.width, right - left);
-    const height = Math.min(canvasRect.height, bottom - top);
+			this.obj = obj;
+			this.minProp = minProp;
+			this.maxProp = maxProp;
+			this.minDif = minDif;
 
-    // setup the scissor to only render to that part of the canvas
-    const positiveYUpBottom = canvasRect.height - bottom;
-    renderer.setScissor(left, positiveYUpBottom, width, height);
-    renderer.setViewport(left, positiveYUpBottom, width, height);
+		}
+		get min() {
 
-    // return the aspect
-    return width / height;
-  }
+			return this.obj[ this.minProp ];
 
-  function render() {
+		}
+		set min( v ) {
 
-    resizeRendererToDisplaySize(renderer);
+			this.obj[ this.minProp ] = v;
+			this.obj[ this.maxProp ] = Math.max( this.obj[ this.maxProp ], v + this.minDif );
 
-    // turn on the scissor
-    renderer.setScissorTest(true);
+		}
+		get max() {
 
-    // render the original view
-    {
-      const aspect = setScissorForElement(view1Elem);
+			return this.obj[ this.maxProp ];
 
-      // adjust the camera for this aspect
-      camera.aspect = aspect;
-      camera.updateProjectionMatrix();
-      cameraHelper.update();
+		}
+		set max( v ) {
 
-      // don't draw the camera helper in the original view
-      cameraHelper.visible = false;
+			this.obj[ this.maxProp ] = v;
+			this.min = this.min; // this will call the min setter
 
-      scene.background.set(0x000000);
+		}
 
-      // render
-      renderer.render(scene, camera);
-    }
+	}
 
-    // render from the 2nd camera
-    {
-      const aspect = setScissorForElement(view2Elem);
+	const gui = new GUI();
+	gui.add( camera, 'fov', 1, 180 );
+	const minMaxGUIHelper = new MinMaxGUIHelper( camera, 'near', 'far', 0.1 );
+	gui.add( minMaxGUIHelper, 'min', 0.1, 50, 0.1 ).name( 'near' );
+	gui.add( minMaxGUIHelper, 'max', 0.1, 50, 0.1 ).name( 'far' );
 
-      // adjust the camera for this aspect
-      camera2.aspect = aspect;
-      camera2.updateProjectionMatrix();
+	const controls = new OrbitControls( camera, view1Elem );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
 
-      // draw the camera helper in the 2nd view
-      cameraHelper.visible = true;
+	const camera2 = new THREE.PerspectiveCamera(
+		60, // fov
+		2, // aspect
+		0.1, // near
+		500, // far
+	);
+	camera2.position.set( 40, 10, 30 );
+	camera2.lookAt( 0, 5, 0 );
 
-      scene.background.set(0x000040);
+	const controls2 = new OrbitControls( camera2, view2Elem );
+	controls2.target.set( 0, 5, 0 );
+	controls2.update();
 
-      renderer.render(scene, camera2);
-    }
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+	scene.add( cameraHelper );
 
-    requestAnimationFrame(render);
-  }
+	{
+
+		const planeSize = 40;
+
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/checker.png' );
+		texture.wrapS = THREE.RepeatWrapping;
+		texture.wrapT = THREE.RepeatWrapping;
+		texture.magFilter = THREE.NearestFilter;
+		texture.colorSpace = THREE.SRGBColorSpace;
+		const repeats = planeSize / 2;
+		texture.repeat.set( repeats, repeats );
+
+		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+		const planeMat = new THREE.MeshPhongMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		mesh.rotation.x = Math.PI * - .5;
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const cubeSize = 4;
+		const cubeGeo = new THREE.BoxGeometry( cubeSize, cubeSize, cubeSize );
+		const cubeMat = new THREE.MeshPhongMaterial( { color: '#8AC' } );
+		const mesh = new THREE.Mesh( cubeGeo, cubeMat );
+		mesh.position.set( cubeSize + 1, cubeSize / 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const sphereRadius = 3;
+		const sphereWidthDivisions = 32;
+		const sphereHeightDivisions = 16;
+		const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
+		const sphereMat = new THREE.MeshPhongMaterial( { color: '#CA8' } );
+		const mesh = new THREE.Mesh( sphereGeo, sphereMat );
+		mesh.position.set( - sphereRadius - 1, sphereRadius + 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( 0, 10, 0 );
+		light.target.position.set( - 5, 0, 0 );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function setScissorForElement( elem ) {
+
+		const canvasRect = canvas.getBoundingClientRect();
+		const elemRect = elem.getBoundingClientRect();
+
+		// compute a canvas relative rectangle
+		const right = Math.min( elemRect.right, canvasRect.right ) - canvasRect.left;
+		const left = Math.max( 0, elemRect.left - canvasRect.left );
+		const bottom = Math.min( elemRect.bottom, canvasRect.bottom ) - canvasRect.top;
+		const top = Math.max( 0, elemRect.top - canvasRect.top );
+
+		const width = Math.min( canvasRect.width, right - left );
+		const height = Math.min( canvasRect.height, bottom - top );
+
+		// setup the scissor to only render to that part of the canvas
+		const positiveYUpBottom = canvasRect.height - bottom;
+		renderer.setScissor( left, positiveYUpBottom, width, height );
+		renderer.setViewport( left, positiveYUpBottom, width, height );
+
+		// return the aspect
+		return width / height;
+
+	}
+
+	function render() {
+
+		resizeRendererToDisplaySize( renderer );
+
+		// turn on the scissor
+		renderer.setScissorTest( true );
+
+		// render the original view
+		{
+
+			const aspect = setScissorForElement( view1Elem );
+
+			// adjust the camera for this aspect
+			camera.aspect = aspect;
+			camera.updateProjectionMatrix();
+			cameraHelper.update();
+
+			// don't draw the camera helper in the original view
+			cameraHelper.visible = false;
+
+			scene.background.set( 0x000000 );
+
+			// render
+			renderer.render( scene, camera );
+
+		}
+
+		// render from the 2nd camera
+		{
+
+			const aspect = setScissorForElement( view2Elem );
+
+			// adjust the camera for this aspect
+			camera2.aspect = aspect;
+			camera2.updateProjectionMatrix();
+
+			// draw the camera helper in the 2nd view
+			cameraHelper.visible = true;
+
+			scene.background.set( 0x000040 );
+
+			renderer.render( scene, camera2 );
+
+		}
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 153 - 117
manual/examples/cameras-perspective.html

@@ -35,134 +35,170 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 10, 20);
-
-  class MinMaxGUIHelper {
-    constructor(obj, minProp, maxProp, minDif) {
-      this.obj = obj;
-      this.minProp = minProp;
-      this.maxProp = maxProp;
-      this.minDif = minDif;
-    }
-    get min() {
-      return this.obj[this.minProp];
-    }
-    set min(v) {
-      this.obj[this.minProp] = v;
-      this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-    }
-    get max() {
-      return this.obj[this.maxProp];
-    }
-    set max(v) {
-      this.obj[this.maxProp] = v;
-      this.min = this.min;  // this will call the min setter
-    }
-  }
 
-  function updateCamera() {
-    camera.updateProjectionMatrix();
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const gui = new GUI();
-  gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-  const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-  gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near').onChange(updateCamera);
-  gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-
-  {
-    const planeSize = 40;
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/checker.png');
-    texture.wrapS = THREE.RepeatWrapping;
-    texture.wrapT = THREE.RepeatWrapping;
-    texture.magFilter = THREE.NearestFilter;
-    const repeats = planeSize / 2;
-    texture.repeat.set(repeats, repeats);
-
-    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-    const planeMat = new THREE.MeshPhongMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    mesh.rotation.x = Math.PI * -.5;
-    scene.add(mesh);
-  }
-  {
-    const cubeSize = 4;
-    const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
-    const cubeMat = new THREE.MeshPhongMaterial({color: '#8AC'});
-    const mesh = new THREE.Mesh(cubeGeo, cubeMat);
-    mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
-    scene.add(mesh);
-  }
-  {
-    const sphereRadius = 3;
-    const sphereWidthDivisions = 32;
-    const sphereHeightDivisions = 16;
-    const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-    const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
-    const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-    mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
-    scene.add(mesh);
-  }
+	const fov = 45;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 10, 20 );
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(0, 10, 0);
-    light.target.position.set(-5, 0, 0);
-    scene.add(light);
-    scene.add(light.target);
-  }
+	class MinMaxGUIHelper {
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		constructor( obj, minProp, maxProp, minDif ) {
 
-  function render() {
+			this.obj = obj;
+			this.minProp = minProp;
+			this.maxProp = maxProp;
+			this.minDif = minDif;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		}
+		get min() {
 
-    renderer.render(scene, camera);
+			return this.obj[ this.minProp ];
 
-    requestAnimationFrame(render);
-  }
+		}
+		set min( v ) {
+
+			this.obj[ this.minProp ] = v;
+			this.obj[ this.maxProp ] = Math.max( this.obj[ this.maxProp ], v + this.minDif );
+
+		}
+		get max() {
+
+			return this.obj[ this.maxProp ];
+
+		}
+		set max( v ) {
+
+			this.obj[ this.maxProp ] = v;
+			this.min = this.min; // this will call the min setter
+
+		}
+
+	}
+
+	function updateCamera() {
+
+		camera.updateProjectionMatrix();
+
+	}
+
+	const gui = new GUI();
+	gui.add( camera, 'fov', 1, 180 ).onChange( updateCamera );
+	const minMaxGUIHelper = new MinMaxGUIHelper( camera, 'near', 'far', 0.1 );
+	gui.add( minMaxGUIHelper, 'min', 0.1, 50, 0.1 ).name( 'near' ).onChange( updateCamera );
+	gui.add( minMaxGUIHelper, 'max', 0.1, 50, 0.1 ).name( 'far' ).onChange( updateCamera );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+
+	{
+
+		const planeSize = 40;
+
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/checker.png' );
+		texture.wrapS = THREE.RepeatWrapping;
+		texture.wrapT = THREE.RepeatWrapping;
+		texture.magFilter = THREE.NearestFilter;
+		//texture.colorSpace = THREE.SRGBColorSpace;
+		const repeats = planeSize / 2;
+		texture.repeat.set( repeats, repeats );
+
+		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+		const planeMat = new THREE.MeshPhongMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		mesh.rotation.x = Math.PI * - .5;
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const cubeSize = 4;
+		const cubeGeo = new THREE.BoxGeometry( cubeSize, cubeSize, cubeSize );
+		const cubeMat = new THREE.MeshPhongMaterial( { color: '#8AC' } );
+		const mesh = new THREE.Mesh( cubeGeo, cubeMat );
+		mesh.position.set( cubeSize + 1, cubeSize / 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const sphereRadius = 3;
+		const sphereWidthDivisions = 32;
+		const sphereHeightDivisions = 16;
+		const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
+		const sphereMat = new THREE.MeshPhongMaterial( { color: '#CA8' } );
+		const mesh = new THREE.Mesh( sphereGeo, sphereMat );
+		mesh.position.set( - sphereRadius - 1, sphereRadius + 2, 0 );
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( 0, 10, 0 );
+		light.target.position.set( - 5, 0, 0 );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 147 - 112
manual/examples/cameras-z-fighting.html

@@ -35,129 +35,164 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.00001;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(10, 6, 10);
-
-  class MinMaxGUIHelper {
-    constructor(obj, minProp, maxProp, minDif) {
-      this.obj = obj;
-      this.minProp = minProp;
-      this.maxProp = maxProp;
-      this.minDif = minDif;
-    }
-    get min() {
-      return this.obj[this.minProp];
-    }
-    set min(v) {
-      this.obj[this.minProp] = v;
-      this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + this.minDif);
-    }
-    get max() {
-      return this.obj[this.maxProp];
-    }
-    set max(v) {
-      this.obj[this.maxProp] = v;
-      this.min = this.min;  // this will call the min setter
-    }
-  }
 
-  function updateCamera() {
-    camera.updateProjectionMatrix();
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	const fov = 45;
+	const aspect = 2; // the canvas default
+	const near = 0.00001;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 10, 6, 10 );
 
-  const gui = new GUI();
-  gui.add(camera, 'fov', 1, 180).onChange(updateCamera);
-  const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1);
-  gui.add(minMaxGUIHelper, 'min', 0.00001, 50, 0.00001).name('near').onChange(updateCamera);
-  gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far').onChange(updateCamera);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-
-  {
-    const planeSize = 40;
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/checker.png');
-    texture.wrapS = THREE.RepeatWrapping;
-    texture.wrapT = THREE.RepeatWrapping;
-    texture.magFilter = THREE.NearestFilter;
-    const repeats = planeSize / 2;
-    texture.repeat.set(repeats, repeats);
-
-    const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize);
-    const planeMat = new THREE.MeshPhongMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-    });
-    const mesh = new THREE.Mesh(planeGeo, planeMat);
-    mesh.rotation.x = Math.PI * -.5;
-    scene.add(mesh);
-  }
-  {
-    const sphereRadius = 3;
-    const sphereWidthDivisions = 32;
-    const sphereHeightDivisions = 16;
-    const sphereGeo = new THREE.SphereGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
-    const numSpheres = 20;
-    for (let i = 0; i < numSpheres; ++i) {
-      const sphereMat = new THREE.MeshPhongMaterial();
-      sphereMat.color.setHSL(i * .73, 1, 0.5);
-      const mesh = new THREE.Mesh(sphereGeo, sphereMat);
-      mesh.position.set(-sphereRadius - 1, sphereRadius + 2, i * sphereRadius * -2.2);
-      scene.add(mesh);
-    }
-  }
+	class MinMaxGUIHelper {
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(0, 10, 0);
-    light.target.position.set(-5, 0, 0);
-    scene.add(light);
-    scene.add(light.target);
-  }
+		constructor( obj, minProp, maxProp, minDif ) {
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+			this.obj = obj;
+			this.minProp = minProp;
+			this.maxProp = maxProp;
+			this.minDif = minDif;
 
-  function render() {
+		}
+		get min() {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+			return this.obj[ this.minProp ];
 
-    renderer.render(scene, camera);
+		}
+		set min( v ) {
 
-    requestAnimationFrame(render);
-  }
+			this.obj[ this.minProp ] = v;
+			this.obj[ this.maxProp ] = Math.max( this.obj[ this.maxProp ], v + this.minDif );
+
+		}
+		get max() {
+
+			return this.obj[ this.maxProp ];
+
+		}
+		set max( v ) {
+
+			this.obj[ this.maxProp ] = v;
+			this.min = this.min; // this will call the min setter
+
+		}
+
+	}
+
+	function updateCamera() {
+
+		camera.updateProjectionMatrix();
+
+	}
+
+	const gui = new GUI();
+	gui.add( camera, 'fov', 1, 180 ).onChange( updateCamera );
+	const minMaxGUIHelper = new MinMaxGUIHelper( camera, 'near', 'far', 0.1 );
+	gui.add( minMaxGUIHelper, 'min', 0.00001, 50, 0.00001 ).name( 'near' ).onChange( updateCamera );
+	gui.add( minMaxGUIHelper, 'max', 0.1, 50, 0.1 ).name( 'far' ).onChange( updateCamera );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+
+	{
+
+		const planeSize = 40;
+
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/checker.png' );
+		texture.wrapS = THREE.RepeatWrapping;
+		texture.wrapT = THREE.RepeatWrapping;
+		texture.magFilter = THREE.NearestFilter;
+		texture.colorSpace = THREE.SRGBColorSpace;
+		const repeats = planeSize / 2;
+		texture.repeat.set( repeats, repeats );
+
+		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
+		const planeMat = new THREE.MeshPhongMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+		} );
+		const mesh = new THREE.Mesh( planeGeo, planeMat );
+		mesh.rotation.x = Math.PI * - .5;
+		scene.add( mesh );
+
+	}
+
+	{
+
+		const sphereRadius = 3;
+		const sphereWidthDivisions = 32;
+		const sphereHeightDivisions = 16;
+		const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
+		const numSpheres = 20;
+		for ( let i = 0; i < numSpheres; ++ i ) {
+
+			const sphereMat = new THREE.MeshPhongMaterial();
+			sphereMat.color.setHSL( i * .73, 1, 0.5 );
+			const mesh = new THREE.Mesh( sphereGeo, sphereMat );
+			mesh.position.set( - sphereRadius - 1, sphereRadius + 2, i * sphereRadius * - 2.2 );
+			scene.add( mesh );
+
+		}
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( 0, 10, 0 );
+		light.target.position.set( - 5, 0, 0 );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 43 - 31
manual/examples/canvas-random-dots.html

@@ -11,37 +11,49 @@
 <script type="module">
 
 function main() {
-  const ctx = document.createElement('canvas').getContext('2d');
-  document.body.appendChild(ctx.canvas);
-  ctx.canvas.width = 256;
-  ctx.canvas.height = 256;
-  ctx.fillStyle = '#FFF';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-
-  function randInt(min, max) {
-    if (max === undefined) {
-      max = min;
-      min = 0;
-    }
-    return Math.random() * (max - min) + min | 0;
-  }
-
-  function drawRandomDot() {
-    ctx.fillStyle = `#${randInt(0x1000000).toString(16).padStart(6, '0')}`;
-    ctx.beginPath();
-
-    const x = randInt(256);
-    const y = randInt(256);
-    const radius = randInt(10, 64);
-    ctx.arc(x, y, radius, 0, Math.PI * 2);
-    ctx.fill();
-  }
-
-  function render() {
-    drawRandomDot();
-    requestAnimationFrame(render);
-  }
-  requestAnimationFrame(render);
+
+	const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+	document.body.appendChild( ctx.canvas );
+	ctx.canvas.width = 256;
+	ctx.canvas.height = 256;
+	ctx.fillStyle = '#FFF';
+	ctx.fillRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
+
+	function randInt( min, max ) {
+
+		if ( max === undefined ) {
+
+			max = min;
+			min = 0;
+
+		}
+
+		return Math.random() * ( max - min ) + min | 0;
+
+	}
+
+	function drawRandomDot() {
+
+		ctx.fillStyle = `#${randInt( 0x1000000 ).toString( 16 ).padStart( 6, '0' )}`;
+		ctx.beginPath();
+
+		const x = randInt( 256 );
+		const y = randInt( 256 );
+		const radius = randInt( 10, 64 );
+		ctx.arc( x, y, radius, 0, Math.PI * 2 );
+		ctx.fill();
+
+	}
+
+	function render() {
+
+		drawRandomDot();
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
+
 }
 
 main();

+ 151 - 112
manual/examples/canvas-textured-cube-qix.html

@@ -36,130 +36,169 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-  const cubes = [];  // just an array we can use to rotate the cubes
-  const ctx = document.createElement('canvas').getContext('2d');
-  ctx.canvas.width = 256;
-  ctx.canvas.height = 256;
-  ctx.fillStyle = '#FFF';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-  const texture = new THREE.CanvasTexture(ctx.canvas);
-
-  const material = new THREE.MeshBasicMaterial({
-    map: texture,
-  });
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
 
-  function rand(min, max) {
-  if (max === undefined) {
-    max = min;
-    min = 0;
-  }
-    return Math.random() * (max - min) + min;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function randVelocity() {
-    return rand(2, 4) * (rand(2) < 1 ? -1 : 1);
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const maxLines = 60;
-  const points = [
-    { position: [rand(256), rand(256)], direction: [randVelocity(), randVelocity()]},
-    { position: [rand(256), rand(256)], direction: [randVelocity(), randVelocity()]},
-  ];
-  const lineHistory = [];
-  let lineCursor = 0;
-
-  function drawCurrentLine() {
-    const line = lineHistory[lineCursor];
-    ctx.beginPath();
-    ctx.moveTo(...line[0]);
-    ctx.lineTo(...line[1]);
-    ctx.stroke();
-  }
+	const scene = new THREE.Scene();
 
-  function drawLines(time) {
-    points.forEach((point) => {
-      point.position.forEach((position, ndx) => {
-        const newPosition = position + point.direction[ndx];
-        if (newPosition > 255) {
-          point.direction[ndx] = rand(-2, -4);
-        } else if (newPosition < 0) {
-          point.direction[ndx] = rand( 2,  4);
-        }
-        point.position[ndx] = newPosition;
-      });
-    });
-    if (lineHistory.length === maxLines) {
-      ctx.lineWidth = 3;
-      ctx.strokeStyle = '#FFF';
-      drawCurrentLine();
-    }
-    lineHistory[lineCursor] = points.map(point => point.position.slice());
-    ctx.lineWidth = 1;
-    ctx.strokeStyle = hsl(time, 1, .5);
-    drawCurrentLine();
-    lineCursor = (lineCursor + 1) % maxLines;
-  }
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  function hsl(h, s, l) {
-    return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
-  }
+	const cubes = []; // just an array we can use to rotate the cubes
+	const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+	ctx.canvas.width = 256;
+	ctx.canvas.height = 256;
+	ctx.fillStyle = '#FFF';
+	ctx.fillRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
+	const texture = new THREE.CanvasTexture( ctx.canvas );
 
-  function render(time) {
-    time *= 0.001;
+	const material = new THREE.MeshBasicMaterial( {
+		map: texture,
+	} );
+	const cube = new THREE.Mesh( geometry, material );
+	scene.add( cube );
+	cubes.push( cube ); // add to our list of cubes to rotate
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function resizeRendererToDisplaySize( renderer ) {
 
-    drawLines(time * 0.1);
-    texture.needsUpdate = true;
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = .2 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+			renderer.setSize( width, height, false );
 
-    renderer.render(scene, camera);
+		}
 
-    requestAnimationFrame(render);
-  }
+		return needResize;
+
+	}
+
+	function rand( min, max ) {
+
+		if ( max === undefined ) {
+
+			max = min;
+			min = 0;
+
+		}
+
+		return Math.random() * ( max - min ) + min;
+
+	}
+
+	function randVelocity() {
+
+		return rand( 2, 4 ) * ( rand( 2 ) < 1 ? - 1 : 1 );
+
+	}
+
+	const maxLines = 60;
+	const points = [
+		{ position: [ rand( 256 ), rand( 256 ) ], direction: [ randVelocity(), randVelocity() ] },
+		{ position: [ rand( 256 ), rand( 256 ) ], direction: [ randVelocity(), randVelocity() ] },
+	];
+	const lineHistory = [];
+	let lineCursor = 0;
+
+	function drawCurrentLine() {
+
+		const line = lineHistory[ lineCursor ];
+		ctx.beginPath();
+		ctx.moveTo( ...line[ 0 ] );
+		ctx.lineTo( ...line[ 1 ] );
+		ctx.stroke();
+
+	}
+
+	function drawLines( time ) {
+
+		points.forEach( ( point ) => {
+
+			point.position.forEach( ( position, ndx ) => {
+
+				const newPosition = position + point.direction[ ndx ];
+				if ( newPosition > 255 ) {
+
+					point.direction[ ndx ] = rand( - 2, - 4 );
+
+				} else if ( newPosition < 0 ) {
+
+					point.direction[ ndx ] = rand( 2, 4 );
+
+				}
+
+				point.position[ ndx ] = newPosition;
+
+			} );
+
+		} );
+		if ( lineHistory.length === maxLines ) {
+
+			ctx.lineWidth = 3;
+			ctx.strokeStyle = '#FFF';
+			drawCurrentLine();
+
+		}
+
+		lineHistory[ lineCursor ] = points.map( point => point.position.slice() );
+		ctx.lineWidth = 1;
+		ctx.strokeStyle = hsl( time, 1, .5 );
+		drawCurrentLine();
+		lineCursor = ( lineCursor + 1 ) % maxLines;
+
+	}
+
+	function hsl( h, s, l ) {
+
+		return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		drawLines( time * 0.1 );
+		texture.needsUpdate = true;
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = .2 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 98 - 77
manual/examples/canvas-textured-cube.html

@@ -36,93 +36,114 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
-
-  const cubes = [];  // just an array we can use to rotate the cubes
-  const ctx = document.createElement('canvas').getContext('2d');
-  ctx.canvas.width = 256;
-  ctx.canvas.height = 256;
-  ctx.fillStyle = '#FFF';
-  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-  const texture = new THREE.CanvasTexture(ctx.canvas);
-
-  const material = new THREE.MeshBasicMaterial({
-    map: texture,
-  });
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
-  cubes.push(cube);  // add to our list of cubes to rotate
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
 
-  function randInt(min, max) {
-    if (max === undefined) {
-      max = min;
-      min = 0;
-    }
-    return Math.random() * (max - min) + min | 0;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function drawRandomDot() {
-    ctx.fillStyle = `#${randInt(0x1000000).toString(16).padStart(6, '0')}`;
-    ctx.beginPath();
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const x = randInt(256);
-    const y = randInt(256);
-    const radius = randInt(10, 64);
-    ctx.arc(x, y, radius, 0, Math.PI * 2);
-    ctx.fill();
-  }
+	const scene = new THREE.Scene();
 
-  function render(time) {
-    time *= 0.001;
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	const cubes = []; // just an array we can use to rotate the cubes
+	const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+	ctx.canvas.width = 256;
+	ctx.canvas.height = 256;
+	ctx.fillStyle = '#FFF';
+	ctx.fillRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
+	const texture = new THREE.CanvasTexture( ctx.canvas );
 
-    drawRandomDot();
-    texture.needsUpdate = true;
+	const material = new THREE.MeshBasicMaterial( {
+		map: texture,
+	} );
+	const cube = new THREE.Mesh( geometry, material );
+	scene.add( cube );
+	cubes.push( cube ); // add to our list of cubes to rotate
 
-    cubes.forEach((cube, ndx) => {
-      const speed = .2 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+	function resizeRendererToDisplaySize( renderer ) {
 
-    renderer.render(scene, camera);
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
 
-    requestAnimationFrame(render);
-  }
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function randInt( min, max ) {
+
+		if ( max === undefined ) {
+
+			max = min;
+			min = 0;
+
+		}
+
+		return Math.random() * ( max - min ) + min | 0;
+
+	}
+
+	function drawRandomDot() {
+
+		ctx.fillStyle = `#${randInt( 0x1000000 ).toString( 16 ).padStart( 6, '0' )}`;
+		ctx.beginPath();
+
+		const x = randInt( 256 );
+		const y = randInt( 256 );
+		const radius = randInt( 10, 64 );
+		ctx.arc( x, y, radius, 0, Math.PI * 2 );
+		ctx.fill();
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		drawRandomDot();
+		texture.needsUpdate = true;
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = .2 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 181 - 158
manual/examples/canvas-textured-labels-one-canvas.html

@@ -35,172 +35,195 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('white');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const bodyRadiusTop = .4;
-  const bodyRadiusBottom = .2;
-  const bodyHeight = 2;
-  const bodyRadialSegments = 6;
-  const bodyGeometry = new THREE.CylinderGeometry(
-      bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-
-  const headRadius = bodyRadiusTop * 0.8;
-  const headLonSegments = 12;
-  const headLatSegments = 5;
-  const headGeometry = new THREE.SphereGeometry(
-      headRadius, headLonSegments, headLatSegments);
-
-  const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-  const ctx = document.createElement('canvas').getContext('2d');
-
-  function makeLabelCanvas(baseWidth, size, name) {
-    const borderSize = 2;
-    const font =  `${size}px bold sans-serif`;
-    ctx.font = font;
-    // measure how long the name will be
-    const textWidth = ctx.measureText(name).width;
-
-    const doubleBorderSize = borderSize * 2;
-    const width = baseWidth + doubleBorderSize;
-    const height = size + doubleBorderSize;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-
-    // need to set font again after resizing canvas
-    ctx.font = font;
-    ctx.textBaseline = 'middle';
-    ctx.textAlign = 'center';
-
-    ctx.fillStyle = 'blue';
-    ctx.fillRect(0, 0, width, height);
-
-    // scale to fit but don't stretch
-    const scaleFactor = Math.min(1, baseWidth / textWidth);
-    ctx.translate(width / 2, height / 2);
-    ctx.scale(scaleFactor, 1);
-    ctx.fillStyle = 'white';
-    ctx.fillText(name, 0, 0);
-
-    return ctx.canvas;
-  }
 
-  const forceTextureInitialization = function() {
-    const material = new THREE.MeshBasicMaterial();
-    const geometry = new THREE.PlaneGeometry();
-    const scene = new THREE.Scene();
-    scene.add(new THREE.Mesh(geometry, material));
-    const camera = new THREE.Camera();
-
-    return function forceTextureInitialization(texture) {
-      material.map = texture;
-      renderer.render(scene, camera);
-    };
-  }();
-
-  function makePerson(x, labelWidth, size, name, color) {
-    const canvas = makeLabelCanvas(labelWidth, size, name);
-    const texture = new THREE.CanvasTexture(canvas);
-    // because our canvas is likely not a power of 2
-    // in both dimensions set the filtering appropriately.
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = THREE.ClampToEdgeWrapping;
-    texture.wrapT = THREE.ClampToEdgeWrapping;
-    forceTextureInitialization(texture);
-
-    const labelMaterial = new THREE.MeshBasicMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-      transparent: true,
-    });
-    const bodyMaterial = new THREE.MeshPhongMaterial({
-      color,
-      flatShading: true,
-    });
-
-    const root = new THREE.Object3D();
-    root.position.x = x;
-
-    const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-    root.add(body);
-    body.position.y = bodyHeight / 2;
-
-    const head = new THREE.Mesh(headGeometry, bodyMaterial);
-    root.add(head);
-    head.position.y = bodyHeight + headRadius * 1.1;
-
-    const label = new THREE.Mesh(labelGeometry, labelMaterial);
-    root.add(label);
-    label.position.y = bodyHeight * 4 / 5;
-    label.position.z = bodyRadiusTop * 1.01;
-
-    // if units are meters then 0.01 here makes size
-    // of the label into centimeters.
-    const labelBaseScale = 0.01;
-    label.scale.x = canvas.width  * labelBaseScale;
-    label.scale.y = canvas.height * labelBaseScale;
-
-    scene.add(root);
-    return root;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-  makePerson(-0, 150, 32, 'Green Machine', 'green');
-  makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.update();
 
-    renderer.render(scene, camera);
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'white' );
 
-    requestAnimationFrame(render);
-  }
+	function addLight( position ) {
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const bodyRadiusTop = .4;
+	const bodyRadiusBottom = .2;
+	const bodyHeight = 2;
+	const bodyRadialSegments = 6;
+	const bodyGeometry = new THREE.CylinderGeometry(
+		bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments );
+
+	const headRadius = bodyRadiusTop * 0.8;
+	const headLonSegments = 12;
+	const headLatSegments = 5;
+	const headGeometry = new THREE.SphereGeometry(
+		headRadius, headLonSegments, headLatSegments );
+
+	const labelGeometry = new THREE.PlaneGeometry( 1, 1 );
+
+	const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+
+	function makeLabelCanvas( baseWidth, size, name ) {
+
+		const borderSize = 2;
+		const font = `${size}px bold sans-serif`;
+		ctx.font = font;
+		// measure how long the name will be
+		const textWidth = ctx.measureText( name ).width;
+
+		const doubleBorderSize = borderSize * 2;
+		const width = baseWidth + doubleBorderSize;
+		const height = size + doubleBorderSize;
+		ctx.canvas.width = width;
+		ctx.canvas.height = height;
+
+		// need to set font again after resizing canvas
+		ctx.font = font;
+		ctx.textBaseline = 'middle';
+		ctx.textAlign = 'center';
+
+		ctx.fillStyle = 'blue';
+		ctx.fillRect( 0, 0, width, height );
+
+		// scale to fit but don't stretch
+		const scaleFactor = Math.min( 1, baseWidth / textWidth );
+		ctx.translate( width / 2, height / 2 );
+		ctx.scale( scaleFactor, 1 );
+		ctx.fillStyle = 'white';
+		ctx.fillText( name, 0, 0 );
+
+		return ctx.canvas;
+
+	}
+
+	const forceTextureInitialization = function () {
+
+		const material = new THREE.MeshBasicMaterial();
+		const geometry = new THREE.PlaneGeometry();
+		const scene = new THREE.Scene();
+		scene.add( new THREE.Mesh( geometry, material ) );
+		const camera = new THREE.Camera();
+
+		return function forceTextureInitialization( texture ) {
+
+			material.map = texture;
+			renderer.render( scene, camera );
+
+		};
+
+	}();
+
+	function makePerson( x, labelWidth, size, name, color ) {
+
+		const canvas = makeLabelCanvas( labelWidth, size, name );
+		const texture = new THREE.CanvasTexture( canvas );
+		// because our canvas is likely not a power of 2
+		// in both dimensions set the filtering appropriately.
+		texture.minFilter = THREE.LinearFilter;
+		texture.wrapS = THREE.ClampToEdgeWrapping;
+		texture.wrapT = THREE.ClampToEdgeWrapping;
+		forceTextureInitialization( texture );
+
+		const labelMaterial = new THREE.MeshBasicMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+			transparent: true,
+		} );
+		const bodyMaterial = new THREE.MeshPhongMaterial( {
+			color,
+			flatShading: true,
+		} );
+
+		const root = new THREE.Object3D();
+		root.position.x = x;
+
+		const body = new THREE.Mesh( bodyGeometry, bodyMaterial );
+		root.add( body );
+		body.position.y = bodyHeight / 2;
+
+		const head = new THREE.Mesh( headGeometry, bodyMaterial );
+		root.add( head );
+		head.position.y = bodyHeight + headRadius * 1.1;
+
+		const label = new THREE.Mesh( labelGeometry, labelMaterial );
+		root.add( label );
+		label.position.y = bodyHeight * 4 / 5;
+		label.position.z = bodyRadiusTop * 1.01;
+
+		// if units are meters then 0.01 here makes size
+		// of the label into centimeters.
+		const labelBaseScale = 0.01;
+		label.scale.x = canvas.width * labelBaseScale;
+		label.scale.y = canvas.height * labelBaseScale;
+
+		scene.add( root );
+		return root;
+
+	}
+
+	makePerson( - 3, 150, 32, 'Purple People Eater', 'purple' );
+	makePerson( - 0, 150, 32, 'Green Machine', 'green' );
+	makePerson( + 3, 150, 32, 'Red Menace', 'red' );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 162 - 143
manual/examples/canvas-textured-labels-scale-to-fit.html

@@ -35,157 +35,176 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('white');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const bodyRadiusTop = .4;
-  const bodyRadiusBottom = .2;
-  const bodyHeight = 2;
-  const bodyRadialSegments = 6;
-  const bodyGeometry = new THREE.CylinderGeometry(
-      bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-
-  const headRadius = bodyRadiusTop * 0.8;
-  const headLonSegments = 12;
-  const headLatSegments = 5;
-  const headGeometry = new THREE.SphereGeometry(
-      headRadius, headLonSegments, headLatSegments);
-
-  const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-  function makeLabelCanvas(baseWidth, size, name) {
-    const borderSize = 2;
-    const ctx = document.createElement('canvas').getContext('2d');
-    const font =  `${size}px bold sans-serif`;
-    ctx.font = font;
-    // measure how long the name will be
-    const textWidth = ctx.measureText(name).width;
-
-    const doubleBorderSize = borderSize * 2;
-    const width = baseWidth + doubleBorderSize;
-    const height = size + doubleBorderSize;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-
-    // need to set font again after resizing canvas
-    ctx.font = font;
-    ctx.textBaseline = 'middle';
-    ctx.textAlign = 'center';
-
-    ctx.fillStyle = 'blue';
-    ctx.fillRect(0, 0, width, height);
-
-    // scale to fit but don't stretch
-    const scaleFactor = Math.min(1, baseWidth / textWidth);
-    ctx.translate(width / 2, height / 2);
-    ctx.scale(scaleFactor, 1);
-    ctx.fillStyle = 'white';
-    ctx.fillText(name, 0, 0);
-
-    return ctx.canvas;
-  }
 
-  function makePerson(x, labelWidth, size, name, color) {
-    const canvas = makeLabelCanvas(labelWidth, size, name);
-    const texture = new THREE.CanvasTexture(canvas);
-    // because our canvas is likely not a power of 2
-    // in both dimensions set the filtering appropriately.
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = THREE.ClampToEdgeWrapping;
-    texture.wrapT = THREE.ClampToEdgeWrapping;
-
-    const labelMaterial = new THREE.MeshBasicMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-      transparent: true,
-    });
-    const bodyMaterial = new THREE.MeshPhongMaterial({
-      color,
-      flatShading: true,
-    });
-
-    const root = new THREE.Object3D();
-    root.position.x = x;
-
-    const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-    root.add(body);
-    body.position.y = bodyHeight / 2;
-
-    const head = new THREE.Mesh(headGeometry, bodyMaterial);
-    root.add(head);
-    head.position.y = bodyHeight + headRadius * 1.1;
-
-    const label = new THREE.Mesh(labelGeometry, labelMaterial);
-    root.add(label);
-    label.position.y = bodyHeight * 4 / 5;
-    label.position.z = bodyRadiusTop * 1.01;
-
-    // if units are meters then 0.01 here makes size
-    // of the label into centimeters.
-    const labelBaseScale = 0.01;
-    label.scale.x = canvas.width  * labelBaseScale;
-    label.scale.y = canvas.height * labelBaseScale;
-
-    scene.add(root);
-    return root;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'white' );
+
+	function addLight( position ) {
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const bodyRadiusTop = .4;
+	const bodyRadiusBottom = .2;
+	const bodyHeight = 2;
+	const bodyRadialSegments = 6;
+	const bodyGeometry = new THREE.CylinderGeometry(
+		bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments );
+
+	const headRadius = bodyRadiusTop * 0.8;
+	const headLonSegments = 12;
+	const headLatSegments = 5;
+	const headGeometry = new THREE.SphereGeometry(
+		headRadius, headLonSegments, headLatSegments );
+
+	const labelGeometry = new THREE.PlaneGeometry( 1, 1 );
+
+	function makeLabelCanvas( baseWidth, size, name ) {
 
-  makePerson(-3, 150, 32, 'Purple People Eater', 'purple');
-  makePerson(-0, 150, 32, 'Green Machine', 'green');
-  makePerson(+3, 150, 32, 'Red Menace', 'red');
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		const borderSize = 2;
+		const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+		const font = `${size}px bold sans-serif`;
+		ctx.font = font;
+		// measure how long the name will be
+		const textWidth = ctx.measureText( name ).width;
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		const doubleBorderSize = borderSize * 2;
+		const width = baseWidth + doubleBorderSize;
+		const height = size + doubleBorderSize;
+		ctx.canvas.width = width;
+		ctx.canvas.height = height;
 
-    renderer.render(scene, camera);
+		// need to set font again after resizing canvas
+		ctx.font = font;
+		ctx.textBaseline = 'middle';
+		ctx.textAlign = 'center';
 
-    requestAnimationFrame(render);
-  }
+		ctx.fillStyle = 'blue';
+		ctx.fillRect( 0, 0, width, height );
+
+		// scale to fit but don't stretch
+		const scaleFactor = Math.min( 1, baseWidth / textWidth );
+		ctx.translate( width / 2, height / 2 );
+		ctx.scale( scaleFactor, 1 );
+		ctx.fillStyle = 'white';
+		ctx.fillText( name, 0, 0 );
+
+		return ctx.canvas;
+
+	}
+
+	function makePerson( x, labelWidth, size, name, color ) {
+
+		const canvas = makeLabelCanvas( labelWidth, size, name );
+		const texture = new THREE.CanvasTexture( canvas );
+		// because our canvas is likely not a power of 2
+		// in both dimensions set the filtering appropriately.
+		texture.minFilter = THREE.LinearFilter;
+		texture.wrapS = THREE.ClampToEdgeWrapping;
+		texture.wrapT = THREE.ClampToEdgeWrapping;
+
+		const labelMaterial = new THREE.MeshBasicMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+			transparent: true,
+		} );
+		const bodyMaterial = new THREE.MeshPhongMaterial( {
+			color,
+			flatShading: true,
+		} );
+
+		const root = new THREE.Object3D();
+		root.position.x = x;
+
+		const body = new THREE.Mesh( bodyGeometry, bodyMaterial );
+		root.add( body );
+		body.position.y = bodyHeight / 2;
+
+		const head = new THREE.Mesh( headGeometry, bodyMaterial );
+		root.add( head );
+		head.position.y = bodyHeight + headRadius * 1.1;
+
+		const label = new THREE.Mesh( labelGeometry, labelMaterial );
+		root.add( label );
+		label.position.y = bodyHeight * 4 / 5;
+		label.position.z = bodyRadiusTop * 1.01;
+
+		// if units are meters then 0.01 here makes size
+		// of the label into centimeters.
+		const labelBaseScale = 0.01;
+		label.scale.x = canvas.width * labelBaseScale;
+		label.scale.y = canvas.height * labelBaseScale;
+
+		scene.add( root );
+		return root;
+
+	}
+
+	makePerson( - 3, 150, 32, 'Purple People Eater', 'purple' );
+	makePerson( - 0, 150, 32, 'Green Machine', 'green' );
+	makePerson( + 3, 150, 32, 'Red Menace', 'red' );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 154 - 135
manual/examples/canvas-textured-labels.html

@@ -35,149 +35,168 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 2, 5);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 2, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('white');
-
-  function addLight(position) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...position);
-    scene.add(light);
-    scene.add(light.target);
-  }
-  addLight([-3, 1, 1]);
-  addLight([ 2, 1, .5]);
-
-  const bodyRadiusTop = .4;
-  const bodyRadiusBottom = .2;
-  const bodyHeight = 2;
-  const bodyRadialSegments = 6;
-  const bodyGeometry = new THREE.CylinderGeometry(
-      bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments);
-
-  const headRadius = bodyRadiusTop * 0.8;
-  const headLonSegments = 12;
-  const headLatSegments = 5;
-  const headGeometry = new THREE.SphereGeometry(
-      headRadius, headLonSegments, headLatSegments);
-
-  const labelGeometry = new THREE.PlaneGeometry(1, 1);
-
-  function makeLabelCanvas(size, name) {
-    const borderSize = 2;
-    const ctx = document.createElement('canvas').getContext('2d');
-    const font =  `${size}px bold sans-serif`;
-    ctx.font = font;
-    // measure how long the name will be
-    const doubleBorderSize = borderSize * 2;
-    const width = ctx.measureText(name).width + doubleBorderSize;
-    const height = size + doubleBorderSize;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-
-    // need to set font again after resizing canvas
-    ctx.font = font;
-    ctx.textBaseline = 'top';
-
-    ctx.fillStyle = 'blue';
-    ctx.fillRect(0, 0, width, height);
-    ctx.fillStyle = 'white';
-    ctx.fillText(name, borderSize, borderSize);
-
-    return ctx.canvas;
-  }
 
-  function makePerson(x, size, name, color) {
-    const canvas = makeLabelCanvas(size, name);
-    const texture = new THREE.CanvasTexture(canvas);
-    // because our canvas is likely not a power of 2
-    // in both dimensions set the filtering appropriately.
-    texture.minFilter = THREE.LinearFilter;
-    texture.wrapS = THREE.ClampToEdgeWrapping;
-    texture.wrapT = THREE.ClampToEdgeWrapping;
-
-    const labelMaterial = new THREE.MeshBasicMaterial({
-      map: texture,
-      side: THREE.DoubleSide,
-      transparent: true,
-    });
-    const bodyMaterial = new THREE.MeshPhongMaterial({
-      color,
-      flatShading: true,
-    });
-
-    const root = new THREE.Object3D();
-    root.position.x = x;
-
-    const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
-    root.add(body);
-    body.position.y = bodyHeight / 2;
-
-    const head = new THREE.Mesh(headGeometry, bodyMaterial);
-    root.add(head);
-    head.position.y = bodyHeight + headRadius * 1.1;
-
-    const label = new THREE.Mesh(labelGeometry, labelMaterial);
-    root.add(label);
-    label.position.y = bodyHeight * 4 / 5;
-    label.position.z = bodyRadiusTop * 1.01;
-
-    // if units are meters then 0.01 here makes size
-    // of the label into centimeters.
-    const labelBaseScale = 0.01;
-    label.scale.x = canvas.width  * labelBaseScale;
-    label.scale.y = canvas.height * labelBaseScale;
-
-    scene.add(root);
-    return root;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 2, 5 );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 2, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'white' );
+
+	function addLight( position ) {
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...position );
+		scene.add( light );
+		scene.add( light.target );
+
+	}
+
+	addLight( [ - 3, 1, 1 ] );
+	addLight( [ 2, 1, .5 ] );
+
+	const bodyRadiusTop = .4;
+	const bodyRadiusBottom = .2;
+	const bodyHeight = 2;
+	const bodyRadialSegments = 6;
+	const bodyGeometry = new THREE.CylinderGeometry(
+		bodyRadiusTop, bodyRadiusBottom, bodyHeight, bodyRadialSegments );
+
+	const headRadius = bodyRadiusTop * 0.8;
+	const headLonSegments = 12;
+	const headLatSegments = 5;
+	const headGeometry = new THREE.SphereGeometry(
+		headRadius, headLonSegments, headLatSegments );
 
-  makePerson(-3, 32, 'Purple People Eater', 'purple');
-  makePerson(-0, 32, 'Green Machine', 'green');
-  makePerson(+3, 32, 'Red Menace', 'red');
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const labelGeometry = new THREE.PlaneGeometry( 1, 1 );
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function makeLabelCanvas( size, name ) {
 
-    renderer.render(scene, camera);
+		const borderSize = 2;
+		const ctx = document.createElement( 'canvas' ).getContext( '2d' );
+		const font = `${size}px bold sans-serif`;
+		ctx.font = font;
+		// measure how long the name will be
+		const doubleBorderSize = borderSize * 2;
+		const width = ctx.measureText( name ).width + doubleBorderSize;
+		const height = size + doubleBorderSize;
+		ctx.canvas.width = width;
+		ctx.canvas.height = height;
 
-    requestAnimationFrame(render);
-  }
+		// need to set font again after resizing canvas
+		ctx.font = font;
+		ctx.textBaseline = 'top';
+
+		ctx.fillStyle = 'blue';
+		ctx.fillRect( 0, 0, width, height );
+		ctx.fillStyle = 'white';
+		ctx.fillText( name, borderSize, borderSize );
+
+		return ctx.canvas;
+
+	}
+
+	function makePerson( x, size, name, color ) {
+
+		const canvas = makeLabelCanvas( size, name );
+		const texture = new THREE.CanvasTexture( canvas );
+		// because our canvas is likely not a power of 2
+		// in both dimensions set the filtering appropriately.
+		texture.minFilter = THREE.LinearFilter;
+		texture.wrapS = THREE.ClampToEdgeWrapping;
+		texture.wrapT = THREE.ClampToEdgeWrapping;
+
+		const labelMaterial = new THREE.MeshBasicMaterial( {
+			map: texture,
+			side: THREE.DoubleSide,
+			transparent: true,
+		} );
+		const bodyMaterial = new THREE.MeshPhongMaterial( {
+			color,
+			flatShading: true,
+		} );
+
+		const root = new THREE.Object3D();
+		root.position.x = x;
+
+		const body = new THREE.Mesh( bodyGeometry, bodyMaterial );
+		root.add( body );
+		body.position.y = bodyHeight / 2;
+
+		const head = new THREE.Mesh( headGeometry, bodyMaterial );
+		root.add( head );
+		head.position.y = bodyHeight + headRadius * 1.1;
+
+		const label = new THREE.Mesh( labelGeometry, labelMaterial );
+		root.add( label );
+		label.position.y = bodyHeight * 4 / 5;
+		label.position.z = bodyRadiusTop * 1.01;
+
+		// if units are meters then 0.01 here makes size
+		// of the label into centimeters.
+		const labelBaseScale = 0.01;
+		label.scale.x = canvas.width * labelBaseScale;
+		label.scale.y = canvas.height * labelBaseScale;
+
+		scene.add( root );
+		return root;
+
+	}
+
+	makePerson( - 3, 32, 'Purple People Eater', 'purple' );
+	makePerson( - 0, 32, 'Green Machine', 'green' );
+	makePerson( + 3, 32, 'Red Menace', 'red' );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 240 - 167
manual/examples/cleanup-loaded-files.html

@@ -40,195 +40,268 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {GLTFLoader} from 'three/addons/loaders/GLTFLoader.js';
+import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
 class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (!resource) {
-      return resource;
-    }
 
-    // handle children and when material is an array of materials or
-    // uniform is array of textures
-    if (Array.isArray(resource)) {
-      resource.forEach(resource => this.track(resource));
-      return resource;
-    }
+	constructor() {
+
+		this.resources = new Set();
+
+	}
+	track( resource ) {
+
+		if ( ! resource ) {
+
+			return resource;
+
+		}
+
+		// handle children and when material is an array of materials or
+		// uniform is array of textures
+		if ( Array.isArray( resource ) ) {
+
+			resource.forEach( resource => this.track( resource ) );
+			return resource;
+
+		}
+
+		if ( resource.dispose || resource instanceof THREE.Object3D ) {
+
+			this.resources.add( resource );
+
+		}
+
+		if ( resource instanceof THREE.Object3D ) {
+
+			this.track( resource.geometry );
+			this.track( resource.material );
+			this.track( resource.children );
+
+		} else if ( resource instanceof THREE.Material ) {
+
+			// We have to check if there are any textures on the material
+			for ( const value of Object.values( resource ) ) {
+
+				if ( value instanceof THREE.Texture ) {
+
+					this.track( value );
+
+				}
+
+			}
+
+			// We also have to check if any uniforms reference textures or arrays of textures
+			if ( resource.uniforms ) {
+
+				for ( const value of Object.values( resource.uniforms ) ) {
+
+					if ( value ) {
+
+						const uniformValue = value.value;
+						if ( uniformValue instanceof THREE.Texture ||
+                Array.isArray( uniformValue ) ) {
+
+							this.track( uniformValue );
+
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+		return resource;
+
+	}
+	untrack( resource ) {
+
+		this.resources.delete( resource );
+
+	}
+	dispose() {
+
+		for ( const resource of this.resources ) {
+
+			if ( resource instanceof THREE.Object3D ) {
+
+				if ( resource.parent ) {
+
+					resource.parent.remove( resource );
+
+				}
+
+			}
+
+			if ( resource.dispose ) {
+
+				resource.dispose();
+
+			}
+
+		}
+
+		this.resources.clear();
+
+	}
 
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    if (resource instanceof THREE.Object3D) {
-      this.track(resource.geometry);
-      this.track(resource.material);
-      this.track(resource.children);
-    } else if (resource instanceof THREE.Material) {
-      // We have to check if there are any textures on the material
-      for (const value of Object.values(resource)) {
-        if (value instanceof THREE.Texture) {
-          this.track(value);
-        }
-      }
-      // We also have to check if any uniforms reference textures or arrays of textures
-      if (resource.uniforms) {
-        for (const value of Object.values(resource.uniforms)) {
-          if (value) {
-            const uniformValue = value.value;
-            if (uniformValue instanceof THREE.Texture ||
-                Array.isArray(uniformValue)) {
-              this.track(uniformValue);
-            }
-          }
-        }
-      }
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
-      if (resource instanceof THREE.Object3D) {
-        if (resource.parent) {
-          resource.parent.remove(resource);
-        }
-      }
-      if (resource.dispose) {
-        resource.dispose();
-      }
-    }
-    this.resources.clear();
-  }
 }
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  renderer.outputColorSpace = THREE.SRGBColorSpace;
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('lightblue');
-
-  function addLight(...pos) {
-    const color = 0xFFFFFF;
-    const intensity = 0.8;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...pos);
-    scene.add(light);
-  }
-  addLight(-1, 2, 4);
-  addLight( 2, -2, 3);
-
-  function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
-    const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
-    const halfFovY = THREE.MathUtils.degToRad(camera.fov * .5);
-    const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
-    // compute a unit vector that points in the direction the camera is now
-    // in the xz plane from the center of the box
-    const direction = (new THREE.Vector3())
-        .subVectors(camera.position, boxCenter)
-        .multiply(new THREE.Vector3(1, 0, 1))
-        .normalize();
-
-    // move the camera to a position distance units way from the center
-    // in whatever direction the camera was from the center already
-    camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
-
-    // pick some near and far values for the frustum that
-    // will contain the box.
-    camera.near = boxSize / 100;
-    camera.far = boxSize * 100;
-
-    camera.updateProjectionMatrix();
-
-    // point the camera to look at the center of the box
-    camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
-  }
 
-  const gltfLoader = new GLTFLoader();
-  function loadGLTF(url) {
-    return new Promise((resolve, reject) => {
-      gltfLoader.load(url, resolve, undefined, reject);
-    });
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function waitSeconds(seconds = 0) {
-    return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const fileURLs = [
-    'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf',  /* threejs.org: url */
-    'resources/models/3dbustchallange_submission/scene.gltf',            /* threejs.org: url */
-    'resources/models/mountain_landscape/scene.gltf',                    /* threejs.org: url */
-    'resources/models/simple_house_scene/scene.gltf',                    /* threejs.org: url */
-  ];
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'lightblue' );
 
-  async function loadFiles() {
-    for (;;) {
-      for (const url of fileURLs) {
-        const resMgr = new ResourceTracker();
-        const track = resMgr.track.bind(resMgr);
-        const gltf = await loadGLTF(url);
-        const root = track(gltf.scene);
-        scene.add(root);
+	function addLight( ...pos ) {
 
-        // compute the box that contains all the stuff
-        // from root and below
-        const box = new THREE.Box3().setFromObject(root);
+		const color = 0xFFFFFF;
+		const intensity = 2.5;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...pos );
+		scene.add( light );
 
-        const boxSize = box.getSize(new THREE.Vector3()).length();
-        const boxCenter = box.getCenter(new THREE.Vector3());
+	}
 
-        // set the camera to frame the box
-        frameArea(boxSize * 1.1, boxSize, boxCenter, camera);
+	addLight( - 1, 2, 4 );
+	addLight( 2, - 2, 3 );
 
-        await waitSeconds(2);
-        renderer.render(scene, camera);
+	function frameArea( sizeToFitOnScreen, boxSize, boxCenter, camera ) {
 
-        resMgr.dispose();
+		const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
+		const halfFovY = THREE.MathUtils.degToRad( camera.fov * .5 );
+		const distance = halfSizeToFitOnScreen / Math.tan( halfFovY );
+		// compute a unit vector that points in the direction the camera is now
+		// in the xz plane from the center of the box
+		const direction = ( new THREE.Vector3() )
+			.subVectors( camera.position, boxCenter )
+			.multiply( new THREE.Vector3( 1, 0, 1 ) )
+			.normalize();
 
-        await waitSeconds(1);
+		// move the camera to a position distance units way from the center
+		// in whatever direction the camera was from the center already
+		camera.position.copy( direction.multiplyScalar( distance ).add( boxCenter ) );
 
-      }
-    }
-  }
-  loadFiles();
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		// pick some near and far values for the frustum that
+		// will contain the box.
+		camera.near = boxSize / 100;
+		camera.far = boxSize * 100;
 
-  function render() {
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		camera.updateProjectionMatrix();
 
-    renderer.render(scene, camera);
+		// point the camera to look at the center of the box
+		camera.lookAt( boxCenter.x, boxCenter.y, boxCenter.z );
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	const gltfLoader = new GLTFLoader();
+	function loadGLTF( url ) {
+
+		return new Promise( ( resolve, reject ) => {
+
+			gltfLoader.load( url, resolve, undefined, reject );
+
+		} );
+
+	}
+
+	function waitSeconds( seconds = 0 ) {
+
+		return new Promise( resolve => setTimeout( resolve, seconds * 1000 ) );
+
+	}
+
+	const fileURLs = [
+		'resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', /* threejs.org: url */
+		'resources/models/3dbustchallange_submission/scene.gltf', /* threejs.org: url */
+		'resources/models/mountain_landscape/scene.gltf', /* threejs.org: url */
+		'resources/models/simple_house_scene/scene.gltf', /* threejs.org: url */
+	];
+
+	async function loadFiles() {
+
+		for ( ;; ) {
+
+			for ( const url of fileURLs ) {
+
+				const resMgr = new ResourceTracker();
+				const track = resMgr.track.bind( resMgr );
+				const gltf = await loadGLTF( url );
+				const root = track( gltf.scene );
+				scene.add( root );
+
+				// compute the box that contains all the stuff
+				// from root and below
+				const box = new THREE.Box3().setFromObject( root );
+
+				const boxSize = box.getSize( new THREE.Vector3() ).length();
+				const boxCenter = box.getCenter( new THREE.Vector3() );
+
+				// set the camera to frame the box
+				frameArea( boxSize * 1.1, boxSize, boxCenter, camera );
+
+				await waitSeconds( 2 );
+				renderer.render( scene, camera );
+
+				resMgr.dispose();
+
+				await waitSeconds( 1 );
+
+			}
+
+		}
+
+	}
+
+	loadFiles();
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render() {
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 146 - 98
manual/examples/cleanup-simple.html

@@ -41,115 +41,163 @@
 import * as THREE from 'three';
 
 class ResourceTracker {
-  constructor() {
-    this.resources = new Set();
-  }
-  track(resource) {
-    if (resource.dispose || resource instanceof THREE.Object3D) {
-      this.resources.add(resource);
-    }
-    return resource;
-  }
-  untrack(resource) {
-    this.resources.delete(resource);
-  }
-  dispose() {
-    for (const resource of this.resources) {
-      if (resource instanceof THREE.Object3D) {
-        if (resource.parent) {
-          resource.parent.remove(resource);
-        }
-      }
-      if (resource.dispose) {
-        resource.dispose();
-      }
-    }
-    this.resources.clear();
-  }
+
+	constructor() {
+
+		this.resources = new Set();
+
+	}
+	track( resource ) {
+
+		if ( resource.dispose || resource instanceof THREE.Object3D ) {
+
+			this.resources.add( resource );
+
+		}
+
+		return resource;
+
+	}
+	untrack( resource ) {
+
+		this.resources.delete( resource );
+
+	}
+	dispose() {
+
+		for ( const resource of this.resources ) {
+
+			if ( resource instanceof THREE.Object3D ) {
+
+				if ( resource.parent ) {
+
+					resource.parent.remove( resource );
+
+				}
+
+			}
+
+			if ( resource.dispose ) {
+
+				resource.dispose();
+
+			}
+
+		}
+
+		this.resources.clear();
+
+	}
+
 }
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-  const cubes = [];  // an array we can use to rotate the cubes
-
-  function addStuffToScene() {
-    const resTracker = new ResourceTracker();
-    const track = resTracker.track.bind(resTracker);
-
-    const boxWidth = 1;
-    const boxHeight = 1;
-    const boxDepth = 1;
-    const geometry = track(new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth));
-
-    const loader = new THREE.TextureLoader();
-
-    const material = track(new THREE.MeshBasicMaterial({
-      map: track(loader.load('resources/images/wall.jpg')),
-    }));
-    const cube = track(new THREE.Mesh(geometry, material));
-    scene.add(cube);
-    cubes.push(cube);  // add to our list of cubes to rotate
-    return resTracker;
-  }
 
-  function waitSeconds(seconds = 0) {
-    return new Promise(resolve => setTimeout(resolve, seconds * 1000));
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  async function process() {
-    for (;;) {
-      const resTracker = addStuffToScene();
-      await waitSeconds(2);
-      cubes.length = 0;  // remove the cubes
-      resTracker.dispose();
-      await waitSeconds(1);
-    }
-  }
-  process();
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  function render(time) {
-    time *= 0.001;
+	const scene = new THREE.Scene();
+	const cubes = []; // an array we can use to rotate the cubes
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	function addStuffToScene() {
 
-    cubes.forEach((cube, ndx) => {
-      const speed = .2 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		const resTracker = new ResourceTracker();
+		const track = resTracker.track.bind( resTracker );
 
-    renderer.render(scene, camera);
+		const boxWidth = 1;
+		const boxHeight = 1;
+		const boxDepth = 1;
+		const geometry = track( new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth ) );
 
-    requestAnimationFrame(render);
-  }
+		const loader = new THREE.TextureLoader();
+		const texture = loader.load( 'resources/images/wall.jpg' );
+		texture.colorSpace = THREE.SRGBColorSpace;
+
+		const material = track( new THREE.MeshBasicMaterial( {
+			map: track( texture ),
+		} ) );
+		const cube = track( new THREE.Mesh( geometry, material ) );
+		scene.add( cube );
+		cubes.push( cube ); // add to our list of cubes to rotate
+		return resTracker;
+
+	}
+
+	function waitSeconds( seconds = 0 ) {
+
+		return new Promise( resolve => setTimeout( resolve, seconds * 1000 ) );
+
+	}
+
+	async function process() {
+
+		for ( ;; ) {
+
+			const resTracker = addStuffToScene();
+			await waitSeconds( 2 );
+			cubes.length = 0; // remove the cubes
+			resTracker.dispose();
+			await waitSeconds( 1 );
+
+		}
+
+	}
+
+	process();
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = .2 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 150 - 129
manual/examples/custom-buffergeometry-cube-indexed.html

@@ -36,144 +36,165 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  // NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
-  // Only trying to make it clear most vertices are unique
-  const vertices = [
-    // front
-    { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
-    { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
-    { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], }, // 2
-    { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], }, // 3
-    // right
-    { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], }, // 4
-    { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], }, // 5
-    { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], }, // 6
-    { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], }, // 7
-    // back
-    { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], }, // 8
-    { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], }, // 9
-    { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], }, // 10
-    { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], }, // 11
-    // left
-    { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], }, // 12
-    { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], }, // 13
-    { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], }, // 14
-    { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], }, // 15
-    // top
-    { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], }, // 16
-    { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], }, // 17
-    { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], }, // 18
-    { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], }, // 19
-    // bottom
-    { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], }, // 20
-    { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], }, // 21
-    { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
-    { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
-  ];
-  const positions = [];
-  const normals = [];
-  const uvs = [];
-  for (const vertex of vertices) {
-    positions.push(...vertex.pos);
-    normals.push(...vertex.norm);
-    uvs.push(...vertex.uv);
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 5;
+
+	const scene = new THREE.Scene();
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
+
+	}
+
+	// NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
+	// Only trying to make it clear most vertices are unique
+	const vertices = [
+		// front
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 0 ], }, // 0
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 0 ], }, // 1
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 1 ], }, // 2
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 1 ], }, // 3
+		// right
+		{ pos: [ 1, - 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 0 ], }, // 4
+		{ pos: [ 1, - 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 0 ], }, // 5
+		{ pos: [ 1, 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 1 ], }, // 6
+		{ pos: [ 1, 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 1 ], }, // 7
+		// back
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 0 ], }, // 8
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 0 ], }, // 9
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 1 ], }, // 10
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 1 ], }, // 11
+		// left
+		{ pos: [ - 1, - 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 0 ], }, // 12
+		{ pos: [ - 1, - 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 0 ], }, // 13
+		{ pos: [ - 1, 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 1 ], }, // 14
+		{ pos: [ - 1, 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 1 ], }, // 15
+		// top
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 0 ], }, // 16
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 0 ], }, // 17
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 1 ], }, // 18
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 1 ], }, // 19
+		// bottom
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 0 ], }, // 20
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 0 ], }, // 21
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 1 ], }, // 22
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 1 ], }, // 23
+	];
+	const positions = [];
+	const normals = [];
+	const uvs = [];
+	for ( const vertex of vertices ) {
+
+		positions.push( ...vertex.pos );
+		normals.push( ...vertex.norm );
+		uvs.push( ...vertex.uv );
+
+	}
+
+	const geometry = new THREE.BufferGeometry();
+	const positionNumComponents = 3;
+	const normalNumComponents = 3;
+	const uvNumComponents = 2;
+	geometry.setAttribute(
+		'position',
+		new THREE.BufferAttribute( new Float32Array( positions ), positionNumComponents ) );
+	geometry.setAttribute(
+		'normal',
+		new THREE.BufferAttribute( new Float32Array( normals ), normalNumComponents ) );
+	geometry.setAttribute(
+		'uv',
+		new THREE.BufferAttribute( new Float32Array( uvs ), uvNumComponents ) );
+
+	geometry.setIndex( [
+		0, 1, 2, 2, 1, 3,
+		4, 5, 6, 6, 5, 7,
+		8, 9, 10, 10, 9, 11,
+		12, 13, 14, 14, 13, 15,
+		16, 17, 18, 18, 17, 19,
+		20, 21, 22, 22, 21, 23,
+	] );
+
+	const loader = new THREE.TextureLoader();
+	const texture = loader.load( 'resources/images/star.png' );
+	texture.colorSpace = THREE.SRGBColorSpace;
+
+	function makeInstance( geometry, color, x ) {
+
+		const material = new THREE.MeshPhongMaterial( { color, map: texture } );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x88FF88, 0 ),
+		makeInstance( geometry, 0x8888FF, - 4 ),
+		makeInstance( geometry, 0xFF8888, 4 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
 
-  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-
-  geometry.setIndex([
-     0,  1,  2,   2,  1,  3,
-     4,  5,  6,   6,  5,  7,
-     8,  9, 10,  10,  9, 11,
-    12, 13, 14,  14, 13, 15,
-    16, 17, 18,  18, 17, 19,
-    20, 21, 22,  22, 21, 23,
-  ]);
-
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/star.png');
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color, map: texture});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
+		}
 
-  const cubes = [
-    makeInstance(geometry, 0x88FF88,  0),
-    makeInstance(geometry, 0x8888FF, -4),
-    makeInstance(geometry, 0xFF8888,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		cubes.forEach( ( cube, ndx ) => {
 
-  function render(time) {
-    time *= 0.001;
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		} );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		renderer.render( scene, camera );
 
-    renderer.render(scene, camera);
+		requestAnimationFrame( render );
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 157 - 136
manual/examples/custom-buffergeometry-cube-typedarrays.html

@@ -36,151 +36,172 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  // NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
-  // Only trying to make it clear most vertices are unique
-  const vertices = [
-    // front
-    { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], }, // 0
-    { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], }, // 1
-    { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], }, // 2
-    { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], }, // 3
-    // right
-    { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], }, // 4
-    { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], }, // 5
-    { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], }, // 6
-    { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], }, // 7
-    // back
-    { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], }, // 8
-    { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], }, // 9
-    { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], }, // 10
-    { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], }, // 11
-    // left
-    { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], }, // 12
-    { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], }, // 13
-    { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], }, // 14
-    { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], }, // 15
-    // top
-    { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], }, // 16
-    { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], }, // 17
-    { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], }, // 18
-    { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], }, // 19
-    // bottom
-    { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], }, // 20
-    { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], }, // 21
-    { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], }, // 22
-    { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], }, // 23
-  ];
-  const numVertices = vertices.length;
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  const positions = new Float32Array(numVertices * positionNumComponents);
-  const normals = new Float32Array(numVertices * normalNumComponents);
-  const uvs = new Float32Array(numVertices * uvNumComponents);
-  let posNdx = 0;
-  let nrmNdx = 0;
-  let uvNdx = 0;
-  for (const vertex of vertices) {
-    positions.set(vertex.pos, posNdx);
-    normals.set(vertex.norm, nrmNdx);
-    uvs.set(vertex.uv, uvNdx);
-    posNdx += positionNumComponents;
-    nrmNdx += normalNumComponents;
-    uvNdx += uvNumComponents;
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 5;
+
+	const scene = new THREE.Scene();
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
+
+	}
+
+	// NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
+	// Only trying to make it clear most vertices are unique
+	const vertices = [
+		// front
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 0 ], }, // 0
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 0 ], }, // 1
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 1 ], }, // 2
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 1 ], }, // 3
+		// right
+		{ pos: [ 1, - 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 0 ], }, // 4
+		{ pos: [ 1, - 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 0 ], }, // 5
+		{ pos: [ 1, 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 1 ], }, // 6
+		{ pos: [ 1, 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 1 ], }, // 7
+		// back
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 0 ], }, // 8
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 0 ], }, // 9
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 1 ], }, // 10
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 1 ], }, // 11
+		// left
+		{ pos: [ - 1, - 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 0 ], }, // 12
+		{ pos: [ - 1, - 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 0 ], }, // 13
+		{ pos: [ - 1, 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 1 ], }, // 14
+		{ pos: [ - 1, 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 1 ], }, // 15
+		// top
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 0 ], }, // 16
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 0 ], }, // 17
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 1 ], }, // 18
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 1 ], }, // 19
+		// bottom
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 0 ], }, // 20
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 0 ], }, // 21
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 1 ], }, // 22
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 1 ], }, // 23
+	];
+	const numVertices = vertices.length;
+	const positionNumComponents = 3;
+	const normalNumComponents = 3;
+	const uvNumComponents = 2;
+	const positions = new Float32Array( numVertices * positionNumComponents );
+	const normals = new Float32Array( numVertices * normalNumComponents );
+	const uvs = new Float32Array( numVertices * uvNumComponents );
+	let posNdx = 0;
+	let nrmNdx = 0;
+	let uvNdx = 0;
+	for ( const vertex of vertices ) {
+
+		positions.set( vertex.pos, posNdx );
+		normals.set( vertex.norm, nrmNdx );
+		uvs.set( vertex.uv, uvNdx );
+		posNdx += positionNumComponents;
+		nrmNdx += normalNumComponents;
+		uvNdx += uvNumComponents;
+
+	}
+
+	const geometry = new THREE.BufferGeometry();
+	geometry.setAttribute(
+		'position',
+		new THREE.BufferAttribute( positions, positionNumComponents ) );
+	geometry.setAttribute(
+		'normal',
+		new THREE.BufferAttribute( normals, normalNumComponents ) );
+	geometry.setAttribute(
+		'uv',
+		new THREE.BufferAttribute( uvs, uvNumComponents ) );
+
+	geometry.setIndex( [
+		0, 1, 2, 2, 1, 3, // front
+		4, 5, 6, 6, 5, 7, // right
+		8, 9, 10, 10, 9, 11, // back
+		12, 13, 14, 14, 13, 15, // left
+		16, 17, 18, 18, 17, 19, // top
+		20, 21, 22, 22, 21, 23, // bottom
+	] );
+
+	const loader = new THREE.TextureLoader();
+	const texture = loader.load( 'resources/images/star.png' );
+	texture.colorSpace = THREE.SRGBColorSpace;
+
+	function makeInstance( geometry, color, x ) {
+
+		const material = new THREE.MeshPhongMaterial( { color, map: texture } );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x88FF88, 0 ),
+		makeInstance( geometry, 0x8888FF, - 4 ),
+		makeInstance( geometry, 0xFF8888, 4 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
 
-  const geometry = new THREE.BufferGeometry();
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(positions, positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(normals, normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(uvs, uvNumComponents));
-
-  geometry.setIndex([
-     0,  1,  2,   2,  1,  3,  // front
-     4,  5,  6,   6,  5,  7,  // right
-     8,  9, 10,  10,  9, 11,  // back
-    12, 13, 14,  14, 13, 15,  // left
-    16, 17, 18,  18, 17, 19,  // top
-    20, 21, 22,  22, 21, 23,  // bottom
-  ]);
-
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/star.png');
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color, map: texture});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
+		}
 
-  const cubes = [
-    makeInstance(geometry, 0x88FF88,  0),
-    makeInstance(geometry, 0x8888FF, -4),
-    makeInstance(geometry, 0xFF8888,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		cubes.forEach( ( cube, ndx ) => {
 
-  function render(time) {
-    time *= 0.001;
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		} );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		renderer.render( scene, camera );
 
-    renderer.render(scene, camera);
+		requestAnimationFrame( render );
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 159 - 138
manual/examples/custom-buffergeometry-cube.html

@@ -36,153 +36,174 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  // NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
-  // Only trying to make it clear most vertices are unique
-  const vertices = [
-    // front
-    { pos: [-1, -1,  1], norm: [ 0,  0,  1], uv: [0, 0], },
-    { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-    { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-
-    { pos: [-1,  1,  1], norm: [ 0,  0,  1], uv: [0, 1], },
-    { pos: [ 1, -1,  1], norm: [ 0,  0,  1], uv: [1, 0], },
-    { pos: [ 1,  1,  1], norm: [ 0,  0,  1], uv: [1, 1], },
-    // right
-    { pos: [ 1, -1,  1], norm: [ 1,  0,  0], uv: [0, 0], },
-    { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-    { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-
-    { pos: [ 1,  1,  1], norm: [ 1,  0,  0], uv: [0, 1], },
-    { pos: [ 1, -1, -1], norm: [ 1,  0,  0], uv: [1, 0], },
-    { pos: [ 1,  1, -1], norm: [ 1,  0,  0], uv: [1, 1], },
-    // back
-    { pos: [ 1, -1, -1], norm: [ 0,  0, -1], uv: [0, 0], },
-    { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-    { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-
-    { pos: [ 1,  1, -1], norm: [ 0,  0, -1], uv: [0, 1], },
-    { pos: [-1, -1, -1], norm: [ 0,  0, -1], uv: [1, 0], },
-    { pos: [-1,  1, -1], norm: [ 0,  0, -1], uv: [1, 1], },
-    // left
-    { pos: [-1, -1, -1], norm: [-1,  0,  0], uv: [0, 0], },
-    { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-    { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-
-    { pos: [-1,  1, -1], norm: [-1,  0,  0], uv: [0, 1], },
-    { pos: [-1, -1,  1], norm: [-1,  0,  0], uv: [1, 0], },
-    { pos: [-1,  1,  1], norm: [-1,  0,  0], uv: [1, 1], },
-    // top
-    { pos: [ 1,  1, -1], norm: [ 0,  1,  0], uv: [0, 0], },
-    { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-    { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-
-    { pos: [ 1,  1,  1], norm: [ 0,  1,  0], uv: [0, 1], },
-    { pos: [-1,  1, -1], norm: [ 0,  1,  0], uv: [1, 0], },
-    { pos: [-1,  1,  1], norm: [ 0,  1,  0], uv: [1, 1], },
-    // bottom
-    { pos: [ 1, -1,  1], norm: [ 0, -1,  0], uv: [0, 0], },
-    { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-    { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-
-    { pos: [ 1, -1, -1], norm: [ 0, -1,  0], uv: [0, 1], },
-    { pos: [-1, -1,  1], norm: [ 0, -1,  0], uv: [1, 0], },
-    { pos: [-1, -1, -1], norm: [ 0, -1,  0], uv: [1, 1], },
-  ];
-  const positions = [];
-  const normals = [];
-  const uvs = [];
-  for (const vertex of vertices) {
-    positions.push(...vertex.pos);
-    normals.push(...vertex.norm);
-    uvs.push(...vertex.uv);
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 5;
+
+	const scene = new THREE.Scene();
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
+
+	}
+
+	// NOT A GOOD EXAMPLE OF HOW TO MAKE A CUBE!
+	// Only trying to make it clear most vertices are unique
+	const vertices = [
+		// front
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 0 ], },
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 1 ], },
+
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 0, 1 ], },
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 0, 1 ], uv: [ 1, 1 ], },
+		// right
+		{ pos: [ 1, - 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 0 ], },
+		{ pos: [ 1, - 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 1 ], },
+
+		{ pos: [ 1, 1, 1 ], norm: [ 1, 0, 0 ], uv: [ 0, 1 ], },
+		{ pos: [ 1, - 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, 1, - 1 ], norm: [ 1, 0, 0 ], uv: [ 1, 1 ], },
+		// back
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 0 ], },
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 1 ], },
+
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 0, 1 ], },
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 0, - 1 ], uv: [ 1, 1 ], },
+		// left
+		{ pos: [ - 1, - 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 0 ], },
+		{ pos: [ - 1, - 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 1 ], },
+
+		{ pos: [ - 1, 1, - 1 ], norm: [ - 1, 0, 0 ], uv: [ 0, 1 ], },
+		{ pos: [ - 1, - 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, 1, 1 ], norm: [ - 1, 0, 0 ], uv: [ 1, 1 ], },
+		// top
+		{ pos: [ 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 0 ], },
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 1 ], },
+
+		{ pos: [ 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 0, 1 ], },
+		{ pos: [ - 1, 1, - 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, 1, 1 ], norm: [ 0, 1, 0 ], uv: [ 1, 1 ], },
+		// bottom
+		{ pos: [ 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 0 ], },
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 1 ], },
 
-  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-  const uvNumComponents = 2;
-  geometry.setAttribute(
-      'position',
-      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
-  geometry.setAttribute(
-      'uv',
-      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
-
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/star.png');
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color, map: texture});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
+		{ pos: [ 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 0, 1 ], },
+		{ pos: [ - 1, - 1, 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 0 ], },
+		{ pos: [ - 1, - 1, - 1 ], norm: [ 0, - 1, 0 ], uv: [ 1, 1 ], },
+	];
+	const positions = [];
+	const normals = [];
+	const uvs = [];
+	for ( const vertex of vertices ) {
 
-  const cubes = [
-    makeInstance(geometry, 0x88FF88,  0),
-    makeInstance(geometry, 0x8888FF, -4),
-    makeInstance(geometry, 0xFF8888,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+		positions.push( ...vertex.pos );
+		normals.push( ...vertex.norm );
+		uvs.push( ...vertex.uv );
 
-  function render(time) {
-    time *= 0.001;
+	}
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	const geometry = new THREE.BufferGeometry();
+	const positionNumComponents = 3;
+	const normalNumComponents = 3;
+	const uvNumComponents = 2;
+	geometry.setAttribute(
+		'position',
+		new THREE.BufferAttribute( new Float32Array( positions ), positionNumComponents ) );
+	geometry.setAttribute(
+		'normal',
+		new THREE.BufferAttribute( new Float32Array( normals ), normalNumComponents ) );
+	geometry.setAttribute(
+		'uv',
+		new THREE.BufferAttribute( new Float32Array( uvs ), uvNumComponents ) );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+	const loader = new THREE.TextureLoader();
+	const texture = loader.load( 'resources/images/star.png' );
+	texture.colorSpace = THREE.SRGBColorSpace;
 
-    renderer.render(scene, camera);
+	function makeInstance( geometry, color, x ) {
 
-    requestAnimationFrame(render);
-  }
+		const material = new THREE.MeshPhongMaterial( { color, map: texture } );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x88FF88, 0 ),
+		makeInstance( geometry, 0x8888FF, - 4 ),
+		makeInstance( geometry, 0xFF8888, 4 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 176 - 145
manual/examples/custom-buffergeometry-dynamic.html

@@ -36,162 +36,193 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 3;
-
-  const scene = new THREE.Scene();
-
-  function addLight(...pos) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...pos);
-    scene.add(light);
-  }
-  addLight(-1, 2, 4);
-  addLight( 2, -2, 3);
-
-  function makeSpherePositions(segmentsAround, segmentsDown) {
-    const numVertices = segmentsAround * segmentsDown * 6;
-    const numComponents = 3;
-    const positions = new Float32Array(numVertices * numComponents);
-    const indices = [];
-
-    const longHelper = new THREE.Object3D();
-    const latHelper = new THREE.Object3D();
-    const pointHelper = new THREE.Object3D();
-    longHelper.add(latHelper);
-    latHelper.add(pointHelper);
-    pointHelper.position.z = 1;
-    const temp = new THREE.Vector3();
-
-    function getPoint(lat, long) {
-      latHelper.rotation.x = lat;
-      longHelper.rotation.y = long;
-      longHelper.updateMatrixWorld(true);
-      return pointHelper.getWorldPosition(temp).toArray();
-    }
 
-    let posNdx = 0;
-    let ndx = 0;
-    for (let down = 0; down < segmentsDown; ++down) {
-      const v0 = down / segmentsDown;
-      const v1 = (down + 1) / segmentsDown;
-      const lat0 = (v0 - 0.5) * Math.PI;
-      const lat1 = (v1 - 0.5) * Math.PI;
-
-      for (let across = 0; across < segmentsAround; ++across) {
-        const u0 = across / segmentsAround;
-        const u1 = (across + 1) / segmentsAround;
-        const long0 = u0 * Math.PI * 2;
-        const long1 = u1 * Math.PI * 2;
-
-        positions.set(getPoint(lat0, long0), posNdx);  posNdx += numComponents;
-        positions.set(getPoint(lat1, long0), posNdx);  posNdx += numComponents;
-        positions.set(getPoint(lat0, long1), posNdx);  posNdx += numComponents;
-        positions.set(getPoint(lat1, long1), posNdx);  posNdx += numComponents;
-
-        indices.push(
-          ndx, ndx + 1, ndx + 2,
-          ndx + 2, ndx + 1, ndx + 3,
-        );
-        ndx += 4;
-      }
-    }
-    return {positions, indices};
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const segmentsAround = 24;
-  const segmentsDown = 16;
-  const {positions, indices} = makeSpherePositions(segmentsAround, segmentsDown);
-
-  const normals = positions.slice();
-
-  const geometry = new THREE.BufferGeometry();
-  const positionNumComponents = 3;
-  const normalNumComponents = 3;
-
-  const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents);
-  positionAttribute.setUsage(THREE.DynamicDrawUsage);
-  geometry.setAttribute(
-      'position',
-      positionAttribute);
-  geometry.setAttribute(
-      'normal',
-      new THREE.BufferAttribute(normals, normalNumComponents));
-  geometry.setIndex(indices);
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({
-      color,
-      side: THREE.DoubleSide,
-      shininess: 100,
-    });
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 100;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 3;
 
-  const cubes = [
-    makeInstance(geometry, 0xFF0000, 0),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	const scene = new THREE.Scene();
 
-  const temp = new THREE.Vector3();
+	function addLight( ...pos ) {
 
-  function render(time) {
-    time *= 0.001;
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( ...pos );
+		scene.add( light );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	}
 
-    for (let i = 0; i < positions.length; i += 3) {
-      const quad = (i / 12 | 0);
-      const ringId = quad / segmentsAround | 0;
-      const ringQuadId = quad % segmentsAround;
-      const ringU = ringQuadId / segmentsAround;
-      const angle = ringU * Math.PI * 2;
-      temp.fromArray(normals, i);
-      temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5));
-      temp.toArray(positions, i);
-    }
-    positionAttribute.needsUpdate = true;
+	addLight( - 1, 2, 4 );
+	addLight( 2, - 2, 3 );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = -0.2 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.y = rot;
-    });
+	function makeSpherePositions( segmentsAround, segmentsDown ) {
 
-    renderer.render(scene, camera);
+		const numVertices = segmentsAround * segmentsDown * 6;
+		const numComponents = 3;
+		const positions = new Float32Array( numVertices * numComponents );
+		const indices = [];
 
-    requestAnimationFrame(render);
-  }
+		const longHelper = new THREE.Object3D();
+		const latHelper = new THREE.Object3D();
+		const pointHelper = new THREE.Object3D();
+		longHelper.add( latHelper );
+		latHelper.add( pointHelper );
+		pointHelper.position.z = 1;
+		const temp = new THREE.Vector3();
+
+		function getPoint( lat, long ) {
+
+			latHelper.rotation.x = lat;
+			longHelper.rotation.y = long;
+			longHelper.updateMatrixWorld( true );
+			return pointHelper.getWorldPosition( temp ).toArray();
+
+		}
+
+		let posNdx = 0;
+		let ndx = 0;
+		for ( let down = 0; down < segmentsDown; ++ down ) {
+
+			const v0 = down / segmentsDown;
+			const v1 = ( down + 1 ) / segmentsDown;
+			const lat0 = ( v0 - 0.5 ) * Math.PI;
+			const lat1 = ( v1 - 0.5 ) * Math.PI;
+
+			for ( let across = 0; across < segmentsAround; ++ across ) {
+
+				const u0 = across / segmentsAround;
+				const u1 = ( across + 1 ) / segmentsAround;
+				const long0 = u0 * Math.PI * 2;
+				const long1 = u1 * Math.PI * 2;
+
+				positions.set( getPoint( lat0, long0 ), posNdx ); posNdx += numComponents;
+				positions.set( getPoint( lat1, long0 ), posNdx ); posNdx += numComponents;
+				positions.set( getPoint( lat0, long1 ), posNdx ); posNdx += numComponents;
+				positions.set( getPoint( lat1, long1 ), posNdx ); posNdx += numComponents;
+
+				indices.push(
+					ndx, ndx + 1, ndx + 2,
+					ndx + 2, ndx + 1, ndx + 3,
+				);
+				ndx += 4;
+
+			}
+
+		}
+
+		return { positions, indices };
+
+	}
+
+	const segmentsAround = 24;
+	const segmentsDown = 16;
+	const { positions, indices } = makeSpherePositions( segmentsAround, segmentsDown );
+
+	const normals = positions.slice();
+
+	const geometry = new THREE.BufferGeometry();
+	const positionNumComponents = 3;
+	const normalNumComponents = 3;
+
+	const positionAttribute = new THREE.BufferAttribute( positions, positionNumComponents );
+	positionAttribute.setUsage( THREE.DynamicDrawUsage );
+	geometry.setAttribute(
+		'position',
+		positionAttribute );
+	geometry.setAttribute(
+		'normal',
+		new THREE.BufferAttribute( normals, normalNumComponents ) );
+	geometry.setIndex( indices );
+
+	function makeInstance( geometry, color, x ) {
+
+		const material = new THREE.MeshPhongMaterial( {
+			color,
+			side: THREE.DoubleSide,
+			shininess: 100,
+		} );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0xFF0000, 0 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const temp = new THREE.Vector3();
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		for ( let i = 0; i < positions.length; i += 3 ) {
+
+			const quad = ( i / 12 | 0 );
+			const ringId = quad / segmentsAround | 0;
+			const ringQuadId = quad % segmentsAround;
+			const ringU = ringQuadId / segmentsAround;
+			const angle = ringU * Math.PI * 2;
+			temp.fromArray( normals, i );
+			temp.multiplyScalar( THREE.MathUtils.lerp( 1, 1.4, Math.sin( time + ringId + angle ) * .5 + .5 ) );
+			temp.toArray( positions, i );
+
+		}
+
+		positionAttribute.needsUpdate = true;
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = - 0.2 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 0 - 163
manual/examples/custom-geometry-cube-face-colors.html

@@ -1,163 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube - Face Colors</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-     // front
-     new THREE.Face3(0, 3, 2),
-     new THREE.Face3(0, 1, 3),
-     // right
-     new THREE.Face3(1, 7, 3),
-     new THREE.Face3(1, 5, 7),
-     // back
-     new THREE.Face3(5, 6, 7),
-     new THREE.Face3(5, 4, 6),
-     // left
-     new THREE.Face3(4, 2, 6),
-     new THREE.Face3(4, 0, 2),
-     // top
-     new THREE.Face3(2, 7, 6),
-     new THREE.Face3(2, 3, 7),
-     // bottom
-     new THREE.Face3(4, 1, 0),
-     new THREE.Face3(4, 5, 1),
-  );
-
-  geometry.faces[ 0].color = geometry.faces[ 1].color = new THREE.Color('red');
-  geometry.faces[ 2].color = geometry.faces[ 3].color = new THREE.Color('yellow');
-  geometry.faces[ 4].color = geometry.faces[ 5].color = new THREE.Color('green');
-  geometry.faces[ 6].color = geometry.faces[ 7].color = new THREE.Color('cyan');
-  geometry.faces[ 8].color = geometry.faces[ 9].color = new THREE.Color('blue');
-  geometry.faces[10].color = geometry.faces[11].color = new THREE.Color('magenta');
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshBasicMaterial({vertexColors: true});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x44FF44,  0),
-    makeInstance(geometry, 0x4444FF, -4),
-    makeInstance(geometry, 0xFF4444,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 158
manual/examples/custom-geometry-cube-face-normals.html

@@ -1,158 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube - face normals</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-     // front
-     new THREE.Face3(0, 3, 2),
-     new THREE.Face3(0, 1, 3),
-     // right
-     new THREE.Face3(1, 7, 3),
-     new THREE.Face3(1, 5, 7),
-     // back
-     new THREE.Face3(5, 6, 7),
-     new THREE.Face3(5, 4, 6),
-     // left
-     new THREE.Face3(4, 2, 6),
-     new THREE.Face3(4, 0, 2),
-     // top
-     new THREE.Face3(2, 7, 6),
-     new THREE.Face3(2, 3, 7),
-     // bottom
-     new THREE.Face3(4, 1, 0),
-     new THREE.Face3(4, 5, 1),
-  );
-
-  geometry.computeFaceNormals();
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x44FF44,  0),
-    makeInstance(geometry, 0x4444FF, -4),
-    makeInstance(geometry, 0xFF4444,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 182
manual/examples/custom-geometry-cube-texcoords.html

@@ -1,182 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube - Texture Coordinates</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-    // front
-    new THREE.Face3(0, 3, 2),
-    new THREE.Face3(0, 1, 3),
-    // right
-    new THREE.Face3(1, 7, 3),
-    new THREE.Face3(1, 5, 7),
-    // back
-    new THREE.Face3(5, 6, 7),
-    new THREE.Face3(5, 4, 6),
-    // left
-    new THREE.Face3(4, 2, 6),
-    new THREE.Face3(4, 0, 2),
-    // top
-    new THREE.Face3(2, 7, 6),
-    new THREE.Face3(2, 3, 7),
-    // bottom
-    new THREE.Face3(4, 1, 0),
-    new THREE.Face3(4, 5, 1),
-  );
-
-  geometry.faceVertexUvs[0].push(
-    // front
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-    // right
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-    // back
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-    // left
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-    // top
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-    // bottom
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 1), new THREE.Vector2(0, 1) ],
-    [ new THREE.Vector2(0, 0), new THREE.Vector2(1, 0), new THREE.Vector2(1, 1) ],
-);
-
-  geometry.computeFaceNormals();
-
-  const loader = new THREE.TextureLoader();
-  const texture = loader.load('resources/images/star.png');
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color, map: texture});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x88FF88,  0),
-    makeInstance(geometry, 0x8888FF, -4),
-    makeInstance(geometry, 0xFF8888,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 166
manual/examples/custom-geometry-cube-vertex-colors.html

@@ -1,166 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube - Vertex Colors</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-     // front
-     new THREE.Face3(0, 3, 2),
-     new THREE.Face3(0, 1, 3),
-     // right
-     new THREE.Face3(1, 7, 3),
-     new THREE.Face3(1, 5, 7),
-     // back
-     new THREE.Face3(5, 6, 7),
-     new THREE.Face3(5, 4, 6),
-     // left
-     new THREE.Face3(4, 2, 6),
-     new THREE.Face3(4, 0, 2),
-     // top
-     new THREE.Face3(2, 7, 6),
-     new THREE.Face3(2, 3, 7),
-     // bottom
-     new THREE.Face3(4, 1, 0),
-     new THREE.Face3(4, 5, 1),
-  );
-
-  geometry.faces.forEach((face, ndx) => {
-    face.vertexColors = [
-      (new THREE.Color()).setHSL(ndx / 12      , 1, 0.5),
-      (new THREE.Color()).setHSL(ndx / 12 + 0.1, 1, 0.5),
-      (new THREE.Color()).setHSL(ndx / 12 + 0.2, 1, 0.5),
-    ];
-  });
-
-  geometry.computeFaceNormals();
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshBasicMaterial({vertexColors: true});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x44FF44,  0),
-    makeInstance(geometry, 0x4444FF, -4),
-    makeInstance(geometry, 0xFF4444,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 158
manual/examples/custom-geometry-cube-vertex-normals.html

@@ -1,158 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube - Vertex Normals</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-     // front
-     new THREE.Face3(0, 3, 2),
-     new THREE.Face3(0, 1, 3),
-     // right
-     new THREE.Face3(1, 7, 3),
-     new THREE.Face3(1, 5, 7),
-     // back
-     new THREE.Face3(5, 6, 7),
-     new THREE.Face3(5, 4, 6),
-     // left
-     new THREE.Face3(4, 2, 6),
-     new THREE.Face3(4, 0, 2),
-     // top
-     new THREE.Face3(2, 7, 6),
-     new THREE.Face3(2, 3, 7),
-     // bottom
-     new THREE.Face3(4, 1, 0),
-     new THREE.Face3(4, 5, 1),
-  );
-
-  geometry.computeVertexNormals();
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x44FF44,  0),
-    makeInstance(geometry, 0x4444FF, -4),
-    makeInstance(geometry, 0xFF4444,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 156
manual/examples/custom-geometry-cube.html

@@ -1,156 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Cube</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 100;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 5;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
-
-  const geometry = new THREE.Geometry();
-  geometry.vertices.push(
-    new THREE.Vector3(-1, -1,  1),  // 0
-    new THREE.Vector3( 1, -1,  1),  // 1
-    new THREE.Vector3(-1,  1,  1),  // 2
-    new THREE.Vector3( 1,  1,  1),  // 3
-    new THREE.Vector3(-1, -1, -1),  // 4
-    new THREE.Vector3( 1, -1, -1),  // 5
-    new THREE.Vector3(-1,  1, -1),  // 6
-    new THREE.Vector3( 1,  1, -1),  // 7
-  );
-
-  /*
-       6----7
-      /|   /|
-     2----3 |
-     | |  | |
-     | 4--|-5
-     |/   |/
-     0----1
-  */
-
-  geometry.faces.push(
-     // front
-     new THREE.Face3(0, 3, 2),
-     new THREE.Face3(0, 1, 3),
-     // right
-     new THREE.Face3(1, 7, 3),
-     new THREE.Face3(1, 5, 7),
-     // back
-     new THREE.Face3(5, 6, 7),
-     new THREE.Face3(5, 4, 6),
-     // left
-     new THREE.Face3(4, 2, 6),
-     new THREE.Face3(4, 0, 2),
-     // top
-     new THREE.Face3(2, 7, 6),
-     new THREE.Face3(2, 3, 7),
-     // bottom
-     new THREE.Face3(4, 1, 0),
-     new THREE.Face3(4, 5, 1),
-  );
-
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshBasicMaterial({color});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-
-    cube.position.x = x;
-    return cube;
-  }
-
-  const cubes = [
-    makeInstance(geometry, 0x44FF44,  0),
-    makeInstance(geometry, 0x4444FF, -4),
-    makeInstance(geometry, 0xFF4444,  4),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render(time) {
-    time *= 0.001;
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 0 - 195
manual/examples/custom-geometry-heightmap.html

@@ -1,195 +0,0 @@
-<!-- Licensed under a BSD license. See license.html for license -->
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-    <title>Three.js - Custom Geometry - Heightmap</title>
-    <style>
-    html, body {
-        height: 100%;
-        margin: 0;
-    }
-    #c {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-    </style>
-  </head>
-  <body>
-    <canvas id="c"></canvas>
-  </body>
-<!-- Import maps polyfill -->
-<!-- Remove this when import maps will be widely supported -->
-<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
-
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js",
-    "three/addons/": "../../examples/jsm/"
-  }
-}
-</script>
-
-<script type="module">
-import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
-
-function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 200;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(20, 20, 20);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 0, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-
-  function addLight(...pos) {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(...pos);
-    scene.add(light);
-  }
-
-  addLight(-1, 2, 4);
-  addLight(1, 2, -2);
-
-  const imgLoader = new THREE.ImageLoader();
-  imgLoader.load('resources/images/heightmap-96x64.png', createHeightmap);
-
-  function createHeightmap(image) {
-    // extract the data from the image by drawing it to a canvas
-    // and calling getImageData
-    const ctx = document.createElement('canvas').getContext('2d');
-    const {width, height} = image;
-    ctx.canvas.width = width;
-    ctx.canvas.height = height;
-    ctx.drawImage(image, 0, 0);
-    const {data} = ctx.getImageData(0, 0, width, height);
-
-    const geometry = new THREE.Geometry();
-
-    const cellsAcross = width - 1;
-    const cellsDeep = height - 1;
-    for (let z = 0; z < cellsDeep; ++z) {
-      for (let x = 0; x < cellsAcross; ++x) {
-        // compute row offsets into the height data
-        // we multiply by 4 because the data is R,G,B,A but we
-        // only care about R
-        const base0 = (z * width + x) * 4;
-        const base1 = base0 + (width * 4);
-
-        // look up the height for the for points
-        // around this cell
-        const h00 = data[base0] / 32;
-        const h01 = data[base0 + 4] / 32;
-        const h10 = data[base1] / 32;
-        const h11 = data[base1 + 4] / 32;
-        // compute the average height
-        const hm = (h00 + h01 + h10 + h11) / 4;
-
-        // the corner positions
-        const x0 = x;
-        const x1 = x + 1;
-        const z0 = z;
-        const z1 = z + 1;
-
-        // remember the first index of these 5 vertices
-        const ndx = geometry.vertices.length;
-
-        // add the 4 corners for this cell and the midpoint
-        geometry.vertices.push(
-          new THREE.Vector3(x0, h00, z0),
-          new THREE.Vector3(x1, h01, z0),
-          new THREE.Vector3(x0, h10, z1),
-          new THREE.Vector3(x1, h11, z1),
-          new THREE.Vector3((x0 + x1) / 2, hm, (z0 + z1) / 2),
-        );
-
-        //      2----3
-        //      |\  /|
-        //      | \/4|
-        //      | /\ |
-        //      |/  \|
-        //      0----1
-
-        // create 4 triangles
-        geometry.faces.push(
-          new THREE.Face3(ndx    , ndx + 4, ndx + 1),
-          new THREE.Face3(ndx + 1, ndx + 4, ndx + 3),
-          new THREE.Face3(ndx + 3, ndx + 4, ndx + 2),
-          new THREE.Face3(ndx + 2, ndx + 4, ndx + 0),
-        );
-
-        // add the texture coordinates for each vertex of each face.
-        const u0 = x / cellsAcross;
-        const v0 = z / cellsDeep;
-        const u1 = (x + 1) / cellsAcross;
-        const v1 = (z + 1) / cellsDeep;
-        const um = (u0 + u1) / 2;
-        const vm = (v0 + v1) / 2;
-        geometry.faceVertexUvs[0].push(
-          [ new THREE.Vector2(u0, v0), new THREE.Vector2(um, vm), new THREE.Vector2(u1, v0) ],
-          [ new THREE.Vector2(u1, v0), new THREE.Vector2(um, vm), new THREE.Vector2(u1, v1) ],
-          [ new THREE.Vector2(u1, v1), new THREE.Vector2(um, vm), new THREE.Vector2(u0, v1) ],
-          [ new THREE.Vector2(u0, v1), new THREE.Vector2(um, vm), new THREE.Vector2(u0, v0) ],
-        );
-      }
-    }
-
-    geometry.computeFaceNormals();
-
-    // center the geometry
-    geometry.translate(width / -2, 0, height / -2);
-
-    const loader = new THREE.TextureLoader();
-    const texture = loader.load('resources/images/star.png');
-
-    const material = new THREE.MeshPhongMaterial({color: 'green', map: texture});
-
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
-  }
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
-
-  function render() {
-
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
-
-  requestAnimationFrame(render);
-}
-
-main();
-</script>
-</html>
-

+ 119 - 86
manual/examples/debug-js-clearing-logger.html

@@ -49,110 +49,143 @@
 import * as THREE from 'three';
 
 class ClearingLogger {
-  constructor(elem) {
-    this.elem = elem;
-    this.lines = [];
-  }
-  log(...args) {
-    this.lines.push([...args].join(' '));
-  }
-  render() {
-    this.elem.textContent = this.lines.join('\n');
-    this.lines = [];
-  }
+
+	constructor( elem ) {
+
+		this.elem = elem;
+		this.lines = [];
+
+	}
+	log( ...args ) {
+
+		this.lines.push( [ ...args ].join( ' ' ) );
+
+	}
+	render() {
+
+		this.elem.textContent = this.lines.join( '\n' );
+		this.lines = [];
+
+	}
+
 }
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
 
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 20;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('cyan');
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 20;
 
-  const geometry = new THREE.SphereGeometry();
-  const material = new THREE.MeshBasicMaterial({color: 'red'});
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'cyan' );
 
-  const things = [];
+	const geometry = new THREE.SphereGeometry();
+	const material = new THREE.MeshBasicMaterial( { color: 'red' } );
 
-  function rand(min, max) {
-    if (max === undefined) {
-      max = min;
-      min = 0;
-    }
-    return Math.random() * (max - min) + min;
-  }
+	const things = [];
 
-  function createThing() {
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    things.push({
-      mesh,
-      timer: 2,
-      velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
-    });
-  }
+	function rand( min, max ) {
 
-  canvas.addEventListener('click', createThing);
+		if ( max === undefined ) {
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+			max = min;
+			min = 0;
 
-  const logger = new ClearingLogger(document.querySelector('#debug pre'));
+		}
 
-  let then = 0;
-  function render(now) {
-    now *= 0.001;  // convert to seconds
-    const deltaTime = now - then;
-    then = now;
+		return Math.random() * ( max - min ) + min;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	}
 
-    logger.log('fps:', (1 / deltaTime).toFixed(1));
-    logger.log('num things:', things.length);
-    for (let i = 0; i < things.length;) {
-      const thing = things[i];
-      const mesh = thing.mesh;
-      const pos = mesh.position;
-      logger.log(
-          'timer:', thing.timer.toFixed(3),
-          'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
-      thing.timer -= deltaTime;
-      if (thing.timer <= 0) {
-        // remove this thing. Note we don't advance `i`
-        things.splice(i, 1);
-        scene.remove(mesh);
-      } else {
-        mesh.position.addScaledVector(thing.velocity, deltaTime);
-        ++i;
-      }
-    }
+	function createThing() {
 
-    renderer.render(scene, camera);
-    logger.render();
+		const mesh = new THREE.Mesh( geometry, material );
+		scene.add( mesh );
+		things.push( {
+			mesh,
+			timer: 2,
+			velocity: new THREE.Vector3( rand( - 5, 5 ), rand( - 5, 5 ), rand( - 5, 5 ) ),
+		} );
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	canvas.addEventListener( 'click', createThing );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const logger = new ClearingLogger( document.querySelector( '#debug pre' ) );
+
+	let then = 0;
+	function render( now ) {
+
+		now *= 0.001; // convert to seconds
+		const deltaTime = now - then;
+		then = now;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		logger.log( 'fps:', ( 1 / deltaTime ).toFixed( 1 ) );
+		logger.log( 'num things:', things.length );
+		for ( let i = 0; i < things.length; ) {
+
+			const thing = things[ i ];
+			const mesh = thing.mesh;
+			const pos = mesh.position;
+			logger.log(
+				'timer:', thing.timer.toFixed( 3 ),
+				'pos:', pos.x.toFixed( 3 ), pos.y.toFixed( 3 ), pos.z.toFixed( 3 ) );
+			thing.timer -= deltaTime;
+			if ( thing.timer <= 0 ) {
+
+				// remove this thing. Note we don't advance `i`
+				things.splice( i, 1 );
+				scene.remove( mesh );
+
+			} else {
+
+				mesh.position.addScaledVector( thing.velocity, deltaTime );
+				++ i;
+
+			}
+
+		}
+
+		renderer.render( scene, camera );
+		logger.render();
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 63 - 51
manual/examples/debug-js-html-elements.html

@@ -50,64 +50,76 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 20;
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('red');
-
-  const geometry = new THREE.SphereGeometry();
-  const material = new THREE.MeshBasicMaterial({color: 'yellow'});
-
-  const mesh = new THREE.Mesh(geometry, material);
-  scene.add(mesh);
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
 
-  const xElem = document.querySelector('#x');
-  const yElem = document.querySelector('#y');
-  const zElem = document.querySelector('#z');
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function render(time) {
-    time *= 0.001;  // convert to seconds
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 20;
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'red' );
 
-    mesh.position.set(
-      Math.sin(time * 1.2) * 5,
-      Math.sin(time * 1.1) * 5,
-      Math.sin(time * 1.3) * 10,
-    );
-    xElem.textContent = mesh.position.x.toFixed(3);
-    yElem.textContent = mesh.position.y.toFixed(3);
-    zElem.textContent = mesh.position.z.toFixed(3);
+	const geometry = new THREE.SphereGeometry();
+	const material = new THREE.MeshBasicMaterial( { color: 'yellow' } );
 
-    renderer.render(scene, camera);
+	const mesh = new THREE.Mesh( geometry, material );
+	scene.add( mesh );
 
-    requestAnimationFrame(render);
-  }
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	const xElem = document.querySelector( '#x' );
+	const yElem = document.querySelector( '#y' );
+	const zElem = document.querySelector( '#z' );
+
+	function render( time ) {
+
+		time *= 0.001; // convert to seconds
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		mesh.position.set(
+			Math.sin( time * 1.2 ) * 5,
+			Math.sin( time * 1.1 ) * 5,
+			Math.sin( time * 1.3 ) * 10,
+		);
+		xElem.textContent = mesh.position.x.toFixed( 3 );
+		yElem.textContent = mesh.position.y.toFixed( 3 );
+		zElem.textContent = mesh.position.z.toFixed( 3 );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 145 - 102
manual/examples/debug-js-params.html

@@ -73,137 +73,180 @@ import * as THREE from 'three';
   *      name: 'gman',
   *    }
   */
-  function getQuery() {
-  const params = {};
-  const q = (window.location.search || '').substring(1);
-  q.split('&').forEach((pair) => {
-    const keyValue = pair.split('=').map(decodeURIComponent);
-    params[keyValue[0]] = keyValue[1];
-  });
-  return params;
+function getQuery() {
+
+	const params = {};
+	const q = ( window.location.search || '' ).substring( 1 );
+	q.split( '&' ).forEach( ( pair ) => {
+
+		const keyValue = pair.split( '=' ).map( decodeURIComponent );
+		params[ keyValue[ 0 ] ] = keyValue[ 1 ];
+
+	} );
+	return params;
+
 }
 
 class DummyLogger {
-  log() {}
-  render() {}
+
+	log() {}
+	render() {}
+
 }
 
 class ClearingLogger {
-  constructor(elem) {
-    this.elem = elem;
-    this.lines = [];
-  }
-  log(...args) {
-    this.lines.push([...args].join(' '));
-  }
-  render() {
-    this.elem.textContent = this.lines.join('\n');
-    this.lines = [];
-  }
+
+	constructor( elem ) {
+
+		this.elem = elem;
+		this.lines = [];
+
+	}
+	log( ...args ) {
+
+		this.lines.push( [ ...args ].join( ' ' ) );
+
+	}
+	render() {
+
+		this.elem.textContent = this.lines.join( '\n' );
+		this.lines = [];
+
+	}
+
 }
 
 const query = getQuery();
 const debug = query.debug === 'true';
 const logger = debug
-   ? new ClearingLogger(document.querySelector('#debug pre'))
-   : new DummyLogger();
-if (debug) {
-  document.querySelector('#debug').style.display = '';
+	? new ClearingLogger( document.querySelector( '#debug pre' ) )
+	: new DummyLogger();
+if ( debug ) {
+
+	document.querySelector( '#debug' ).style.display = '';
+
 }
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
 
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 50;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 20;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('cyan');
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 50;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 20;
 
-  const geometry = new THREE.SphereGeometry();
-  const material = new THREE.MeshBasicMaterial({color: 'red'});
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'cyan' );
 
-  const things = [];
+	const geometry = new THREE.SphereGeometry();
+	const material = new THREE.MeshBasicMaterial( { color: 'red' } );
 
-  function rand(min, max) {
-    if (max === undefined) {
-      max = min;
-      min = 0;
-    }
-    return Math.random() * (max - min) + min;
-  }
+	const things = [];
 
-  function createThing() {
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    things.push({
-      mesh,
-      timer: 2,
-      velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
-    });
-  }
+	function rand( min, max ) {
 
-  canvas.addEventListener('click', createThing);
+		if ( max === undefined ) {
 
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+			max = min;
+			min = 0;
 
-  let then = 0;
-  function render(now) {
-    now *= 0.001;  // convert to seconds
-    const deltaTime = now - then;
-    then = now;
+		}
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+		return Math.random() * ( max - min ) + min;
 
-    if (things.length === 0) {
-      createThing();
-    }
+	}
 
-    logger.log('fps:', (1 / deltaTime).toFixed(1));
-    logger.log('num things:', things.length);
-    for (let i = 0; i < things.length;) {
-      const thing = things[i];
-      const mesh = thing.mesh;
-      const pos = mesh.position;
-      logger.log(
-          'timer:', thing.timer.toFixed(3),
-          'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
-      thing.timer -= deltaTime;
-      if (thing.timer <= 0) {
-        // remove this thing. Note we don't advance `i`
-        things.splice(i, 1);
-        scene.remove(mesh);
-      } else {
-        mesh.position.addScaledVector(thing.velocity, deltaTime);
-        ++i;
-      }
-    }
+	function createThing() {
 
-    renderer.render(scene, camera);
-    logger.render();
+		const mesh = new THREE.Mesh( geometry, material );
+		scene.add( mesh );
+		things.push( {
+			mesh,
+			timer: 2,
+			velocity: new THREE.Vector3( rand( - 5, 5 ), rand( - 5, 5 ), rand( - 5, 5 ) ),
+		} );
 
-    requestAnimationFrame(render);
-  }
+	}
+
+	canvas.addEventListener( 'click', createThing );
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	let then = 0;
+	function render( now ) {
+
+		now *= 0.001; // convert to seconds
+		const deltaTime = now - then;
+		then = now;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		if ( things.length === 0 ) {
+
+			createThing();
+
+		}
+
+		logger.log( 'fps:', ( 1 / deltaTime ).toFixed( 1 ) );
+		logger.log( 'num things:', things.length );
+		for ( let i = 0; i < things.length; ) {
+
+			const thing = things[ i ];
+			const mesh = thing.mesh;
+			const pos = mesh.position;
+			logger.log(
+				'timer:', thing.timer.toFixed( 3 ),
+				'pos:', pos.x.toFixed( 3 ), pos.y.toFixed( 3 ), pos.z.toFixed( 3 ) );
+			thing.timer -= deltaTime;
+			if ( thing.timer <= 0 ) {
+
+				// remove this thing. Note we don't advance `i`
+				things.splice( i, 1 );
+				scene.remove( mesh );
+
+			} else {
+
+				mesh.position.addScaledVector( thing.velocity, deltaTime );
+				++ i;
+
+			}
+
+		}
+
+		renderer.render( scene, camera );
+		logger.render();
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 134 - 117
manual/examples/debugging-mcve.html

@@ -16,128 +16,145 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
+import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 45;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 10000;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.set(0, 1000, 2000);
-
-  const controls = new OrbitControls(camera, canvas);
-  controls.target.set(0, 5, 0);
-  controls.update();
-
-  const scene = new THREE.Scene();
-  scene.background = new THREE.Color('black');
-
-  scene.add(new THREE.GridHelper(5000, 10));
-
-  let curve;
-  let curveObject;
-  {
-    const controlPoints = [
-      [1.118281, 5.115846, -3.681386],
-      [3.948875, 5.115846, -3.641834],
-      [3.960072, 5.115846, -0.240352],
-      [3.985447, 5.115846, 4.585005],
-      [-3.793631, 5.115846, 4.585006],
-      [-3.826839, 5.115846, -14.736200],
-      [-14.542292, 5.115846, -14.765865],
-      [-14.520929, 5.115846, -3.627002],
-      [-5.452815, 5.115846, -3.634418],
-      [-5.467251, 5.115846, 4.549161],
-      [-13.266233, 5.115846, 4.567083],
-      [-13.250067, 5.115846, -13.499271],
-      [4.081842, 5.115846, -13.435463],
-      [4.125436, 5.115846, -5.334928],
-      [-14.521364, 5.115846, -5.239871],
-      [-14.510466, 5.115846, 5.486727],
-      [5.745666, 5.115846, 5.510492],
-      [5.787942, 5.115846, -14.728308],
-      [-5.423720, 5.115846, -14.761919],
-      [-5.373599, 5.115846, -3.704133],
-      [1.004861, 5.115846, -3.641834],
-    ];
-    const p0 = new THREE.Vector3();
-    const p1 = new THREE.Vector3();
-    curve = new THREE.CatmullRomCurve3(
-      controlPoints.map((p, ndx) => {
-        p0.set(...p);
-        p1.set(...controlPoints[(ndx + 1) % controlPoints.length]);
-        return [
-          (new THREE.Vector3()).copy(p0),
-          (new THREE.Vector3()).lerpVectors(p0, p1, 0.1),
-          (new THREE.Vector3()).lerpVectors(p0, p1, 0.9),
-        ];
-      }).flat(),
-      true,
-    );
-    {
-      const points = curve.getPoints(250);
-      const geometry = new THREE.BufferGeometry().setFromPoints(points);
-      const material = new THREE.LineBasicMaterial({color: 0xff0000});
-      curveObject = new THREE.Line(geometry, material);
-      curveObject.scale.set(100, 100, 100);
-      curveObject.position.y = -621;
-      material.depthTest = false;
-      curveObject.renderOrder = 1;
-      scene.add(curveObject);
-    }
-  }
-
-  const geometry = new THREE.BoxGeometry(100, 100, 300);
-  const material = new THREE.MeshBasicMaterial({color: 'cyan'});
-  const cars = [];
-  for (let i = 0; i < 10; ++i) {
-    const mesh = new THREE.Mesh(geometry, material);
-    scene.add(mesh);
-    cars.push(mesh);
-  }
-
-  // create 2 Vector3s we can use for path calculations
-  const carPosition = new THREE.Vector3();
-  const carTarget = new THREE.Vector3();
-
-  function render(time) {
-    time *= 0.001;  // convert to seconds
-
-    {
-      const pathTime = time * .01;
-      const targetOffset = 0.01;
-      cars.forEach((car, ndx) => {
-        // a number between 0 and 1 to evenly space the cars
-        const u = pathTime + ndx / cars.length;
 
-        // get the first point
-        curve.getPointAt(u % 1, carPosition);
-        carPosition.applyMatrix4(curveObject.matrixWorld);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+
+	const fov = 45;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 10000;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.set( 0, 1000, 2000 );
+
+	const controls = new OrbitControls( camera, canvas );
+	controls.target.set( 0, 5, 0 );
+	controls.update();
+
+	const scene = new THREE.Scene();
+	scene.background = new THREE.Color( 'black' );
+
+	scene.add( new THREE.GridHelper( 5000, 10 ) );
+
+	let curve;
+	let curveObject;
+	{
+
+		const controlPoints = [
+			[ 1.118281, 5.115846, - 3.681386 ],
+			[ 3.948875, 5.115846, - 3.641834 ],
+			[ 3.960072, 5.115846, - 0.240352 ],
+			[ 3.985447, 5.115846, 4.585005 ],
+			[ - 3.793631, 5.115846, 4.585006 ],
+			[ - 3.826839, 5.115846, - 14.736200 ],
+			[ - 14.542292, 5.115846, - 14.765865 ],
+			[ - 14.520929, 5.115846, - 3.627002 ],
+			[ - 5.452815, 5.115846, - 3.634418 ],
+			[ - 5.467251, 5.115846, 4.549161 ],
+			[ - 13.266233, 5.115846, 4.567083 ],
+			[ - 13.250067, 5.115846, - 13.499271 ],
+			[ 4.081842, 5.115846, - 13.435463 ],
+			[ 4.125436, 5.115846, - 5.334928 ],
+			[ - 14.521364, 5.115846, - 5.239871 ],
+			[ - 14.510466, 5.115846, 5.486727 ],
+			[ 5.745666, 5.115846, 5.510492 ],
+			[ 5.787942, 5.115846, - 14.728308 ],
+			[ - 5.423720, 5.115846, - 14.761919 ],
+			[ - 5.373599, 5.115846, - 3.704133 ],
+			[ 1.004861, 5.115846, - 3.641834 ],
+		];
+		const p0 = new THREE.Vector3();
+		const p1 = new THREE.Vector3();
+		curve = new THREE.CatmullRomCurve3(
+			controlPoints.map( ( p, ndx ) => {
+
+				p0.set( ...p );
+				p1.set( ...controlPoints[ ( ndx + 1 ) % controlPoints.length ] );
+				return [
+					( new THREE.Vector3() ).copy( p0 ),
+					( new THREE.Vector3() ).lerpVectors( p0, p1, 0.1 ),
+					( new THREE.Vector3() ).lerpVectors( p0, p1, 0.9 ),
+				];
+
+			} ).flat(),
+			true,
+		);
+		{
+
+			const points = curve.getPoints( 250 );
+			const geometry = new THREE.BufferGeometry().setFromPoints( points );
+			const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
+			curveObject = new THREE.Line( geometry, material );
+			curveObject.scale.set( 100, 100, 100 );
+			curveObject.position.y = - 621;
+			material.depthTest = false;
+			curveObject.renderOrder = 1;
+			scene.add( curveObject );
+
+		}
+
+	}
+
+	const geometry = new THREE.BoxGeometry( 100, 100, 300 );
+	const material = new THREE.MeshBasicMaterial( { color: 'cyan' } );
+	const cars = [];
+	for ( let i = 0; i < 10; ++ i ) {
+
+		const mesh = new THREE.Mesh( geometry, material );
+		scene.add( mesh );
+		cars.push( mesh );
+
+	}
+
+	// create 2 Vector3s we can use for path calculations
+	const carPosition = new THREE.Vector3();
+	const carTarget = new THREE.Vector3();
+
+	function render( time ) {
+
+		time *= 0.001; // convert to seconds
+
+		{
+
+			const pathTime = time * .01;
+			const targetOffset = 0.01;
+			cars.forEach( ( car, ndx ) => {
+
+				// a number between 0 and 1 to evenly space the cars
+				const u = pathTime + ndx / cars.length;
+
+				// get the first point
+				curve.getPointAt( u % 1, carPosition );
+				carPosition.applyMatrix4( curveObject.matrixWorld );
+
+				// get a second point slightly further down the curve
+				curve.getPointAt( ( u + targetOffset ) % 1, carTarget );
+				carTarget.applyMatrix4( curveObject.matrixWorld );
+
+				// put the car at the first point (temporarily)
+				car.position.copy( carPosition );
+				// point the car the second point
+				car.lookAt( carTarget );
+
+				// put the car between the 2 points
+				car.position.lerpVectors( carPosition, carTarget, 0.5 );
+
+			} );
+
+		}
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
 
-        // get a second point slightly further down the curve
-        curve.getPointAt((u + targetOffset) % 1, carTarget);
-        carTarget.applyMatrix4(curveObject.matrixWorld);
-
-        // put the car at the first point (temporarily)
-        car.position.copy(carPosition);
-        // point the car the second point
-        car.lookAt(carTarget);
-
-        // put the car between the 2 points
-        car.position.lerpVectors(carPosition, carTarget, 0.5);
-      });
-    }
-
-    renderer.render(scene, camera);
-
-    requestAnimationFrame(render);
-  }
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 145 - 109
manual/examples/fog-gui.html

@@ -35,131 +35,167 @@
 
 <script type="module">
 import * as THREE from 'three';
-import {GUI} from 'three/addons/libs/lil-gui.module.min.js';
+import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-  const gui = new GUI();
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  // We use this class to pass to lil-gui
-  // so when it manipulates near or far
-  // near is never > far and far is never < near
-  // Also when lil-gui maniplates color we'll
-  // update both the fog and background colors.
-  class FogGUIHelper {
-    constructor(fog, backgroundColor) {
-      this.fog = fog;
-      this.backgroundColor = backgroundColor;
-    }
-    get near() {
-      return this.fog.near;
-    }
-    set near(v) {
-      this.fog.near = v;
-      this.fog.far = Math.max(this.fog.far, v);
-    }
-    get far() {
-      return this.fog.far;
-    }
-    set far(v) {
-      this.fog.far = v;
-      this.fog.near = Math.min(this.fog.near, v);
-    }
-    get color() {
-      return `#${this.fog.color.getHexString()}`;
-    }
-    set color(hexString) {
-      this.fog.color.set(hexString);
-      this.backgroundColor.set(hexString);
-    }
-  }
 
-  {
-    const near = 1;
-    const far = 2;
-    const color = 'lightblue';
-    scene.fog = new THREE.Fog(color, near, far);
-    scene.background = new THREE.Color(color);
-
-    const fogGUIHelper = new FogGUIHelper(scene.fog, scene.background);
-    gui.add(fogGUIHelper, 'near', near, far).listen();
-    gui.add(fogGUIHelper, 'far', near, far).listen();
-    gui.addColor(fogGUIHelper, 'color');
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
+	const gui = new GUI();
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const scene = new THREE.Scene();
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	// We use this class to pass to lil-gui
+	// so when it manipulates near or far
+	// near is never > far and far is never < near
+	// Also when lil-gui maniplates color we'll
+	// update both the fog and background colors.
+	class FogGUIHelper {
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+		constructor( fog, backgroundColor ) {
 
-    cube.position.x = x;
+			this.fog = fog;
+			this.backgroundColor = backgroundColor;
 
-    return cube;
-  }
+		}
+		get near() {
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+			return this.fog.near;
 
-  function render(time) {
-    time *= 0.001;
+		}
+		set near( v ) {
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+			this.fog.near = v;
+			this.fog.far = Math.max( this.fog.far, v );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+		}
+		get far() {
 
-    renderer.render(scene, camera);
+			return this.fog.far;
 
-    requestAnimationFrame(render);
-  }
+		}
+		set far( v ) {
+
+			this.fog.far = v;
+			this.fog.near = Math.min( this.fog.near, v );
+
+		}
+		get color() {
+
+			return `#${this.fog.color.getHexString()}`;
+
+		}
+		set color( hexString ) {
+
+			this.fog.color.set( hexString );
+			this.backgroundColor.set( hexString );
+
+		}
+
+	}
+
+	{
+
+		const near = 1;
+		const far = 2;
+		const color = 'lightblue';
+		scene.fog = new THREE.Fog( color, near, far );
+		scene.background = new THREE.Color( color );
+
+		const fogGUIHelper = new FogGUIHelper( scene.fog, scene.background );
+		gui.add( fogGUIHelper, 'near', near, far ).listen();
+		gui.add( fogGUIHelper, 'far', near, far ).listen();
+		gui.addColor( fogGUIHelper, 'color' );
+
+	}
+
+	{
+
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
+
+	}
+
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
+
+	function makeInstance( geometry, color, x ) {
+
+		const material = new THREE.MeshPhongMaterial( { color } );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 90 - 70
manual/examples/fog.html

@@ -36,89 +36,109 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const near = 1;
-    const far = 2;
-    const color = 'lightblue';
-    scene.fog = new THREE.Fog(color, near, far);
-    scene.background = new THREE.Color(color);
-  }
 
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const scene = new THREE.Scene();
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	{
 
-    cube.position.x = x;
+		const near = 1;
+		const far = 2;
+		const color = 'lightblue';
+		scene.fog = new THREE.Fog( color, near, far );
+		scene.background = new THREE.Color( color );
 
-    return cube;
-  }
+	}
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
-
-  function resizeRendererToDisplaySize(renderer) {
-    const canvas = renderer.domElement;
-    const width = canvas.clientWidth;
-    const height = canvas.clientHeight;
-    const needResize = canvas.width !== width || canvas.height !== height;
-    if (needResize) {
-      renderer.setSize(width, height, false);
-    }
-    return needResize;
-  }
+	{
 
-  function render(time) {
-    time *= 0.001;
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-    if (resizeRendererToDisplaySize(renderer)) {
-      const canvas = renderer.domElement;
-      camera.aspect = canvas.clientWidth / canvas.clientHeight;
-      camera.updateProjectionMatrix();
-    }
+	}
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    renderer.render(scene, camera);
+	function makeInstance( geometry, color, x ) {
 
-    requestAnimationFrame(render);
-  }
+		const material = new THREE.MeshPhongMaterial( { color } );
+
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	function resizeRendererToDisplaySize( renderer ) {
+
+		const canvas = renderer.domElement;
+		const width = canvas.clientWidth;
+		const height = canvas.clientHeight;
+		const needResize = canvas.width !== width || canvas.height !== height;
+		if ( needResize ) {
+
+			renderer.setSize( width, height, false );
+
+		}
+
+		return needResize;
+
+	}
+
+	function render( time ) {
+
+		time *= 0.001;
+
+		if ( resizeRendererToDisplaySize( renderer ) ) {
+
+			const canvas = renderer.domElement;
+			camera.aspect = canvas.clientWidth / canvas.clientHeight;
+			camera.updateProjectionMatrix();
+
+		}
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
-  requestAnimationFrame(render);
 }
 
 main();

+ 58 - 47
manual/examples/fundamentals-3-cubes.html

@@ -25,63 +25,74 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  function makeInstance(geometry, color, x) {
-    const material = new THREE.MeshPhongMaterial({color});
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-    const cube = new THREE.Mesh(geometry, material);
-    scene.add(cube);
+	const scene = new THREE.Scene();
 
-    cube.position.x = x;
+	{
 
-    return cube;
-  }
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-  const cubes = [
-    makeInstance(geometry, 0x44aa88,  0),
-    makeInstance(geometry, 0x8844aa, -2),
-    makeInstance(geometry, 0xaa8844,  2),
-  ];
+	}
 
-  function render(time) {
-    time *= 0.001;  // convert time to seconds
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-    cubes.forEach((cube, ndx) => {
-      const speed = 1 + ndx * .1;
-      const rot = time * speed;
-      cube.rotation.x = rot;
-      cube.rotation.y = rot;
-    });
+	function makeInstance( geometry, color, x ) {
 
-    renderer.render(scene, camera);
+		const material = new THREE.MeshPhongMaterial( { color } );
 
-    requestAnimationFrame(render);
-  }
-  requestAnimationFrame(render);
+		const cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+
+		cube.position.x = x;
+
+		return cube;
+
+	}
+
+	const cubes = [
+		makeInstance( geometry, 0x44aa88, 0 ),
+		makeInstance( geometry, 0x8844aa, - 2 ),
+		makeInstance( geometry, 0xaa8844, 2 ),
+	];
+
+	function render( time ) {
+
+		time *= 0.001; // convert time to seconds
+
+		cubes.forEach( ( cube, ndx ) => {
+
+			const speed = 1 + ndx * .1;
+			const rot = time * speed;
+			cube.rotation.x = rot;
+			cube.rotation.y = rot;
+
+		} );
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
 }
 

+ 29 - 24
manual/examples/fundamentals-with-animation.html

@@ -25,39 +25,44 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
 
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const scene = new THREE.Scene();
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const scene = new THREE.Scene();
 
-  const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
+	const material = new THREE.MeshBasicMaterial( { color: 0x44aa88 } ); // greenish blue
 
-  function render(time) {
-    time *= 0.001;  // convert time to seconds
+	const cube = new THREE.Mesh( geometry, material );
+	scene.add( cube );
 
-    cube.rotation.x = time;
-    cube.rotation.y = time;
+	function render( time ) {
 
-    renderer.render(scene, camera);
+		time *= 0.001; // convert time to seconds
 
-    requestAnimationFrame(render);
-  }
-  requestAnimationFrame(render);
+		cube.rotation.x = time;
+		cube.rotation.y = time;
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
 }
 

+ 41 - 34
manual/examples/fundamentals-with-light.html

@@ -25,47 +25,54 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
-
-  const scene = new THREE.Scene();
-
-  {
-    const color = 0xFFFFFF;
-    const intensity = 1;
-    const light = new THREE.DirectionalLight(color, intensity);
-    light.position.set(-1, 2, 4);
-    scene.add(light);
-  }
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const material = new THREE.MeshPhongMaterial({color: 0x44aa88});  // greenish blue
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
+	const scene = new THREE.Scene();
 
-  function render(time) {
-    time *= 0.001;  // convert time to seconds
+	{
 
-    cube.rotation.x = time;
-    cube.rotation.y = time;
+		const color = 0xFFFFFF;
+		const intensity = 3;
+		const light = new THREE.DirectionalLight( color, intensity );
+		light.position.set( - 1, 2, 4 );
+		scene.add( light );
 
-    renderer.render(scene, camera);
+	}
 
-    requestAnimationFrame(render);
-  }
-  requestAnimationFrame(render);
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
+
+	const material = new THREE.MeshPhongMaterial( { color: 0x44aa88 } ); // greenish blue
+
+	const cube = new THREE.Mesh( geometry, material );
+	scene.add( cube );
+
+	function render( time ) {
+
+		time *= 0.001; // convert time to seconds
+
+		cube.rotation.x = time;
+		cube.rotation.y = time;
+
+		renderer.render( scene, camera );
+
+		requestAnimationFrame( render );
+
+	}
+
+	requestAnimationFrame( render );
 
 }
 

+ 20 - 17
manual/examples/fundamentals.html

@@ -25,29 +25,32 @@
 import * as THREE from 'three';
 
 function main() {
-  const canvas = document.querySelector('#c');
-  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
 
-  const fov = 75;
-  const aspect = 2;  // the canvas default
-  const near = 0.1;
-  const far = 5;
-  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
-  camera.position.z = 2;
+	const canvas = document.querySelector( '#c' );
+	const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
+	renderer.useLegacyLights = false;
 
-  const scene = new THREE.Scene();
+	const fov = 75;
+	const aspect = 2; // the canvas default
+	const near = 0.1;
+	const far = 5;
+	const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+	camera.position.z = 2;
 
-  const boxWidth = 1;
-  const boxHeight = 1;
-  const boxDepth = 1;
-  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
+	const scene = new THREE.Scene();
 
-  const material = new THREE.MeshBasicMaterial({color: 0x44aa88});  // greenish blue
+	const boxWidth = 1;
+	const boxHeight = 1;
+	const boxDepth = 1;
+	const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth );
 
-  const cube = new THREE.Mesh(geometry, material);
-  scene.add(cube);
+	const material = new THREE.MeshBasicMaterial( { color: 0x44aa88 } ); // greenish blue
+
+	const cube = new THREE.Mesh( geometry, material );
+	scene.add( cube );
+
+	renderer.render( scene, camera );
 
-  renderer.render(scene, camera);
 }
 
 main();

+ 1 - 2
manual/fr/custom-buffergeometry.html

@@ -436,8 +436,7 @@ positionAttribute.needsUpdate = true;
 make your own geometry and how to dynamically update the contents of a
 <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>.</p>
 <!-- needed in English only to prevent warning from outdated translations -->
-<p><a href="resources/threejs-geometry.svg"></a>
-<a href="custom-geometry.html"></a></p>
+<p><a href="resources/threejs-geometry.svg"></a></p>
 <p><canvas id="c"></canvas></p>
 <script type="module" src="../resources/threejs-custom-buffergeometry.js"></script>
 

+ 1 - 1
manual/fr/fundamentals.html

@@ -272,7 +272,7 @@ Three.js propose plusieurs type de lumière que nous détaillerons dans
 <a href="lights.html">un futur article</a>. Pour le moment, créons une lumière directionnelle.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);

+ 4 - 3
manual/ja/backgrounds.html

@@ -68,6 +68,7 @@ body {
 <p>THREE.jsで簡単にできます。シーンの背景をテクスチャに設定すれば良いのです。</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const bgTexture = loader.load('resources/images/daikanyama.jpg');
+bgTexture.colorSpace = THREE.SRGBColorSpace;
 scene.background = bgTexture;
 </pre>
 <p>このようになります。</p>
@@ -223,9 +224,9 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +  const texture = loader.load(
 +    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
 +    () =&gt; {
-+      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-+      rt.fromEquirectangularTexture(renderer, texture);
-+      scene.background = rt.texture;
++      texture.mapping = THREE.EquirectangularReflectionMapping;
++      texture.colorSpace = THREE.SRGBColorSpace;
++      scene.background = texture;
 +    });
 }
 </pre>

+ 1 - 1
manual/ja/fundamentals.html

@@ -176,7 +176,7 @@ three.jsには <a href="lights.html">今後の記事</a> で紹介する多く
 とりあえずディレクショナルライトを作成しましょう。</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);

+ 4 - 3
manual/ko/backgrounds.html

@@ -71,6 +71,7 @@ Three.js로 배경을 렌더링해야 합니다.</p>
 <p>간단히 장면의 배경에 텍스처를 입혀주기만 하면 되죠.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const bgTexture = loader.load('resources/images/daikanyama.jpg');
+bgTexture.colorSpace = THREE.SRGBColorSpace;
 scene.background = bgTexture;
 </pre>
 <p></p><div translate="no" class="threejs_example_container notranslate">
@@ -228,9 +229,9 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +  const texture = loader.load(
 +    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
 +    () =&gt; {
-+      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-+      rt.fromEquirectangularTexture(renderer, texture);
-+      scene.background = rt.texture;
++      texture.mapping = THREE.EquirectangularReflectionMapping;
++      texture.colorSpace = THREE.SRGBColorSpace;
++      scene.background = texture;
 +    });
 }
 </pre>

+ 1 - 1
manual/ko/fundamentals.html

@@ -250,7 +250,7 @@ Three.js에는 다양한 종류의 광원이 있습니다. 다 살펴보기 힘
 <a href="/docs/#api/ko/lights/DirectionalLight"><code class="notranslate" translate="no">DirectionalLight</code></a>를 사용해보도록 하죠.</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);

+ 0 - 7
manual/ru/custom-buffergeometry.html

@@ -31,13 +31,6 @@
       <div class="lesson">
         <div class="lesson-main">
           <p></p>
-<p>В <a href="custom-geometry.html">предыдущей статье</a> рассказывалось, как использовать <code class="notranslate" translate="no">Geometry</code>. Эта статья о <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>. <a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> обычно быстрее запускается и использует меньше памяти, но может быть сложнее в настройке. </p>
-<p>В <a href="custom-geometry.html">статье о Geometry</a> мы рассказали, что для использования <code class="notranslate" translate="no">Geometry</code> вы предоставляете массив вершин <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a> (позиций). 
-Затем вы создаете объекты <a href="/docs/#api/en/core/Face3"><code class="notranslate" translate="no">Face3</code></a>, определяя по индексу 3 вершины, которые составляют каждый треугольник фигуры, которую вы делаете.
-Для каждого <a href="/docs/#api/en/core/Face3"><code class="notranslate" translate="no">Face3</code></a> вы можете указать либо нормаль грани, либо нормали для каждой отдельной вершины грани. 
-Вы также можете указать цвет грани или отдельные цвета вершин. Наконец, вы можете создать параллельный массив массивов текстурных координат (UV), 
-один массив для каждой грани, содержащий массив UV, один для каждой вершины грани. </p>
-<div class="threejs_center"><img src="../resources/threejs-geometry.svg" style="width: 700px"></div>
 
 <p><a href="/docs/#api/en/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> с другой стороны использует названный <code class="notranslate" translate="no">BufferAttributes</code>. 
 Каждый атрибут <a href="/docs/#api/en/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> представляет собой массив данных одного типа: позиции, нормали, цвета и ультрафиолетовые лучи. 

+ 1 - 1
manual/ru/fundamentals.html

@@ -191,7 +191,7 @@ requestAnimationFrame(render);
 следующей статье. А пока давайте создадим направленный свет.</p>
 <pre class="prettyprint showlinemods notranslate notranslate" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);

+ 4 - 3
manual/zh/backgrounds.html

@@ -75,6 +75,7 @@ body {
         <p>THREE.js 让这变得非常简单。我们可以将场景的背景设置为一种纹理。</p>
         <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const loader = new THREE.TextureLoader();
 const bgTexture = loader.load('resources/images/daikanyama.jpg');
+bgTexture.colorSpace = THREE.SRGBColorSpace;
 scene.background = bgTexture;</pre>
         <p>效果如下</p>
         <p></p>
@@ -241,9 +242,9 @@ const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 +  const texture = loader.load(
 +    'resources/images/equirectangularmaps/tears_of_steel_bridge_2k.jpg',
 +    () =&gt; {
-+      const rt = new THREE.WebGLCubeRenderTarget(texture.image.height);
-+      rt.fromEquirectangularTexture(renderer, texture);
-+      scene.background = rt.texture;
++      texture.mapping = THREE.EquirectangularReflectionMapping;
++      texture.colorSpace = THREE.SRGBColorSpace;
++      scene.background = texture;
 +    });
 }</pre>
           <p>这就是全部要做的事。</p>

+ 1 - 2
manual/zh/custom-buffergeometry.html

@@ -377,8 +377,7 @@ positionAttribute.needsUpdate = true;
 <p></p>
 <p>我希望这些例子能对如何使用 <a href="/docs/#api/zh/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a> 直接创建你自己的几何体和如何动态更新 <a href="/docs/#api/zh/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> 的内容发挥作用。</p>
 <!-- needed in English only to prevent warning from outdated translations -->
-<p><a href="resources/threejs-geometry.svg"></a>
-<a href="custom-geometry.html"></a></p>
+<p><a href="resources/threejs-geometry.svg"></a></p>
 <p><canvas id="c"></canvas></p>
 <script type="module" src="../resources/threejs-custom-buffergeometry.js"></script>
 

+ 1 - 1
manual/zh/fundamentals.html

@@ -181,7 +181,7 @@ requestAnimationFrame(render);
 <p>效果好了一些但还是很难看出是三维的。我们来添加些光照效果,应该会有点帮助。three.js中有很多种类型的灯光,我们将在<a href="lights.html">后期文章</a>中详细讨论。现在我们先创建一盏平行光。</p>
 <pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
   const color = 0xFFFFFF;
-  const intensity = 1;
+  const intensity = 3;
   const light = new THREE.DirectionalLight(color, intensity);
   light.position.set(-1, 2, 4);
   scene.add(light);