17
Help us understand the problem. What are the problem?

posted at

updated at

Blenderで3Dモデルを作成し、webpack × Three.js でサイトを作成する

概要

今回はQiitaのキャラクター(Qiitan)の3Dモデルを作成し、Three.jsで表示するサイト作成まで書いていこうと思います。
長くなってしまいますが、参考になるところがあれば嬉しいです。

対象

・ Blenderをやってみたい人
・ Three.jsを使って3Dモデルのサイトを作ってみたい人
・ webpackを使った開発環境がある人(※webpackの細かい説明は省略しているため)

目次

  1. バージョンなど
  2. Blenderのダウンロード
  3. よく使うショートカット
  4. BlenderでQiitanを作成
  5. ファイル構成
  6. Three.jsでglbファイルを読み込む
  7. GSAPでアニメーションをつける
  8. 完成
  9. 参考

1. バージョンなど

macOS Big Sur v11.4
Blender v2.93.1
Node v16.4.2
vscode v1.60.0
webpack v5.27.2
typescript v4.2.3
three.js v0.133.1
gsap v3.8.0

2. Blenderのダウンロード

こちらからダウンロードできます。
https://www.blender.org/download/

3. よく使うショートカット

3D制作で非常に使えるショートカットを紹介します。
ショートカットを覚えると大幅な時間短縮ができます。

オブジェクトモード、編集モード共通

Aキー
→オブジェクトの全選択

Xキー
→削除

Tabキー
→オブジェクトモードと編集モードを切り替える

Gキー
→対象を移動できる
 →Gキー + x(y,z)でX(y,z)軸に方向にのみ移動させる

Rキー
→対象を回転できる
 →Rキー + x(y,z)でx(y,z)軸に方向にのみ回転させる

Sキー
→対象の拡大、縮小ができる

Shift + Aキー
→球体や立方体、平面などを生成する

Shift + Dキー
→対象物の複製

編集モードのみ

Eキー
→対象の頂点、辺、面を押し出す

Fキー
→対象に面を張る

Alt(option)+ 左クリック
→周を選択

頂点、辺、面を選択した状態で Ctrl(command) + r
→オブジェクトにぐるっと一周辺を入れることができる(ループカット)

4. BlenderでQiitanを作成

早速作成していきます。
今回作成するQiitanの画像は下記のサイトからお借りしました。
https://suzuri.jp/qiita

こちらを参考に作成します。
スクリーンショット 2021-11-14 11.58.11.png

デフォルトで設置されているカメラ、メッシュ、ライトを削除します。
Aキーで全選択し、Xキーで削除を選択。
スクリーンショット 2021-11-12 13.40.00.png

右上のナビゲートで-Y(画像赤四角)をクリックし、作業画面を設定します。
Shift + Aキー画像から背景を選択。
az.png

Qiitanの画像を追加します。
スクリーンショット 2021-11-12 13.42.29.png

Shift + AキーメッシュからUV球を選択。
スクリーンショット 2021-11-12 13.43.24.png

UV球を選択した状態でTabキーで編集モードにします。
右上のオブジェクトの透明化(画像赤四角)を有効にして、先程追加した背景画像を見られるようにします。
aw.png

UV球を選択した状態で、SキーでUV球をQiitanの全体サイズに合わせます。
スクリーンショット 2021-11-12 13.44.57.png

左側半分を選択し、Xキー頂点を削除します。
スクリーンショット 2021-11-12 14.30.26.png

右側全体を選択し、モディファイアの追加からミラーを選択。
スクリーンショット 2021-11-12 14.30.59.png

クリッピングにチェックを入れます。
これで簡単に左右対称のモデルが作成できるようになります。
スクリーンショット 2021-11-12 14.31.13.png

上部真ん中にあるプロポーショナル編集(画像赤四角)を有効にして、耳を作成します。
(この時右側だけ動かせば自動的に左側も同じように動きます。)
aq (1).png

