SNSをチェック

WebGLとThree.jsで流体アニメーションを作成する

WebGLとThree.jsを使用して流体アニメーションを作成することは、視覚的に非常に魅力的なプロジェクトです。Three.jsは、WebGLを抽象化して扱いやすくするライブラリであり、3Dグラフィックスの描画を簡単に行うことができます。今回は、Three.jsとTypeScriptを使って基本的な流体アニメーションを作成する方法を解説します。

See the Pen Fluid Animation by techcode sample (@techcode-sample) on CodePen.

必要な準備

  1. プロジェクトのセットアップ
  2. Three.jsのインストール
  3. 基本的なシーンの作成
  4. 流体シミュレーションの実装

1. プロジェクトのセットアップ

まず、TypeScriptとThree.jsを使用するためのプロジェクトをセットアップします。

mkdir fluid-animation
cd fluid-animation
npm init -y
npm install three typescript @types/three
npx tsc --init

tsconfig.jsonを設定して、プロジェクトのTypeScriptコンパイラオプションを適切に設定します。

{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"]
}

2. Three.jsのインストール

Three.jsをインストールし、TypeScriptの型定義もインストールします。

npm install three @types/three

3. 基本的なシーンの作成

次に、Three.jsを使用して基本的なシーンを作成します。src/index.tsを作成し、以下のコードを追加します。

import * as THREE from 'three';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);

scene.add(cube);
camera.position.z = 5;

function animate() {
requestAnimationFrame(animate);

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

renderer.render(scene, camera);
}

animate();

このコードは、基本的なThree.jsのシーンをセットアップし、回転する緑色のキューブを描画します。

4. 流体シミュレーションの実装

流体アニメーションの実装には、流体シミュレーションのアルゴリズムを使用します。ここでは、簡単な流体シミュレーションの例を示します。流体シミュレーションの詳細な実装は複雑ですが、Three.jsのシェーダーを使用して基本的なシミュレーションを実現できます。

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const planeGeometry = new THREE.PlaneGeometry(10, 10, 100, 100);
const planeMaterial = new THREE.ShaderMaterial({
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float time;
varying vec2 vUv;
void main() {
vec2 position = -1.0 + 2.0 * vUv;
float a = atan(position.y, position.x);
float r = sqrt(dot(position, position));
float offset = sin(r * 12.0 - time * 4.0);
gl_FragColor = vec4(vec3(offset), 1.0);
}
`,
uniforms: {
time: { value: 1.0 }
}
});

const plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);

camera.position.z = 5;

const controls = new OrbitControls(camera, renderer.domElement);

function animate() {
requestAnimationFrame(animate);

planeMaterial.uniforms.time.value += 0.05;

controls.update();
renderer.render(scene, camera);
}

animate();

window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});

コードの解説

  1. シェーダーマテリアルの設定:
    • vertexShader: 頂点シェーダー。各頂点の位置を計算します。
    • fragmentShader: フラグメントシェーダー。各ピクセルの色を計算します。
    • uniforms: シェーダーに渡すグローバル変数。時間を表すtimeを設定します。
  2. アニメーションループ:
    • animate関数内で、planeMaterial.uniforms.time.valueを更新し、時間経過に伴うアニメーションを実現します。
    • requestAnimationFrameを使用してアニメーションを実行します。
  3. リサイズ対応:
    • ウィンドウのリサイズに対応するため、resizeイベントリスナーを追加しています。

これで、簡単な流体アニメーションをThree.jsとTypeScriptで実装できました。このアプローチを基に、さらに複雑な流体シミュレーションを実装することも可能です。例えば、流体の速度や圧力の計算を追加したり、異なるシェーダーを使用してリアルなエフェクトを実現したりすることができます。

ぜひ、これらの基本をもとに、自分のプロジェクトで応用してみてください。Three.jsとTypeScriptの強力な組み合わせにより、美しい流体アニメーションを作成することができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です