From 34690431470891445a6a6afcc6c193b7442f891a Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Sat, 1 Jul 2023 10:03:03 +0200 Subject: [PATCH] Manual: Honor latest changes. (#26354) --- manual/en/lights.html | 36 +- manual/en/post-processing-3dlut.html | 2 +- manual/en/post-processing.html | 1 + manual/examples/game-check-animations.html | 331 +-- manual/examples/game-conga-line-w-notes.html | 1833 ++++++++++------- manual/examples/game-conga-line.html | 1457 +++++++------ manual/examples/game-just-player.html | 589 +++--- manual/examples/game-load-models.html | 258 ++- manual/examples/game-player-input.html | 953 +++++---- manual/examples/gpw-data-viewer.html | 154 +- ...xed-textures-picking-and-highlighting.html | 722 ++++--- .../indexed-textures-picking-debounced.html | 773 +++---- manual/examples/indexed-textures-picking.html | 609 +++--- .../indexed-textures-random-colors.html | 672 +++--- manual/examples/lights-ambient.html | 226 +- .../examples/lights-directional-w-helper.html | 273 +-- manual/examples/lights-directional.html | 240 ++- manual/examples/lights-hemisphere.html | 232 ++- .../lights-point-physically-correct.html | 171 -- manual/examples/lights-point.html | 260 ++- manual/examples/lights-rectarea.html | 310 +-- manual/examples/lights-spot-w-helper.html | 311 +-- manual/examples/load-gltf-animated-cars.html | 480 +++-- manual/examples/load-gltf-car-path-fixed.html | 432 ++-- manual/examples/load-gltf-car-path.html | 426 ++-- .../load-gltf-dump-scenegraph-extra.html | 305 +-- .../examples/load-gltf-dump-scenegraph.html | 285 +-- .../examples/load-gltf-rotate-cars-fixed.html | 320 +-- manual/examples/load-gltf-rotate-cars.html | 288 +-- manual/examples/load-gltf-shadows.html | 755 ++++--- manual/examples/load-gltf.html | 260 +-- manual/examples/load-obj-auto-camera-xz.html | 266 +-- manual/examples/load-obj-auto-camera.html | 250 ++- manual/examples/load-obj-materials-fixed.html | 200 +- .../load-obj-materials-windmill2.html | 280 +-- manual/examples/load-obj-materials.html | 198 +- manual/examples/load-obj-no-materials.html | 186 +- manual/examples/load-obj-wat.html | 186 +- manual/examples/lots-of-objects-animated.html | 730 ++++--- .../lots-of-objects-merged-vertexcolors.html | 398 ++-- manual/examples/lots-of-objects-merged.html | 344 ++-- .../lots-of-objects-morphtargets.html | 760 ++++--- .../lots-of-objects-multiple-data-sets.html | 602 +++--- manual/examples/lots-of-objects-slow.html | 340 +-- manual/examples/multiple-scenes-controls.html | 256 ++- .../examples/multiple-scenes-copy-canvas.html | 270 +-- manual/examples/multiple-scenes-generic.html | 218 +- manual/examples/multiple-scenes-selector.html | 236 ++- manual/examples/multiple-scenes-v1.html | 196 +- manual/examples/multiple-scenes-v2.html | 202 +- manual/examples/multiple-scenes-v3.html | 206 +- .../examples/offscreencanvas-w-fallback.html | 77 +- .../offscreencanvas-w-orbitcontrols.html | 305 +-- .../examples/offscreencanvas-w-picking.html | 199 +- manual/examples/offscreencanvas.html | 50 +- manual/examples/picking-gpu.html | 440 ++-- .../picking-raycaster-complex-geo.html | 298 +-- .../picking-raycaster-transparency.html | 336 +-- manual/examples/picking-raycaster.html | 319 +-- .../postprocessing-3dlut-identity.html | 461 +++-- .../examples/postprocessing-3dlut-prep.html | 265 +-- .../postprocessing-3dlut-w-loader.html | 676 +++--- manual/examples/postprocessing-3dlut.html | 607 +++--- ...processing-adobe-lut-to-png-converter.html | 303 +-- manual/examples/postprocessing-custom.html | 204 +- manual/examples/postprocessing-gui.html | 240 ++- manual/examples/postprocessing.html | 205 +- manual/examples/primitives-text.html | 258 ++- manual/examples/primitives.html | 728 ++++--- manual/fr/lights.html | 28 +- manual/ja/lights.html | 35 +- manual/ja/post-processing.html | 1 + manual/ko/lights.html | 37 +- manual/ko/post-processing.html | 1 + manual/ru/lights.html | 35 +- manual/zh/lights.html | 27 +- manual/zh/post-processing.html | 1 + 77 files changed, 14629 insertions(+), 11795 deletions(-) delete mode 100644 manual/examples/lights-point-physically-correct.html diff --git a/manual/en/lights.html b/manual/en/lights.html index 2e6b2f059a22c3..a1c34c671b6f3e 100644 --- a/manual/en/lights.html +++ b/manual/en/lights.html @@ -84,6 +84,7 @@

Lights

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); @@ -470,41 +471,6 @@

click here to open in a separate window -

-

One thing we didn't cover is that there is a setting on the WebGLRenderer -called physicallyCorrectLights. It effects how light falls off as distance from light. -It only affects PointLight and SpotLight. RectAreaLight does this automatically.

-

For lights though the basic idea is you don't set a distance for them to fade out, -and you don't set intensity. Instead you set the power of -the light in lumens and then three.js will use physics calculations like real lights. -The units of three.js in this case are meters and a 60w light bulb would have -around 800 lumens. There's also a decay property. It should -be set to 2 for realistic decay.

-

Let's test that.

-

First we'll turn on physically correct lights

-
const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
-+renderer.physicallyCorrectLights = true;
-
-

Then we'll set the power to 800 lumens, the decay to 2, and -the distance to Infinity.

