Three.js - Picking - RayCaster w/Transparency

With orthographic camera

by navinleon

HTML

<canvas id="c"></canvas>

CSS

body {
  margin: 0;
}
#c {
  width: 100vw;
  height: 100vh;
  display: block;
}

JavaScript

// Three.js - Picking - RayCaster w/Transparency
// from https://threejsfundamentals.org/threejs/threejs-picking-gpu.html

import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const camera = new THREE.OrthographicCamera(0, 1, 0, 1, -1, 1);
  camera.position.z = 1;

  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 geometry = new THREE.PlaneBufferGeometry();

  function rand(min, max) {
    if (max === undefined) {
      max = min;
      min = 0;
    }
    return min + (max - min) * Math.random();
  }

  function randomColor() {
    return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`;
  }

  const loader = new THREE.TextureLoader();
  const texture = loader.load('https://threejsfundamentals.org/threejs/resources/images/frame.png');

  const idToObject = {};
  const numObjects = 100;
  for (let i = 0; i < numObjects; ++i) {
    const id = i + 1;
    const material = new THREE.MeshBasicMaterial({
      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(-500, 500), rand(-500, 500), 0);
    cube.rotation.set(0, 0, rand(Math.PI));
    cube.scale.set(rand(32, 64), rand(32, 64), 1);

    const pickingMaterial = new THREE.MeshPhongMaterial({
      emissive: new THREE.Color(id),
      color: new THREE.Color(0, 0, 0),
      specular: new...