耳を丸くしたいので、Ctrl + Bキーでベベルをします。
幅1mセグメントは5とします。
スクリーンショット 2021-11-13 10.29.41.png

増やした頂点を背景画像に合わせてGキーで移動します。
スクリーンショット 2021-11-13 10.30.25.png

同じ要領で体全体も背景画像に合わせます。
スクリーンショット 2021-11-13 10.31.50.png

ここまでできたらミラーを終了します。
Tabキーでオブジェクトモードに変更し、ミラーの「∨」から適用を選択。
次に尻尾を作っていきます。
スクリーンショット 2021-11-13 10.37.00.png

3キー(または左上の赤四角をクリック)で面選択モードに変更。
右後ろの4面を選択します。
aa.png

Iキーで面を差し込みます。
スクリーンショット 2021-11-13 10.40.25.png

そのままGキーで面を押し出します。
スクリーンショット 2021-11-13 10.40.46.png

右上のナビゲートで-Yをクリックし、作業画面を設定。
尻尾に合わせてGキーで頂点を移動していきます。
(1キー、または赤四角をクリックで頂点選択モードに変更できます。) 
ok.png

頂点が足りないときはCtrl + R(ループカット)で頂点を増やします。
スクリーンショット 2021-11-13 10.46.03.png

尻尾はこんな感じで完成です。
スクリーンショット 2021-11-14 9.55.50.png

Tabキーでオブジェクトモードに変更。
Shift + Aメッシュからを追加します。
スクリーンショット 2021-11-14 10.00.51.png

X軸方向に90度回転するために
RキーXキー90の順で入力します。
スクリーンショット 2021-11-14 10.01.09.png

円を選択した状態でTabキーで編集モードにします。
顔の白い部分に合わせて移動します。
スクリーンショット 2021-11-14 10.03.26.png

一度Tabキーでオブジェクトモードに戻り、
UV球の両方を選択した状態でTabキーで編集モードに変更します。
また、その両方を選択した状態でメッシュからナイフ投影を選択。
スクリーンショット 2021-11-14 10.03.52.png

すると円の形にUV球が切り抜けます。
この要領で目やひげも切り抜いていきます。
スクリーンショット 2021-11-14 10.07.03.png

目やひげ、口、耳を追加し、ナイフ投影します。
スクリーンショット 2021-11-14 10.53.10.png

ナイフ投影が完了し、各パーツができてきました。
次にマテリアルをつけていきます。
スクリーンショット 2021-11-14 11.08.22.png

