A3 Code Note

08/26/2022

Three.js:マウスによる背景の動き + レンズフレア

上記動画のメモです。
いくつか書き換えている部分があります。
デモサイト
my git

VSCodeでの下準備

  1. 「Three.js」と検索
  2. 左側のcodeの中の”download”をクリック
  3. ダウンロードしたzipを解凍
  4. プロジェクトのフォルダを作成し、VSCodeで開いておく
  5. 解凍したzipの「build」,「jsm」2つをそのプロジェクトの中に入れておく
    ・build
    ・jsm : examples > jsm
  6. 「lens flare」と検索し、好きな画像をプロジェクトの中に「textures」というフォルダを作り入れておく

現状
プロジェクトの中に「build」「jsm」「textures」というフォルダがある状態

box作成

03:20 index.html, script.js 作成
03:40 htmlコーディング
04:12 jsの記述——————-
04:34 土台作成
06:55 箱作成
10:40 平行光源
11:30 レンダラー
13:10 各種修正(カメラ、箱の回転)
15:35 ポイント光源

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MouseMove Three.js</title>
</head>
<body>
    <script src="script.js" type="module"></script>
</body>
</html>
import * as THREE from "./build/three.module.js"

let camera, scene, renderer;

init();

function init() {
    // camera
    camera = new THREE.PerspectiveCamera(
        40,
        window.innerWidth / window.innerHeight,
        1,
        15000
    );
    camera.position.z = 250;

    // scene
    scene = new THREE.Scene();
    const size = 250;
    const geometry = new THREE.BoxGeometry(size, size, size);
    const material = new THREE.MeshPhongMaterial({
        color: 0xffffff,
        specular: 0xffffff,
        shininess: 50,
    });
    
    // boxを2500個作成
    for(let i = 0; i < 2500; i++) {
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.x = 8000 * (2.0 * Math.random() - 1.0);
        mesh.position.y = 8000 * (2.0 * Math.random() - 1.0);
        mesh.position.z = 8000 * (2.0 * Math.random() - 1.0);

        // 回転度合いを決める
        mesh.rotation.x = Math.random() * Math.PI;
        mesh.rotation.y = Math.random() * Math.PI;
        mesh.rotation.z = Math.random() * Math.PI;

        scene.add(mesh);           
    }

    // 平行光源
    const dirLight = new THREE.DirectionalLight(0xffffff, 0.03);
    scene.add(dirLight);

    // ポイント光源
    addLight(0.08, 0.3, 0.9, 0, 0, -1000)
    function addLight(h, s, l, x, y, z) {
        const light = new THREE.PointLight(0xffffff, 1.5, 2000);
        light.color.setHSL(h, s, l);
        light.position.set(x, y, z);
        scene.add(light);
    }

    // renderer
    renderer = new THREE.WebGL1Renderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    renderer.render(scene, camera);

}

マウス操作 + レンズフレア

18:30 マウス操作
24:00 レンズフレア

// シーンなどが使えるようにモジュールをすべてインポート
import * as THREE from "./build/three.module.js";
// マウス操作
import { FlyControls } from "./jsm/controls/FlyControls.js";
// レンズフレア
import { Lensflare, LensflareElement } from "./jsm/objects/Lensflare.js";

let camera, scene, renderer;
let controls;

// 現在の経過時間を出力する
const clock = new THREE.Clock();

init();