-
const color = 0xFFFFFF;
-const intensity = 1;
-const light = new THREE.PointLight(color, intensity);
-light.power = 800;
-light.decay = 2;
-light.distance = Infinity;
-
-

and we'll add gui so we can change the power and decay

-
const gui = new GUI();
-gui.addColor(new ColorGUIHelper(light, 'color'), 'value').name('color');
-gui.add(light, 'decay', 0, 4, 0.01);
-gui.add(light, 'power', 0, 2000);
-
-

-

It's important to note each light you add to the scene slows down how fast three.js renders the scene so you should always try to use as few as diff --git a/manual/en/post-processing-3dlut.html b/manual/en/post-processing-3dlut.html index b9134381044f29..4ebca9fbe66f39 100644 --- a/manual/en/post-processing-3dlut.html +++ b/manual/en/post-processing-3dlut.html @@ -180,7 +180,7 @@

Post Processing 3DLUT

composer.addPass(renderModel); composer.addPass(effectLUT); composer.addPass(effectLUTNearest); -composer.addPass(gammaPass); +composer.addPass(outputPass);

Let's make some GUI code to select one lut or the other

const lutNameIndexMap = {};
diff --git a/manual/en/post-processing.html b/manual/en/post-processing.html
index 03bfa8e24eab6b..19e1c40fbfc33f 100644
--- a/manual/en/post-processing.html
+++ b/manual/en/post-processing.html
@@ -107,6 +107,7 @@ 

renderToScree import {RenderPass} from 'three/addons/postprocessing/RenderPass.js'; import {BloomPass} from 'three/addons/postprocessing/BloomPass.js'; import {FilmPass} from 'three/addons/postprocessing/FilmPass.js'; +import {OutputPass} from 'three/addons/postprocessing/OutputPass.js';

For pretty much any post processing EffectComposer.js, and RenderPass.js are required.