マテリアルから新規を選択
まずは体全体の緑(#5CC500)を入力
スクリーンショット 2021-11-14 11.08.35.png

UV球をAキーで全選択
割り当てを選択
スクリーンショット 2021-11-14 11.08.54.png

右上のシェーディングから、マテリアルプレビューを選択(右から2番目)
緑色を確認できます。
同じ要領で目や耳も色をつけます。
スクリーンショット 2021-11-14 11.09.08.png

白(#FFFFFF)、黒(#000000)、黄色(#E6DB2C)でこのようになります。
スクリーンショット 2021-11-14 11.24.48.png

表面を滑らかにします。
Tabキーでオブジェクトモードに変更
UV球をAキーで全選択し、右クリックでスムースシェードを追加します。
スクリーンショット 2021-11-14 11.36.49.png

これで完成です。
スクリーンショット 2021-11-14 11.38.48.png

Three.jsで読み込むため、glTF形式でエクスポートします。
ファイルからエクスポート
glTF2.0(.glb/gltf)を選択。
スクリーンショット 2021-11-14 11.39.16.png

右側のジオメトリから、モディファイアを適用にチェックを入れます。
(他はデフォルトでOK)
ファイル名を入力し、エクスポートします。
スクリーンショット 2021-11-14 11.39.53.png

ここからwebpackとThree.jsで読み込んでいきます。

5. ファイル構成

ファイル構成は下記の通りです。

.
├── src
│   └── img
│   └── obj
│   │   └── qiitan.glb
│   │
│   └── scripts
│   │   └── components
│   │   │    └── webgl.ts
│   │   └── app.ts
│   │
│   └── static
│   │   └── favicon.ico
│   │
│   └── styles
│   │   └── base
│   │   │    └── base.scss
│   │   │    └── reset.scss
│   │   └── global
│   │   │    └── functions
│   │   │    │    └── functions.scss
│   │   │    │    └── mixins.scss
│   │   │    │    └── mq.scss
│   │   │    └── setting
│   │   │         └── color.scss
│   │   │         └── font.scss
│   │   │         └── size.scss
│   │   └── project
│   │   └── style.scss
│   │
│   └── index.html
│
├── .eslintrc.js
├── .prettierrc.js
├── package-lock.json
├── package.json
├── tsconfig.json
└── webpack.config.js

three.jsは忘れずにインストールしておきます。

npm install three @types/three

6. Three.jsでglbファイルを読み込む

Three.jsで3Dを表示するために必要なものは下記の通りです。
① 型の定義と設定
② htmlの設定
③ Sceneの設定
④ Cameraの設定
⑤ Rendererの設定
⑥ Lightの設定
⑦ Renderingの設定
⑧ Loaderの設定

まずはthree.jsを使用できるようにします。

webgl.ts
// three.js を使用する
import * as THREE from 'three';

次にthree.jsから、glbファイルを読み込むためのGLTFLoaderをインポートします。

webgl.ts
// GLTFLoader を使用する
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

① 型の定義と設定

webgl.ts
export default class WebGL {
    winSize: {
        [s: string]: number;
    };
    elms: {
        [s: string]: HTMLElement;
    };
    dpr: number;
    three: {
        scene: THREE.Scene;
        renderer: THREE.WebGLRenderer | null;
        clock: THREE.Clock;
        redraw: Group | null;
        camera: THREE.PerspectiveCamera | null;
        cameraFov: number;
        cameraAspect: number;
    };
    srcObj: string;
    constructor() {
        // ウィンドウサイズを取得
        this.winSize = {
            wd: window.innerWidth,
            wh: window.innerHeight,
        };
        // canvas要素を取得
        this.elms = {
            canvas: document.querySelector('[data-canvas]'),
        };
        // デバイスピクセル比(最大値=2)
        this.dpr = Math.min(window.devicePixelRatio, 2);
        // Three.jsに必要な要素
        this.three = {
            scene: null,
            renderer: null,
            clock: null,
            redraw: null,
            camera: null,
            cameraFov: 50,
            cameraAspect: window.innerWidth / window.innerHeight,
        };
        // 作成したqiitanの3Dモデルを読み込む
        this.srcObj = './obj/qiitan.glb';
        this.init();
    }

② htmlの設定

canvasを設置する箇所を指定します。

index.html
<body>
    <main>
        <section>
            <div data-canvas></div>
        </section>
    </main>
</body>

③ Sceneの設定

3D空間の生成を行う設定です。

webgl.ts
initScene(): void {
    // シーンを作成
    this.three.scene = new THREE.Scene();
}

④ Cameraの設定

3Dを撮影するためのカメラ設定です。

webgl.ts
initCamera(): void {
    // カメラを作成(視野角, スペクト比, near, far)
    this.three.camera = new THREE.PerspectiveCamera(this.three.cameraFov, this.winSize.wd / this.winSize.wh, this.three.cameraAspect, 1000);
    this.three.camera.position.set(0, 0, 9);
}

⑤ Rendererの設定

レンダリングを行うための設定です。

webgl.ts
initRenderer(): void {
    // レンダラーを作成
    this.three.renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true, // 背景を透明にする
    });
    this.three.renderer.setPixelRatio(this.dpr); // retina対応
    this.three.renderer.setSize(this.winSize.wd, this.winSize.wh); // 画面サイズをセット
    this.three.renderer.physicallyCorrectLights = true;
    this.three.renderer.shadowMap.enabled = true; // シャドウを有効にする
    this.three.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // PCFShadowMapの結果から更に隣り合う影との間を線形補間して描画する
    this.elms.canvas.appendChild(this.three.renderer.domElement); // HTMLにcanvasを追加
    this.three.renderer.outputEncoding = THREE.GammaEncoding; // 出力エンコーディングを定義
}

⑥ Lightの設定

Lightにはたくさん種類があります。
その時に合ったライトを使用するとより良いサイトができます。

webgl.ts
setLight() {
    // 環境光源(色, 光の強さ)
    const ambientLight = new THREE.AmbientLight(0x666666);
    this.three.scene.add(ambientLight);
}

⑦ Renderingの設定

3Dを画面に繰り返し描写するための設定です。

webgl.ts
rendering(): void {
    // レンダリングを実行
    requestAnimationFrame(this.rendering.bind(this));
    this.three.renderer.render(this.three.scene, this.three.camera);
}

⑧ Loaderの設定

作成した3Dモデルの読み込みを設定します。
読み込み完了後にrenderingを実行しています。

webgl.ts
setLoading() {
    // glTF形式の3Dモデルを読み込む
    const loader = new GLTFLoader();
    loader.load(this.srcObj, (obj) => {
        const data = obj.scene;
         // 3Dモデルをredrawに入れる
        this.three.redraw = data;
        // 3Dモデルの初期サイズ設定
        data.scale.set(0.8, 0.8, 0.8);
        // シーンに3Dモデルを追加
        this.three.scene.add(data);
        // レンダリングを開始する
        this.rendering();
    });
}

ここまで設定できたら実行します。

webgl.ts
init(): void {
    this.initScene();
    this.initCamera();
    this.initRenderer();
    this.setLight();
    this.setLoading();
}

ブラウザで確認します。
ばっちり表示できました。
スクリーンショット 2021-11-14 13.46.25.png

7. GSAPでアニメーションをつける

gsapのインストール

npm install gsap

gsapのインポート

webgl.ts
import { gsap } from 'gsap';

最後にGSAPでアニメーションをつけていきます。

Renderingの設定に追加

webgl.ts
rendering(): void {
    // レンダリングを実行
    requestAnimationFrame(this.rendering.bind(this));
    this.three.renderer.render(this.three.scene, this.three.camera);
    // アニメーション開始
    this.animate();// 追加
}

アニメーションの設定

例えばY軸に回転させてみます。

webgl.ts
animate() {
    gsap.config({
        force3D: true,
    });
    const tl = gsap.timeline({
        paused: true,
        defaults: {
            duration: 0.6,
            ease: 'power2.easeOut',
        },
    });
    // 回転させる
    tl.to(this.three.redraw.rotation, {
        duration: 1.6,
        y: 6,
    });
    tl.play();
}

ブラウザで確認してみると、回転していることがわかります。
a.gif

位置やサイズは下記のようにすると設定できます。
チェックしながら好きなアニメーションを設定していきます。

webgl.ts
animate() {
    gsap.config({
        force3D: true,
    });
    const tl = gsap.timeline({
        paused: true,
        defaults: {
            duration: 0.6,
            ease: 'power2.easeOut',
        },
    });
    // 回転させる
    tl.to(this.three.redraw.rotation, {
        duration: 1.6,
        y: 6,
    });
    // サイズを変更する
    tl.to(this.three.redraw.scale, {
        duration: 1.6,
        x: 3,
        y: 3,
        z: 3,
    });
    // 位置を変更する
    tl.to(this.three.redraw.position, {
        duration: 1.6,
        x: 3,
        y: 3,
        z: 3,
    });
    tl.play();
}

8. 完成

好きなアニメーションやテキストをつけて完成です。
ogp.png

今回作成したサイトが下記になります。
https://kaito-takase.dev/3d-qiita/

Gitにソースコードを置いているので、参考になるところがあればお願いします。
https://github.com/kaitoooo/3d-qiita

予想通り長くなってしまいましたが、ここまで読んでいただきありがとうございました。

9. 参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
17
Help us understand the problem. What are the problem?