みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Three.jsでトゥーンレンダリング風の表現を試みる 📺

トゥーンレンダリングに憧れて色々試してみました。
使える場所はかなり限定されるのですが、

OrthographicCamera を使う
MeshToonMaterial を使ったオブジェクトを作る
❸ ❷で作ったオブジェクトと同じ形で少し大きなオブジェクトを MeshBasicMaterial を使って作る
❹ ❸で作ったオブジェクトのマテリアルを黒(縁取り線に設定したい色)に変更する
❺ ❸で作ったオブジェクトを❷で作ったオブジェクトよりも奥側に配置する
❻ ❷で作ったオブジェクトと❸で作ったオブジェクトの動きを同期する

という実装で、それっぽいものができました。

DEMO


ソースコード

const width = window.innerWidth;
const height = window.innerHeight;
const aspect = height / width;
const cameraSize = 2;

const renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true
});
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(
  -cameraSize,
  cameraSize,
  cameraSize * aspect,
  -cameraSize * aspect,
  0,
  100
);
const ambientLight = new THREE.AmbientLight(0xdddddd, .8);
const directionalLight = new THREE.DirectionalLight(0xffffff, .4);
const cube = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1),
   new THREE.MeshToonMaterial({
    color: 0xeeeeee
  })
);
const frame = new THREE.Mesh(
  new THREE.BoxGeometry(1.04, 1.04, 1.04),
   new THREE.MeshBasicMaterial({
    color: 0x000000
  })
);

renderer.setSize(width, height);
camera.position.set(0, 0, 1);
directionalLight.position.set(-4, 4, 4);
cube.position.set(0, 0, 0);
frame.position.set(0, 0, -4);

scene.add(camera);
scene.add(ambientLight);
scene.add(directionalLight);
scene.add(cube);
scene.add(frame);

document.body.appendChild(renderer.domElement);

renderer.setAnimationLoop((evt) => {
  renderer.render(scene, camera);
  cube.rotation.x += .01;
  cube.rotation.y += .01;
  cube.rotation.z += .01;
  frame.rotation.x = cube.rotation.x;
  frame.rotation.y = cube.rotation.y;
  frame.rotation.z = cube.rotation.z;
});