diff --git a/manual/examples/game-check-animations.html b/manual/examples/game-check-animations.html index 66b1ac8df1e869..faddb37e04281b 100644 --- a/manual/examples/game-check-animations.html +++ b/manual/examples/game-check-animations.html @@ -88,161 +88,208 @@ diff --git a/manual/examples/indexed-textures-picking-and-highlighting.html b/manual/examples/indexed-textures-picking-and-highlighting.html index d053205dfc2bc2..8e9b399190b2db 100644 --- a/manual/examples/indexed-textures-picking-and-highlighting.html +++ b/manual/examples/indexed-textures-picking-and-highlighting.html @@ -73,96 +73,107 @@ - - - - - - diff --git a/manual/examples/lights-point.html b/manual/examples/lights-point.html index 67ea54c28a645c..5efe304a40e95c 100644 --- a/manual/examples/lights-point.html +++ b/manual/examples/lights-point.html @@ -35,134 +35,168 @@ diff --git a/manual/examples/offscreencanvas.html b/manual/examples/offscreencanvas.html index 1eb2c93bfd33ed..b3f474780abc5d 100644 --- a/manual/examples/offscreencanvas.html +++ b/manual/examples/offscreencanvas.html @@ -33,28 +33,36 @@ diff --git a/manual/examples/picking-gpu.html b/manual/examples/picking-gpu.html index ed4b1af2646646..f661255307671b 100644 --- a/manual/examples/picking-gpu.html +++ b/manual/examples/picking-gpu.html @@ -36,223 +36,267 @@ import * as THREE from 'three'; 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 = 200; - const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); - camera.position.z = 30; - - const scene = new THREE.Scene(); - scene.background = new THREE.Color('white'); - const pickingScene = new THREE.Scene(); - pickingScene.background = new THREE.Color(0); - - // put the camera on a pole (parent it to an object) - // so we can spin the pole to move the camera around the scene - const cameraPole = new THREE.Object3D(); - scene.add(cameraPole); - cameraPole.add(camera); - - { - const color = 0xFFFFFF; - const intensity = 1; - const light = new THREE.DirectionalLight(color, intensity); - light.position.set(-1, 2, 4); - camera.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 rand(min, max) { - if (max === undefined) { - max = min; - min = 0; - } - return min + (max - min) * Math.random(); - } + const fov = 60; + const aspect = 2; // the canvas default + const near = 0.1; + const far = 200; + const camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); + camera.position.z = 30; - function randomColor() { - return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`; - } + const scene = new THREE.Scene(); + scene.background = new THREE.Color( 'white' ); + const pickingScene = new THREE.Scene(); + pickingScene.background = new THREE.Color( 0 ); - const loader = new THREE.TextureLoader(); - const texture = loader.load('resources/images/frame.png'); - - const idToObject = {}; - const numObjects = 100; - for (let i = 0; i < numObjects; ++i) { - const id = i + 1; - const material = new THREE.MeshPhongMaterial({ - color: randomColor(), - map: texture, - transparent: true, - side: THREE.DoubleSide, - alphaTest: 0.5, - }); - - const cube = new THREE.Mesh(geometry, material); - scene.add(cube); - idToObject[id] = cube; - - cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20)); - cube.rotation.set(rand(Math.PI), rand(Math.PI), 0); - cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6)); - - const pickingMaterial = new THREE.MeshPhongMaterial({ - emissive: new THREE.Color(id), - color: new THREE.Color(0, 0, 0), - specular: new THREE.Color(0, 0, 0), - map: texture, - transparent: true, - side: THREE.DoubleSide, - alphaTest: 0.5, - blending: THREE.NoBlending, - }); - const pickingCube = new THREE.Mesh(geometry, pickingMaterial); - pickingScene.add(pickingCube); - pickingCube.position.copy(cube.position); - pickingCube.rotation.copy(cube.rotation); - pickingCube.scale.copy(cube.scale); - } + // put the camera on a pole (parent it to an object) + // so we can spin the pole to move the camera around the scene + const cameraPole = new THREE.Object3D(); + scene.add( cameraPole ); + cameraPole.add( camera ); - 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; - } + { - class GPUPickHelper { - constructor() { - // create a 1x1 pixel render target - this.pickingTexture = new THREE.WebGLRenderTarget(1, 1); - this.pixelBuffer = new Uint8Array(4); - this.pickedObject = null; - this.pickedObjectSavedColor = 0; - } - pick(cssPosition, scene, camera, time) { - const {pickingTexture, pixelBuffer} = this; - - // restore the color if there is a picked object - if (this.pickedObject) { - this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor); - this.pickedObject = undefined; - } - - // set the view offset to represent just a single pixel under the mouse - const pixelRatio = renderer.getPixelRatio(); - camera.setViewOffset( - renderer.getContext().drawingBufferWidth, // full width - renderer.getContext().drawingBufferHeight, // full top - cssPosition.x * pixelRatio | 0, // rect x - cssPosition.y * pixelRatio | 0, // rect y - 1, // rect width - 1, // rect height - ); - // render the scene - renderer.setRenderTarget(pickingTexture); - renderer.render(scene, camera); - renderer.setRenderTarget(null); - // clear the view offset so rendering returns to normal - camera.clearViewOffset(); - //read the pixel - renderer.readRenderTargetPixels( - pickingTexture, - 0, // x - 0, // y - 1, // width - 1, // height - pixelBuffer); - - const id = - (pixelBuffer[0] << 16) | - (pixelBuffer[1] << 8) | - (pixelBuffer[2] ); - - const intersectedObject = idToObject[id]; - if (intersectedObject) { - // pick the first object. It's the closest one - this.pickedObject = intersectedObject; - // save its color - this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); - // set its emissive color to flashing red/yellow - this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000); - } - } - } + const color = 0xFFFFFF; + const intensity = 3; + const light = new THREE.DirectionalLight( color, intensity ); + light.position.set( - 1, 2, 4 ); + camera.add( light ); - const pickPosition = {x: 0, y: 0}; - const pickHelper = new GPUPickHelper(); - clearPickPosition(); + } - function render(time) { - time *= 0.001; // convert to seconds; + 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 rand( min, max ) { - cameraPole.rotation.y = time * .1; + if ( max === undefined ) { - pickHelper.pick(pickPosition, pickingScene, camera, time); + max = min; + min = 0; - renderer.render(scene, camera); + } - requestAnimationFrame(render); - } - requestAnimationFrame(render); - - function getCanvasRelativePosition(event) { - const rect = canvas.getBoundingClientRect(); - return { - x: (event.clientX - rect.left) * canvas.width / rect.width, - y: (event.clientY - rect.top ) * canvas.height / rect.height, - }; - } + return min + ( max - min ) * Math.random(); - function setPickPosition(event) { - const pos = getCanvasRelativePosition(event); - pickPosition.x = pos.x; - pickPosition.y = pos.y; - } + } - function clearPickPosition() { - // unlike the mouse which always has a position - // if the user stops touching the screen we want - // to stop picking. For now we just pick a value - // unlikely to pick something - pickPosition.x = -100000; - pickPosition.y = -100000; - } + function randomColor() { + + return `hsl(${rand( 360 ) | 0}, ${rand( 50, 100 ) | 0}%, 50%)`; + + } + + const loader = new THREE.TextureLoader(); + const texture = loader.load( 'resources/images/frame.png' ); + + const idToObject = {}; + const numObjects = 100; + for ( let i = 0; i < numObjects; ++ i ) { + + const id = i + 1; + const material = new THREE.MeshPhongMaterial( { + color: randomColor(), + map: texture, + transparent: true, + side: THREE.DoubleSide, + alphaTest: 0.5, + } ); + + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + idToObject[ id ] = cube; + + cube.position.set( rand( - 20, 20 ), rand( - 20, 20 ), rand( - 20, 20 ) ); + cube.rotation.set( rand( Math.PI ), rand( Math.PI ), 0 ); + cube.scale.set( rand( 3, 6 ), rand( 3, 6 ), rand( 3, 6 ) ); + + const pickingMaterial = new THREE.MeshPhongMaterial( { + emissive: new THREE.Color( id ), + color: new THREE.Color( 0, 0, 0 ), + specular: new THREE.Color( 0, 0, 0 ), + map: texture, + transparent: true, + side: THREE.DoubleSide, + alphaTest: 0.5, + blending: THREE.NoBlending, + } ); + const pickingCube = new THREE.Mesh( geometry, pickingMaterial ); + pickingScene.add( pickingCube ); + pickingCube.position.copy( cube.position ); + pickingCube.rotation.copy( cube.rotation ); + pickingCube.scale.copy( cube.scale ); + + } + + 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; + + } + + class GPUPickHelper { + + constructor() { + + // create a 1x1 pixel render target + this.pickingTexture = new THREE.WebGLRenderTarget( 1, 1 ); + this.pixelBuffer = new Uint8Array( 4 ); + this.pickedObject = null; + this.pickedObjectSavedColor = 0; + + } + pick( cssPosition, scene, camera, time ) { + + const { pickingTexture, pixelBuffer } = this; + + // restore the color if there is a picked object + if ( this.pickedObject ) { + + this.pickedObject.material.emissive.setHex( this.pickedObjectSavedColor ); + this.pickedObject = undefined; + + } + + // set the view offset to represent just a single pixel under the mouse + const pixelRatio = renderer.getPixelRatio(); + camera.setViewOffset( + renderer.getContext().drawingBufferWidth, // full width + renderer.getContext().drawingBufferHeight, // full top + cssPosition.x * pixelRatio | 0, // rect x + cssPosition.y * pixelRatio | 0, // rect y + 1, // rect width + 1, // rect height + ); + // render the scene + renderer.setRenderTarget( pickingTexture ); + renderer.render( scene, camera ); + renderer.setRenderTarget( null ); + // clear the view offset so rendering returns to normal + camera.clearViewOffset(); + //read the pixel + renderer.readRenderTargetPixels( + pickingTexture, + 0, // x + 0, // y + 1, // width + 1, // height + pixelBuffer ); + + const id = + ( pixelBuffer[ 0 ] << 16 ) | + ( pixelBuffer[ 1 ] << 8 ) | + ( pixelBuffer[ 2 ] ); + + const intersectedObject = idToObject[ id ]; + if ( intersectedObject ) { + + // pick the first object. It's the closest one + this.pickedObject = intersectedObject; + // save its color + this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); + // set its emissive color to flashing red/yellow + this.pickedObject.material.emissive.setHex( ( time * 8 ) % 2 > 1 ? 0xFFFF00 : 0xFF0000 ); + + } + + } + + } + + const pickPosition = { x: 0, y: 0 }; + const pickHelper = new GPUPickHelper(); + clearPickPosition(); + + function render( time ) { + + time *= 0.001; // convert to seconds; + + if ( resizeRendererToDisplaySize( renderer ) ) { + + const canvas = renderer.domElement; + camera.aspect = canvas.clientWidth / canvas.clientHeight; + camera.updateProjectionMatrix(); + + } + + cameraPole.rotation.y = time * .1; + + pickHelper.pick( pickPosition, pickingScene, camera, time ); + + renderer.render( scene, camera ); + + requestAnimationFrame( render ); + + } + + requestAnimationFrame( render ); + + function getCanvasRelativePosition( event ) { + + const rect = canvas.getBoundingClientRect(); + return { + x: ( event.clientX - rect.left ) * canvas.width / rect.width, + y: ( event.clientY - rect.top ) * canvas.height / rect.height, + }; + + } + + function setPickPosition( event ) { + + const pos = getCanvasRelativePosition( event ); + pickPosition.x = pos.x; + pickPosition.y = pos.y; + + } + + function clearPickPosition() { + + // unlike the mouse which always has a position + // if the user stops touching the screen we want + // to stop picking. For now we just pick a value + // unlikely to pick something + pickPosition.x = - 100000; + pickPosition.y = - 100000; + + } + + window.addEventListener( 'mousemove', setPickPosition ); + window.addEventListener( 'mouseout', clearPickPosition ); + window.addEventListener( 'mouseleave', clearPickPosition ); + + window.addEventListener( 'touchstart', ( event ) => { + + // prevent the window from scrolling + event.preventDefault(); + setPickPosition( event.touches[ 0 ] ); + + }, { passive: false } ); + + window.addEventListener( 'touchmove', ( event ) => { - window.addEventListener('mousemove', setPickPosition); - window.addEventListener('mouseout', clearPickPosition); - window.addEventListener('mouseleave', clearPickPosition); + setPickPosition( event.touches[ 0 ] ); - window.addEventListener('touchstart', (event) => { - // prevent the window from scrolling - event.preventDefault(); - setPickPosition(event.touches[0]); - }, {passive: false}); + } ); - window.addEventListener('touchmove', (event) => { - setPickPosition(event.touches[0]); - }); + window.addEventListener( 'touchend', clearPickPosition ); - window.addEventListener('touchend', clearPickPosition); } main(); diff --git a/manual/examples/picking-raycaster-complex-geo.html b/manual/examples/picking-raycaster-complex-geo.html index 1f00e6f79f9dd8..fa19cd8fb70e14 100644 --- a/manual/examples/picking-raycaster-complex-geo.html +++ b/manual/examples/picking-raycaster-complex-geo.html @@ -36,154 +36,198 @@ import * as THREE from 'three'; 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 = 200; - const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); - camera.position.z = 30; - - const scene = new THREE.Scene(); - scene.background = new THREE.Color('white'); - - // put the camera on a pole (parent it to an object) - // so we can spin the pole to move the camera around the scene - const cameraPole = new THREE.Object3D(); - scene.add(cameraPole); - cameraPole.add(camera); - - { - const color = 0xFFFFFF; - const intensity = 1; - const light = new THREE.DirectionalLight(color, intensity); - light.position.set(-1, 2, 4); - camera.add(light); - } - const geometry = new THREE.SphereGeometry(.6, 100, 100); + const canvas = document.querySelector( '#c' ); + const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } ); + renderer.useLegacyLights = false; - function rand(min, max) { - if (max === undefined) { - max = min; - min = 0; - } - return min + (max - min) * Math.random(); - } + const fov = 60; + const aspect = 2; // the canvas default + const near = 0.1; + const far = 200; + const camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); + camera.position.z = 30; - function randomColor() { - return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`; - } + const scene = new THREE.Scene(); + scene.background = new THREE.Color( 'white' ); - const numObjects = 100; - for (let i = 0; i < numObjects; ++i) { - const material = new THREE.MeshPhongMaterial({color: randomColor()}); + // put the camera on a pole (parent it to an object) + // so we can spin the pole to move the camera around the scene + const cameraPole = new THREE.Object3D(); + scene.add( cameraPole ); + cameraPole.add( camera ); - const cube = new THREE.Mesh(geometry, material); - scene.add(cube); + { - cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20)); - cube.rotation.set(rand(Math.PI), rand(Math.PI), 0); - cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6)); - } + const color = 0xFFFFFF; + const intensity = 3; + const light = new THREE.DirectionalLight( color, intensity ); + light.position.set( - 1, 2, 4 ); + camera.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; - } + } - class PickHelper { - constructor() { - this.raycaster = new THREE.Raycaster(); - this.pickedObject = null; - this.pickedObjectSavedColor = 0; - } - pick(normalizedPosition, scene, camera, time) { - // restore the color if there is a picked object - if (this.pickedObject) { - this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor); - this.pickedObject = undefined; - } - - this.raycaster.setFromCamera(normalizedPosition, camera); - const intersectedObjects = this.raycaster.intersectObjects(scene.children); - if (intersectedObjects.length) { - this.pickedObject = intersectedObjects[0].object; - this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); - this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000); - } - } - } + const geometry = new THREE.SphereGeometry( .6, 100, 100 ); - const pickHelper = new PickHelper(); - const pickPosition = {x: -1, y: -1}; - clearPickPosition(); + function rand( min, max ) { - function render(time) { - time *= 0.001; // convert to seconds; + if ( max === undefined ) { - if (resizeRendererToDisplaySize(renderer)) { - const canvas = renderer.domElement; - camera.aspect = canvas.clientWidth / canvas.clientHeight; - camera.updateProjectionMatrix(); - } + max = min; + min = 0; - cameraPole.rotation.y = time * .1; + } - pickHelper.pick(pickPosition, scene, camera, time); + return min + ( max - min ) * Math.random(); - renderer.render(scene, camera); + } - requestAnimationFrame(render); - } - requestAnimationFrame(render); - - function getCanvasRelativePosition(event) { - const rect = canvas.getBoundingClientRect(); - return { - x: (event.clientX - rect.left) * canvas.width / rect.width, - y: (event.clientY - rect.top ) * canvas.height / rect.height, - }; - } + function randomColor() { - function setPickPosition(event) { - const pos = getCanvasRelativePosition(event); - pickPosition.x = pos.x; - pickPosition.y = pos.y; - } + return `hsl(${rand( 360 ) | 0}, ${rand( 50, 100 ) | 0}%, 50%)`; - function clearPickPosition() { - // unlike the mouse which always has a position - // if the user stops touching the screen we want - // to stop picking. For now we just pick a value - // unlikely to pick something - pickPosition.x = -100000; - pickPosition.y = -100000; - } + } + + const numObjects = 100; + for ( let i = 0; i < numObjects; ++ i ) { + + const material = new THREE.MeshPhongMaterial( { color: randomColor() } ); + + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + + cube.position.set( rand( - 20, 20 ), rand( - 20, 20 ), rand( - 20, 20 ) ); + cube.rotation.set( rand( Math.PI ), rand( Math.PI ), 0 ); + cube.scale.set( rand( 3, 6 ), rand( 3, 6 ), rand( 3, 6 ) ); + + } + + 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; + + } + + class PickHelper { + + constructor() { + + this.raycaster = new THREE.Raycaster(); + this.pickedObject = null; + this.pickedObjectSavedColor = 0; + + } + pick( normalizedPosition, scene, camera, time ) { + + // restore the color if there is a picked object + if ( this.pickedObject ) { + + this.pickedObject.material.emissive.setHex( this.pickedObjectSavedColor ); + this.pickedObject = undefined; + + } + + this.raycaster.setFromCamera( normalizedPosition, camera ); + const intersectedObjects = this.raycaster.intersectObjects( scene.children ); + if ( intersectedObjects.length ) { + + this.pickedObject = intersectedObjects[ 0 ].object; + this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); + this.pickedObject.material.emissive.setHex( ( time * 8 ) % 2 > 1 ? 0xFFFF00 : 0xFF0000 ); + + } + + } + + } + + const pickHelper = new PickHelper(); + const pickPosition = { x: - 1, y: - 1 }; + clearPickPosition(); + + function render( time ) { + + time *= 0.001; // convert to seconds; + + if ( resizeRendererToDisplaySize( renderer ) ) { + + const canvas = renderer.domElement; + camera.aspect = canvas.clientWidth / canvas.clientHeight; + camera.updateProjectionMatrix(); + + } + + cameraPole.rotation.y = time * .1; + + pickHelper.pick( pickPosition, scene, camera, time ); + + renderer.render( scene, camera ); + + requestAnimationFrame( render ); + + } + + requestAnimationFrame( render ); + + function getCanvasRelativePosition( event ) { + + const rect = canvas.getBoundingClientRect(); + return { + x: ( event.clientX - rect.left ) * canvas.width / rect.width, + y: ( event.clientY - rect.top ) * canvas.height / rect.height, + }; + + } + + function setPickPosition( event ) { + + const pos = getCanvasRelativePosition( event ); + pickPosition.x = pos.x; + pickPosition.y = pos.y; + + } + + function clearPickPosition() { + + // unlike the mouse which always has a position + // if the user stops touching the screen we want + // to stop picking. For now we just pick a value + // unlikely to pick something + pickPosition.x = - 100000; + pickPosition.y = - 100000; + + } + + window.addEventListener( 'mousemove', setPickPosition ); + window.addEventListener( 'mouseout', clearPickPosition ); + window.addEventListener( 'mouseleave', clearPickPosition ); + + window.addEventListener( 'touchstart', ( event ) => { + + // prevent the window from scrolling + event.preventDefault(); + setPickPosition( event.touches[ 0 ] ); + + }, { passive: false } ); + + window.addEventListener( 'touchmove', ( event ) => { - window.addEventListener('mousemove', setPickPosition); - window.addEventListener('mouseout', clearPickPosition); - window.addEventListener('mouseleave', clearPickPosition); + setPickPosition( event.touches[ 0 ] ); - window.addEventListener('touchstart', (event) => { - // prevent the window from scrolling - event.preventDefault(); - setPickPosition(event.touches[0]); - }, {passive: false}); + } ); - window.addEventListener('touchmove', (event) => { - setPickPosition(event.touches[0]); - }); + window.addEventListener( 'touchend', clearPickPosition ); - window.addEventListener('touchend', clearPickPosition); } main(); diff --git a/manual/examples/picking-raycaster-transparency.html b/manual/examples/picking-raycaster-transparency.html index 8f7cb5bddb8cf7..6435f9174d2384 100644 --- a/manual/examples/picking-raycaster-transparency.html +++ b/manual/examples/picking-raycaster-transparency.html @@ -36,171 +36,215 @@ import * as THREE from 'three'; 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 = 200; - const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); - camera.position.z = 30; - - const scene = new THREE.Scene(); - scene.background = new THREE.Color('white'); - - // put the camera on a pole (parent it to an object) - // so we can spin the pole to move the camera around the scene - const cameraPole = new THREE.Object3D(); - scene.add(cameraPole); - cameraPole.add(camera); - - { - const color = 0xFFFFFF; - const intensity = 1; - const light = new THREE.DirectionalLight(color, intensity); - light.position.set(-1, 2, 4); - camera.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 rand(min, max) { - if (max === undefined) { - max = min; - min = 0; - } - return min + (max - min) * Math.random(); - } + const fov = 60; + const aspect = 2; // the canvas default + const near = 0.1; + const far = 200; + const camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); + camera.position.z = 30; - function randomColor() { - return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`; - } + const scene = new THREE.Scene(); + scene.background = new THREE.Color( 'white' ); - const loader = new THREE.TextureLoader(); - const texture = loader.load('resources/images/frame.png'); - - const numObjects = 100; - for (let i = 0; i < numObjects; ++i) { - const material = new THREE.MeshPhongMaterial({ - color: randomColor(), - map: texture, - transparent: true, - side: THREE.DoubleSide, - alphaTest: 0.1, - }); - - const cube = new THREE.Mesh(geometry, material); - scene.add(cube); - - cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20)); - cube.rotation.set(rand(Math.PI), rand(Math.PI), 0); - cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6)); - } + // put the camera on a pole (parent it to an object) + // so we can spin the pole to move the camera around the scene + const cameraPole = new THREE.Object3D(); + scene.add( cameraPole ); + cameraPole.add( camera ); - 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; - } + { - class PickHelper { - constructor() { - this.raycaster = new THREE.Raycaster(); - this.pickedObject = null; - this.pickedObjectSavedColor = 0; - } - pick(normalizedPosition, scene, camera, time) { - // restore the color if there is a picked object - if (this.pickedObject) { - this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor); - this.pickedObject = undefined; - } - - // cast a ray through the frustum - this.raycaster.setFromCamera(normalizedPosition, camera); - // get the list of objects the ray intersected - const intersectedObjects = this.raycaster.intersectObjects(scene.children); - if (intersectedObjects.length) { - // pick the first object. It's the closest one - this.pickedObject = intersectedObjects[0].object; - // save its color - this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); - // set its emissive color to flashing red/yellow - this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000); - } - } - } + const color = 0xFFFFFF; + const intensity = 3; + const light = new THREE.DirectionalLight( color, intensity ); + light.position.set( - 1, 2, 4 ); + camera.add( light ); - const pickPosition = {x: 0, y: 0}; - const pickHelper = new PickHelper(); - clearPickPosition(); + } - function render(time) { - time *= 0.001; // convert to seconds; + 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 rand( min, max ) { - cameraPole.rotation.y = time * .1; + if ( max === undefined ) { - pickHelper.pick(pickPosition, scene, camera, time); + max = min; + min = 0; - renderer.render(scene, camera); + } - requestAnimationFrame(render); - } - requestAnimationFrame(render); - - function getCanvasRelativePosition(event) { - const rect = canvas.getBoundingClientRect(); - return { - x: (event.clientX - rect.left) * canvas.width / rect.width, - y: (event.clientY - rect.top ) * canvas.height / rect.height, - }; - } + return min + ( max - min ) * Math.random(); - function setPickPosition(event) { - const pos = getCanvasRelativePosition(event); - pickPosition.x = (pos.x / canvas.width ) * 2 - 1; - pickPosition.y = (pos.y / canvas.height) * -2 + 1; // note we flip Y - } + } - function clearPickPosition() { - // unlike the mouse which always has a position - // if the user stops touching the screen we want - // to stop picking. For now we just pick a value - // unlikely to pick something - pickPosition.x = -100000; - pickPosition.y = -100000; - } + function randomColor() { + + return `hsl(${rand( 360 ) | 0}, ${rand( 50, 100 ) | 0}%, 50%)`; + + } + + const loader = new THREE.TextureLoader(); + const texture = loader.load( 'resources/images/frame.png' ); + + const numObjects = 100; + for ( let i = 0; i < numObjects; ++ i ) { + + const material = new THREE.MeshPhongMaterial( { + color: randomColor(), + map: texture, + transparent: true, + side: THREE.DoubleSide, + alphaTest: 0.1, + } ); + + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + + cube.position.set( rand( - 20, 20 ), rand( - 20, 20 ), rand( - 20, 20 ) ); + cube.rotation.set( rand( Math.PI ), rand( Math.PI ), 0 ); + cube.scale.set( rand( 3, 6 ), rand( 3, 6 ), rand( 3, 6 ) ); + + } + + 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; + + } + + class PickHelper { + + constructor() { + + this.raycaster = new THREE.Raycaster(); + this.pickedObject = null; + this.pickedObjectSavedColor = 0; + + } + pick( normalizedPosition, scene, camera, time ) { + + // restore the color if there is a picked object + if ( this.pickedObject ) { + + this.pickedObject.material.emissive.setHex( this.pickedObjectSavedColor ); + this.pickedObject = undefined; + + } + + // cast a ray through the frustum + this.raycaster.setFromCamera( normalizedPosition, camera ); + // get the list of objects the ray intersected + const intersectedObjects = this.raycaster.intersectObjects( scene.children ); + if ( intersectedObjects.length ) { + + // pick the first object. It's the closest one + this.pickedObject = intersectedObjects[ 0 ].object; + // save its color + this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); + // set its emissive color to flashing red/yellow + this.pickedObject.material.emissive.setHex( ( time * 8 ) % 2 > 1 ? 0xFFFF00 : 0xFF0000 ); + + } + + } + + } + + const pickPosition = { x: 0, y: 0 }; + const pickHelper = new PickHelper(); + clearPickPosition(); + + function render( time ) { + + time *= 0.001; // convert to seconds; + + if ( resizeRendererToDisplaySize( renderer ) ) { + + const canvas = renderer.domElement; + camera.aspect = canvas.clientWidth / canvas.clientHeight; + camera.updateProjectionMatrix(); + + } + + cameraPole.rotation.y = time * .1; + + pickHelper.pick( pickPosition, scene, camera, time ); + + renderer.render( scene, camera ); + + requestAnimationFrame( render ); + + } + + requestAnimationFrame( render ); + + function getCanvasRelativePosition( event ) { + + const rect = canvas.getBoundingClientRect(); + return { + x: ( event.clientX - rect.left ) * canvas.width / rect.width, + y: ( event.clientY - rect.top ) * canvas.height / rect.height, + }; + + } + + function setPickPosition( event ) { + + const pos = getCanvasRelativePosition( event ); + pickPosition.x = ( pos.x / canvas.width ) * 2 - 1; + pickPosition.y = ( pos.y / canvas.height ) * - 2 + 1; // note we flip Y + + } + + function clearPickPosition() { + + // unlike the mouse which always has a position + // if the user stops touching the screen we want + // to stop picking. For now we just pick a value + // unlikely to pick something + pickPosition.x = - 100000; + pickPosition.y = - 100000; + + } + + window.addEventListener( 'mousemove', setPickPosition ); + window.addEventListener( 'mouseout', clearPickPosition ); + window.addEventListener( 'mouseleave', clearPickPosition ); + + window.addEventListener( 'touchstart', ( event ) => { + + // prevent the window from scrolling + event.preventDefault(); + setPickPosition( event.touches[ 0 ] ); + + }, { passive: false } ); + + window.addEventListener( 'touchmove', ( event ) => { - window.addEventListener('mousemove', setPickPosition); - window.addEventListener('mouseout', clearPickPosition); - window.addEventListener('mouseleave', clearPickPosition); + setPickPosition( event.touches[ 0 ] ); - window.addEventListener('touchstart', (event) => { - // prevent the window from scrolling - event.preventDefault(); - setPickPosition(event.touches[0]); - }, {passive: false}); + } ); - window.addEventListener('touchmove', (event) => { - setPickPosition(event.touches[0]); - }); + window.addEventListener( 'touchend', clearPickPosition ); - window.addEventListener('touchend', clearPickPosition); } main(); diff --git a/manual/examples/picking-raycaster.html b/manual/examples/picking-raycaster.html index 972fb0039c87d5..c79ffcab3468c7 100644 --- a/manual/examples/picking-raycaster.html +++ b/manual/examples/picking-raycaster.html @@ -36,163 +36,208 @@ import * as THREE from 'three'; 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 = 200; - const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); - camera.position.z = 30; - - const scene = new THREE.Scene(); - scene.background = new THREE.Color('white'); - - // put the camera on a pole (parent it to an object) - // so we can spin the pole to move the camera around the scene - const cameraPole = new THREE.Object3D(); - scene.add(cameraPole); - cameraPole.add(camera); - - { - const color = 0xFFFFFF; - const intensity = 1; - const light = new THREE.DirectionalLight(color, intensity); - light.position.set(-1, 2, 4); - camera.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 rand(min, max) { - if (max === undefined) { - max = min; - min = 0; - } - return min + (max - min) * Math.random(); - } + const fov = 60; + const aspect = 2; // the canvas default + const near = 0.1; + const far = 200; + const camera = new THREE.PerspectiveCamera( fov, aspect, near, far ); + camera.position.z = 30; - function randomColor() { - return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`; - } + const scene = new THREE.Scene(); + scene.background = new THREE.Color( 'white' ); - const numObjects = 100; - for (let i = 0; i < numObjects; ++i) { - const material = new THREE.MeshPhongMaterial({ - color: randomColor(), - }); + // put the camera on a pole (parent it to an object) + // so we can spin the pole to move the camera around the scene + const cameraPole = new THREE.Object3D(); + scene.add( cameraPole ); + cameraPole.add( camera ); - const cube = new THREE.Mesh(geometry, material); - scene.add(cube); + { - cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20)); - cube.rotation.set(rand(Math.PI), rand(Math.PI), 0); - cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6)); - } + const color = 0xFFFFFF; + const intensity = 3; + const light = new THREE.DirectionalLight( color, intensity ); + light.position.set( - 1, 2, 4 ); + camera.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; - } + } - class PickHelper { - constructor() { - this.raycaster = new THREE.Raycaster(); - this.pickedObject = null; - this.pickedObjectSavedColor = 0; - } - pick(normalizedPosition, scene, camera, time) { - // restore the color if there is a picked object - if (this.pickedObject) { - this.pickedObject.material.emissive.setHex(this.pickedObjectSavedColor); - this.pickedObject = undefined; - } - - // cast a ray through the frustum - this.raycaster.setFromCamera(normalizedPosition, camera); - // get the list of objects the ray intersected - const intersectedObjects = this.raycaster.intersectObjects(scene.children); - if (intersectedObjects.length) { - // pick the first object. It's the closest one - this.pickedObject = intersectedObjects[0].object; - // save its color - this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); - // set its emissive color to flashing red/yellow - this.pickedObject.material.emissive.setHex((time * 8) % 2 > 1 ? 0xFFFF00 : 0xFF0000); - } - } - } + const boxWidth = 1; + const boxHeight = 1; + const boxDepth = 1; + const geometry = new THREE.BoxGeometry( boxWidth, boxHeight, boxDepth ); - const pickPosition = {x: 0, y: 0}; - const pickHelper = new PickHelper(); - clearPickPosition(); + function rand( min, max ) { - function render(time) { - time *= 0.001; // convert to seconds; + if ( max === undefined ) { - if (resizeRendererToDisplaySize(renderer)) { - const canvas = renderer.domElement; - camera.aspect = canvas.clientWidth / canvas.clientHeight; - camera.updateProjectionMatrix(); - } + max = min; + min = 0; - cameraPole.rotation.y = time * .1; + } - pickHelper.pick(pickPosition, scene, camera, time); + return min + ( max - min ) * Math.random(); - renderer.render(scene, camera); + } - requestAnimationFrame(render); - } - requestAnimationFrame(render); - - function getCanvasRelativePosition(event) { - const rect = canvas.getBoundingClientRect(); - return { - x: (event.clientX - rect.left) * canvas.width / rect.width, - y: (event.clientY - rect.top ) * canvas.height / rect.height, - }; - } + function randomColor() { - function setPickPosition(event) { - const pos = getCanvasRelativePosition(event); - pickPosition.x = (pos.x / canvas.width ) * 2 - 1; - pickPosition.y = (pos.y / canvas.height) * -2 + 1; // note we flip Y - } + return `hsl(${rand( 360 ) | 0}, ${rand( 50, 100 ) | 0}%, 50%)`; - function clearPickPosition() { - // unlike the mouse which always has a position - // if the user stops touching the screen we want - // to stop picking. For now we just pick a value - // unlikely to pick something - pickPosition.x = -100000; - pickPosition.y = -100000; - } - window.addEventListener('mousemove', setPickPosition); - window.addEventListener('mouseout', clearPickPosition); - window.addEventListener('mouseleave', clearPickPosition); + } + + const numObjects = 100; + for ( let i = 0; i < numObjects; ++ i ) { + + const material = new THREE.MeshPhongMaterial( { + color: randomColor(), + } ); + + const cube = new THREE.Mesh( geometry, material ); + scene.add( cube ); + + cube.position.set( rand( - 20, 20 ), rand( - 20, 20 ), rand( - 20, 20 ) ); + cube.rotation.set( rand( Math.PI ), rand( Math.PI ), 0 ); + cube.scale.set( rand( 3, 6 ), rand( 3, 6 ), rand( 3, 6 ) ); + + } + + 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; + + } + + class PickHelper { + + constructor() { + + this.raycaster = new THREE.Raycaster(); + this.pickedObject = null; + this.pickedObjectSavedColor = 0; + + } + pick( normalizedPosition, scene, camera, time ) { + + // restore the color if there is a picked object + if ( this.pickedObject ) { + + this.pickedObject.material.emissive.setHex( this.pickedObjectSavedColor ); + this.pickedObject = undefined; + + } + + // cast a ray through the frustum + this.raycaster.setFromCamera( normalizedPosition, camera ); + // get the list of objects the ray intersected + const intersectedObjects = this.raycaster.intersectObjects( scene.children ); + if ( intersectedObjects.length ) { + + // pick the first object. It's the closest one + this.pickedObject = intersectedObjects[ 0 ].object; + // save its color + this.pickedObjectSavedColor = this.pickedObject.material.emissive.getHex(); + // set its emissive color to flashing red/yellow + this.pickedObject.material.emissive.setHex( ( time * 8 ) % 2 > 1 ? 0xFFFF00 : 0xFF0000 ); + + } + + } + + } + + const pickPosition = { x: 0, y: 0 }; + const pickHelper = new PickHelper(); + clearPickPosition(); + + function render( time ) { + + time *= 0.001; // convert to seconds; + + if ( resizeRendererToDisplaySize( renderer ) ) { + + const canvas = renderer.domElement; + camera.aspect = canvas.clientWidth / canvas.clientHeight; + camera.updateProjectionMatrix(); + + } + + cameraPole.rotation.y = time * .1; + + pickHelper.pick( pickPosition, scene, camera, time ); + + renderer.render( scene, camera ); + + requestAnimationFrame( render ); + + } + + requestAnimationFrame( render ); + + function getCanvasRelativePosition( event ) { + + const rect = canvas.getBoundingClientRect(); + return { + x: ( event.clientX - rect.left ) * canvas.width / rect.width, + y: ( event.clientY - rect.top ) * canvas.height / rect.height, + }; + + } + + function setPickPosition( event ) { + + const pos = getCanvasRelativePosition( event ); + pickPosition.x = ( pos.x / canvas.width ) * 2 - 1; + pickPosition.y = ( pos.y / canvas.height ) * - 2 + 1; // note we flip Y + + } + + function clearPickPosition() { + + // unlike the mouse which always has a position + // if the user stops touching the screen we want + // to stop picking. For now we just pick a value + // unlikely to pick something + pickPosition.x = - 100000; + pickPosition.y = - 100000; + + } + + window.addEventListener( 'mousemove', setPickPosition ); + window.addEventListener( 'mouseout', clearPickPosition ); + window.addEventListener( 'mouseleave', clearPickPosition ); + + window.addEventListener( 'touchstart', ( event ) => { + + // prevent the window from scrolling + event.preventDefault(); + setPickPosition( event.touches[ 0 ] ); + + }, { passive: false } ); + + window.addEventListener( 'touchmove', ( event ) => { + + setPickPosition( event.touches[ 0 ] ); - window.addEventListener('touchstart', (event) => { - // prevent the window from scrolling - event.preventDefault(); - setPickPosition(event.touches[0]); - }, {passive: false}); + } ); - window.addEventListener('touchmove', (event) => { - setPickPosition(event.touches[0]); - }); + window.addEventListener( 'touchend', clearPickPosition ); - window.addEventListener('touchend', clearPickPosition); } main(); diff --git a/manual/examples/postprocessing-3dlut-identity.html b/manual/examples/postprocessing-3dlut-identity.html index 4bacda0ca3de43..15c683a89b75da 100644 --- a/manual/examples/postprocessing-3dlut-identity.html +++ b/manual/examples/postprocessing-3dlut-identity.html @@ -34,166 +34,185 @@