トゥーンレンダリングに憧れて色々試してみました。
使える場所はかなり限定されるのですが、
❶ 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; });