1
/
5

3D表現に興味がある方必見!Three.jsでオブジェクトを作ってみよう【初心者向け】

こんにちは!ALCHEMYのエンジニア、丸山です。

こんなかっこいいモノが作れればいいなと思いまして、Three.jsを学び始めたんですけど、奥が深くて面白いので、みなさんに共有します。

この記事の対象者

  • Three.js 初心者の方
  • 少しでも、3Dでモノ作りをしたいと思っている方

パッケージのインストールから説明しているので、少しでもweb制作の経験がある方は理解できる内容になっていると思います。

本日のゴール

画面の真ん中に赤い四角を表示させる(下図を参照)
最初は難しいことは考えずに、画面にobjectを表示させてみましょう。
※ ページの最後に完成したソースを載せています

1.下記コマンドを入力してdependency の追加

npm install vite
npm install threenpm install vite
npm install three

copy

※念のため、package.jsonを確認

2.htmlファイルの作成

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<h3>テスト</h3>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<h3>テスト</h3>
</body>
</html>

copy

npm run dev で vite が走っているか確認

テストと反映されている状態


3.JSファイルの作成

script.jsファイルを作成し、先ほど作成したindex.htmlに紐付ける

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<script type="module" src="./script.js"></script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<script type="module" src="./script.js"></script>
</body>
</html>

copy

4.Three.js をインポートしましょう

import * as THREE from 'three'

copy

これで Three.js が提供しているクラスにアクセスできるようになっています。念のため、ログで確認しましょう。

提供されている全てのクラスが羅列されているわけではありませんが、「本日のゴール」でやりたいことを実現するためには十分なので、次に進みます。

5.実際に提供されているクラスを使いmesh(object)を作成

以下を作成していきます。

  • scene
  • object(赤い四角)
  • camera
  • renderer
  • scene

まずはsceneから。
sceneは簡単にいうと、objectやlightsを入れるための箱です。

// Scene
const scene = new THREE.Scene()
// Scene
const scene = new THREE.Scene()

copy

次にobjectの作成。
赤い四角を作成するためにはMeshと呼ばれるタイプのobjectを使用します。
Meshはgeometry(objectの形)とmaterial(obejctの見た目。色など)が合わさったものです。

Mesh = geometry + material

まずはgeometryを作成するので、提供されているBoxGeometryを使用します。それぞれのパラメータは、geometryのサイズです。

// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)

copy

次に、materialを作成します。
今回はMeshBasicMaterial を使用します。
パラメータには色を入れてあげましょう。

// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)

const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)

const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })

copy

geometryとmaterialが完成したので、それぞれ作成したものを使用してmeshを作りましょう。

// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })

const mesh = new THREE.Mesh(geometry, material)// Object
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })

const mesh = new THREE.Mesh(geometry, material)

copy

最後に、作成したmeshをsceneに追加します。

scene.add(mesh)

copy

これでmesh(object)の作成とsceneへの追加が完了しました。

6.cameraを作成


cameraの種類もいくつかあるのですが、今回はPerspectiveCameraというクラスを使います。そして、以下2つのパラメータを入れます。

  • fov (field of view) = 画面に映る視界の広さ。値が大きければ大きいほど、広い範囲を見れるが歪みが発生してしまう。小さいと、objectにズームしている感じになります。defaultは50°で、値は「°」です。
  • aspect ratio = 画面の比率。大体は、width/heightです。
// Sizes
const sizes = {
width: 800,
height: 600
}

// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
scene.add(camera)// Sizes
const sizes = {
width: 800,
height: 600
}

// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
scene.add(camera)

copy

※ cameraもsceneに追加することを忘れずに

7.rendererを作成


rendererの仕事はsceneをレンダリングすること。
つまり、rendererに頼んで、作成したmeshを設定したcameraの位置でレンダリングします。
その際、index.htmlに<canavs>を作成しなくてはいけません。

<canvas class="webgl"></canvas>

copy

script.jsで使用するのでクラス設定をしてください。

script.jsに戻ります。

renderer を作成し<canvas>と紐付ける。

// Canvas
const canvas = document.querySelector('canvas.webgl')

// ...

// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
// Canvas
const canvas = document.querySelector('canvas.webgl')

// ...

// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})

copy

rendereのサイズも設定しなくてはいけないので、setSize(...)というメソッドを使用します。先ほど camera作成時に設定した、widthとheightを使用しましょう。

// Canvas
const canvas = document.querySelector('canvas.webgl')

// ...

// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)// Canvas
const canvas = document.querySelector('canvas.webgl')

// ...

// Renderer
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)

copy

最後に、render(...)メソッドを呼び出して、sceneとcameraをパラメータとして入れます。

renderer.render(scene, camera)

copy

あれれ。。。となると思います。

問題点としては、作成したobejctとcameraのpositionを指定していないことです。defaultでobejctとcameraのpositionは、sceneの真ん中に設置されています。要するに、今見ている画面は作成したobjectの内側です。

なので、

cameraの位置をz軸に沿って動かします。3Dなのでx軸(右、左)とy軸(上、下)にプラスしてz軸(前、後)があります。

const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)

copy

そうすると、赤い箱が浮かんでくると思います。

いかがだったでしょうか。
最後までお読みいただき、ありがとうございました。

↓ 完成したソース

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<canvas class="webgl"></canvas>
<script type="module" src="./script.js"></script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初めてのthree.js</title>
</head>
<body>
<canvas class="webgl"></canvas>
<script type="module" src="./script.js"></script>
</body>
</html>


import * as THREE from 'three'

// Canvas
const canvas = document.querySelector('canvas.webgl')

// Scene
const scene = new THREE.Scene()

/**
* Objects
*/
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

/**
* Sizes
*/
const sizes = {
width: 800,
height: 600
}

/**
* Camera
*/
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)

/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.render(scene, camera)
import * as THREE from 'three'

// Canvas
const canvas = document.querySelector('canvas.webgl')

// Scene
const scene = new THREE.Scene()

/**
* Objects
*/
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

/**
* Sizes
*/
const sizes = {
width: 800,
height: 600
}

/**
* Camera
*/
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)

/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.render(scene, camera)


Invitation from 株式会社ALCHEMY
If this story triggered your interest, have a chat with the team?
株式会社ALCHEMY's job postings

Weekly ranking

Show other rankings
Like 島田 湧斗's Story
Let 島田 湧斗's company know you're interested in their content