// 初期化関数
function init() {
    // カメラ
    camera = new THREE.PerspectiveCamera(
        40, // 視野角
        window.innerWidth / window.innerHeight, // アスペクト比
        1, // 開始距離
        15000 // 終了距離
    );
    camera.position.z = 250; // カメラを引きでみる

    // シーン
    scene = new THREE.Scene();
    
    const size = 250;
    const geometry = new THREE.BoxGeometry(size, size, size); // 箱の大きさ設定
    const material = new THREE.MeshPhongMaterial({ // 箱の色など設定
        color: 0xffffff, // 色:白
        specular: 0xffffff, // 鏡面反射
        shininess: 50, // 輝度
    });
    
    // 箱を2500個作成
    for(let i = 0; i < 2500; i++) {
        // geometry と material をまとめるmeshを作成
        const mesh = new THREE.Mesh(geometry, material);

        //位置をランダムに決める
        mesh.position.x = 8000 * (2.0 * Math.random() - 1.0);
        mesh.position.y = 8000 * (2.0 * Math.random() - 1.0);
        mesh.position.z = 8000 * (2.0 * Math.random() - 1.0);

        // 回転度合いをランダムに決める
        mesh.rotation.x = Math.random() * Math.PI;
        mesh.rotation.y = Math.random() * Math.PI;
        mesh.rotation.z = Math.random() * Math.PI;

        scene.add(mesh);           
    }

    // 平行光源
    const dirLight = new THREE.DirectionalLight(0xffffff, 0.03); // 色, 光の強さ
    scene.add(dirLight);

    // レンズフレアを追加
    const textureLoader = new THREE.TextureLoader();
    const textureFlare = textureLoader.load("./textures/LensFlare.jpg");
    
    // ポイント光源
    addLight(0.08, 0.3, 0.9, 0, 0, -1000)
    function addLight(h, s, l, x, y, z) { // 色相:hue, 彩度:saturation, 輝度:light
        const light = new THREE.PointLight(0xffffff, 1.5, 2000); // 色, 光の強さ, 距離(, 減衰量)
        light.color.setHSL(h, s, l); // 光の色
        light.position.set(x, y, z); // 光の位置
        scene.add(light);

        // レンズフレア設定
        const lensflare = new Lensflare(); // Lensflare関数をインスタンス化
        lensflare.addElement(
            new LensflareElement(textureFlare, 700, 0, light.color)
        );

        scene.add(lensflare);
    }

    // レンダラー
    renderer = new THREE.WebGLRenderer(); // 今回はWebGLRenderer を使用
    renderer.setSize(window.innerWidth, window.innerHeight); // 画面いっぱいいっぱいに表現
    renderer.outputEncoding = THREE.sRGBEncoding; // レンズフレアを明るく描画
    document.body.appendChild(renderer.domElement); // bodyにレンダラーを入れる
    
    // マウス操作
    controls = new FlyControls(camera, renderer.domElement);

    controls.movementSpeed = 2500; // 左クリック、右クリック時の速度
    controls.rollSpeed = Math.PI / 20; // マウス操作時の速度

    animate();
}

// マウス操作のアニメーション
function animate() {
    requestAnimationFrame(animate); //自分(animate関数)を毎フレーム呼び出す

    const delta = clock.getDelta(); //経過した時間を取得
    controls.update(delta); // deltaをアップデートすることによってマウス操作ができるようになる

    renderer.render(scene, camera); // シーンとカメラをレンダリング
}

メニュー、タイトルの追加

29:00 cssの設定
30:00 Google Fonts
30:50 ヘッダーメニュー
33:11 タイトル

+ α

動画では紹介していなかったけれどgitに入っていたものについて

左上のFPSが表示されているバー

import Stats from "./jsm/libs/stats.module.js";

let container, stats;

animate(); // 記述する場所を変更

function init() {
  // divを作成しそこに描画
  container = document.createElement("div");
  document.body.appendChild(container);

  container.appendChild(renderer.domElement); // containerにレンダラーを入れる
  // document.body.appendChild(renderer.domElement); // bodyにレンダラーを入れる

  // ステータスバー作成
  stats = new Stats();
  container.appendChild(stats.dom);
}
function animate() {
  stats.update();
}

リサイズしたら自動でウインドウをリサイズする

function init() {
    // リサイズしたら自動でウインドウをリサイズする
    window.addEventListener("resize", onWindowResize);
}

// リサイズしたときに画面いっぱいいっぱいにする
function onWindowResize() {
    renderer.setSize(window.innerWidth, window.innerHeight);

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
}

平行光線の色をHSLで指定

dirLight.color.setHSL(0.1, 0.7, 0.5);