WebGLは、Webブラウザ上でインタラクティブな3Dグラフィックスを表示するための強力な技術です。WebGLを使うことで、HTMLやJavaScriptを使ってブラウザ上でリアルタイムの3Dアプリケーションを開発することができます。この解説では、WebGLの基本から応用編までをカバーして行くつもりです。
※詳しい方は、寧ろコメントなどでサポートお願いします。
See the Pen Untitled by techcode sample (@techcode-sample) on CodePen.
1. WebGLの基本
1.1 WebGLとは?
まず最初に、WebGLとは何かについて簡単に説明しましょう。WebGLは、Web Graphics Libraryの略で、ブラウザ上で2Dおよび3Dのグラフィックスを描画するためのJavaScript APIです。OpenGL ES(組み込みシステム向けのOpenGLの派生版)をベースにしており、ブラウザ内で直接3Dコンテンツをレンダリングすることができます。これにより、特別なプラグインをインストールすることなく、3DゲームやデータビジュアライゼーションをWeb上で実現できるのです。
1.2 WebGLの基本構造
WebGLを使って3Dグラフィックスを描画するためには、いくつかのステップを踏む必要があります。基本的な流れは以下の通りです。
- HTMLファイルを作成する:
<canvas>
タグを使って、WebGLの描画対象となる領域を作成します。 - JavaScriptでWebGLコンテキストを取得する:
getContext("webgl")
メソッドを使ってWebGLのコンテキストを取得します。 - シェーダーを作成する: WebGLでは、頂点シェーダーとフラグメントシェーダーという2種類のシェーダーを使ってグラフィックスを描画します。これらはGLSL(OpenGL Shading Language)というシェーディング言語で書かれます。
- バッファにデータを送る: 頂点データやテクスチャなどをWebGLバッファに送ります。
- 描画する: WebGLの描画コマンドを実行して、3Dグラフィックスを描画します。
これらのステップは、WebGLでの描画の基本的な流れです。次に、具体的なコード例を使って、このプロセスを詳しく見ていきましょう。
2. WebGLの基本的なコード
2.1 HTMLとJavaScriptのセットアップ
まずは、WebGLを動かすためのHTMLファイルを用意します。以下は、最も基本的なWebGLセットアップの例です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL Basic Example</title>
</head>
<body>
<canvas id="glcanvas" width="640" height="480"></canvas>
<script src="script.js"></script>
</body>
</html>
この例では、<canvas>
タグを使ってWebGLの描画領域を作成しています。そして、script.js
というJavaScriptファイルを読み込んで、ここにWebGLのコードを書いていきます。
2.2 WebGLコンテキストの取得
次に、script.js
ファイルでWebGLコンテキストを取得します。
const canvas = document.getElementById("glcanvas");
const gl = canvas.getContext("webgl");
if (!gl) {
console.log("WebGL not supported, falling back on experimental-webgl");
gl = canvas.getContext("experimental-webgl");
}
if (!gl) {
alert("Your browser does not support WebGL");
}
このコードでは、まずgetContext("webgl")
メソッドを使ってWebGLコンテキストを取得しています。もしブラウザがWebGLをサポートしていない場合は、experimental-webgl
にフォールバックするようにしています。
2.3 シェーダーの作成
WebGLでグラフィックスを描画するためには、シェーダーを作成する必要があります。シェーダーは、グラフィックスパイプラインの特定の部分を処理する小さなプログラムです。WebGLでは、頂点シェーダーとフラグメントシェーダーの2つのシェーダーが必要です。
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
この関数は、シェーダーを作成し、コンパイルするための基本的な手順をまとめたものです。次に、頂点シェーダーとフラグメントシェーダーのコードを定義します。
const vertexShaderSource = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`;
const fragmentShaderSource = `
void main() {
gl_FragColor = vec4(1, 0, 0, 1); // 赤色
}
`;
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
頂点シェーダーは、各頂点の位置を決定します。一方、フラグメントシェーダーは各ピクセルの色を決定します。この例では、画面上に赤色のピクセルを描画するように設定しています。
3. WebGLの応用
3.1 3Dモデルの描画
次に、WebGLを使って3Dモデルを描画する方法について説明します。3Dモデルは通常、多くの頂点で構成されています。これらの頂点をバッファに格納し、WebGLに送り込んで描画します。
const positions = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5,
]);
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
このコードでは、三角形の頂点を定義し、それらをバッファに格納しています。WebGLでは、バッファは頂点データやその他の情報をGPUに送るために使用されます。
3.2 カメラとビュー行列
3D空間でオブジェクトを正しく表示するためには、カメラとビュー行列の概念が必要です。カメラは、シーンをどのように見るかを決定し、ビュー行列はオブジェクトをどのように変換するかを決定します。
const viewMatrix = mat4.create();
mat4.lookAt(viewMatrix, [0, 0, 2], [0, 0, 0], [0, 1, 0]);
const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * Math.PI / 180, canvas.width / canvas.height, 0.1, 10.0);
const modelViewMatrix = mat4.create();
mat4.multiply(modelViewMatrix, viewMatrix, projectionMatrix);
ここでは、lookAt
関数を使ってカメラの位置を設定し、perspective
関数を使って投影行列を作成しています。これにより、3D空間内のオブジェクトが適切に描画されます。
3.3 テクスチャマッピング
3Dモデルに色やパターンを適用するためには、テクスチャマッピングを使用します。テクスチャマッピングは、2Dイメージを3Dモデルに貼り付ける技術です。
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
const image = new Image();
image.src = 'texture.png';
image.onload = () => {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
};
このコードでは、texture.png
という画像をロードし、それをテクスチャとしてWebGLにバインドしています。generateMipmap
関数を使うことで、テクスチャのミップマップも自動的に生成されます。
4. WebGLの高度なテクニック
4.1 シェーダーの高度な使い方
シェーダーは、WebGLでの描画の心臓部です。シェーダーを使うことで、単純な色の描画だけでなく、光の反射や影、さらにはポストプロセッシングエフェクト(例えば、ブラーや色調補正)など、様々な効果を実現することができます。
例えば、Phongシェーディングという技法を使って、よりリアルなライティングを実現することができます。
const fragmentShaderSource = `
precision mediump float;
varying vec3 v_normal;
varying vec3 v_position;
void main() {
vec3 lightDirection = normalize(vec3(1, 1, 1));
float lightIntensity = max(dot(v_normal, lightDirection), 0.0);
vec3 color = vec3(1, 0, 0) * lightIntensity;
gl_FragColor = vec4(color, 1.0);
}
`;
このフラグメントシェーダーでは、光の方向と法線ベクトルの内積を計算し、その結果を色に反映させています。これにより、光の当たる部分が明るくなるリアルなライティングが実現できます。
4.2 ポストプロセッシングエフェクト
ポストプロセッシングエフェクトは、描画されたフレームに対して追加のエフェクトを適用する技術です。例えば、全体にブラーをかけたり、色調を変更したりすることができます。
const fragmentShaderSource = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 v_texcoord;
void main() {
vec4 color = texture2D(u_texture, v_texcoord);
gl_FragColor = vec4(color.rgb * vec3(0.5, 0.5, 1.0), color.a);
}
`;
このシェーダーでは、テクスチャの色に青みを加えるエフェクトを実装しています。こうしたポストプロセッシングエフェクトを使うことで、ゲームやビジュアライゼーションのビジュアルを劇的に向上させることができます。
おまけ
See the Pen Untitled by techcode sample (@techcode-sample) on CodePen.
WebGLと相性が良いJavaScriptライブラリはいくつかありますが、それぞれの用途や特性に応じて選ぶことが重要です。以下に、WebGLと特に相性が良いとされるJavaScriptライブラリを紹介します。
0. Three.js
- 概要: Three.jsは、WebGLを簡単に扱えるように抽象化したライブラリです。シーンの構築、カメラの操作、オブジェクトの描画など、基本的な3Dレンダリングから高度なエフェクトまで幅広く対応しています。
- 用途: ゲーム開発、3Dモデルの表示、インタラクティブなウェブコンテンツの作成。
- 特徴:
- 簡単に使えるAPI。
- 多数のサンプルとドキュメントが充実。
- PBR(物理ベースレンダリング)やポストプロセスエフェクトのサポート。
- 相性の良さ: Three.jsはWebGLの低レベルAPIを隠蔽し、シンプルなコードで複雑な3Dシーンを作成できるため、初心者からプロフェッショナルまで幅広く利用されています。
01. Babylon.js
- 概要: Babylon.jsは、Three.jsと同様にWebGLを使った3Dレンダリングを簡単に行うためのフレームワークです。ゲーム開発に特化した機能や、AR/VRサポートが強力です。
- 用途: 高品質な3Dゲーム、シミュレーション、AR/VRコンテンツの開発。
- 特徴:
- 強力な物理エンジンとシェーダーサポート。
- WebXR対応で、AR/VRコンテンツが容易に作成可能。
- エディターやデバッグツールが豊富。
- 相性の良さ: Babylon.jsは、複雑なシーンやリアルタイムシミュレーションに強く、特に高品質なビジュアルが求められるプロジェクトに適しています。
02. GLSLify
- 概要: GLSLifyは、シェーダーコード(GLSL)をモジュール化し、再利用可能にするためのツールです。WebGLやThree.jsなどと組み合わせて使うことで、シェーダーの管理が容易になります。
- 用途: 複雑なシェーダーエフェクトの作成と管理。
- 特徴:
- シェーダーコードのモジュール化をサポート。
- NPM経由でGLSLモジュールを管理。
- 他のWebGLライブラリとの相性が良い。
- 相性の良さ: 複雑なシェーダーを扱うプロジェクトでは、GLSLifyを使うことでコードの管理が容易になり、メンテナンス性が向上します。
03. Tweakpane
- 概要: Tweakpaneは、WebGLコンテンツをデバッグしたり、リアルタイムにパラメータを調整するためのGUIライブラリです。Three.jsやBabylon.jsと併用して、デバッグや調整が簡単に行えます。
- 用途: パラメータ調整、デバッグ、プロトタイピング。
- 特徴:
- 軽量で使いやすい。
- 直感的なGUIでリアルタイムに設定を変更可能。
- カスタマイズ性が高い。
- 相性の良さ: 開発中のプロジェクトでリアルタイムにパラメータを調整する必要がある場合、Tweakpaneは非常に有用です。
04. PixiJS
- 概要: PixiJSは、2Dグラフィックスに特化したレンダリングエンジンですが、WebGLを内部で利用しています。高速な2Dレンダリングが可能で、Three.jsと組み合わせて使うケースもあります。
- 用途: 2Dゲーム、アニメーション、UIコンポーネントの作成。
- 特徴:
- 高速な2Dレンダリング。
- 簡単に使えるAPIと豊富なエクステンション。
- Three.jsとの統合も可能。
- 相性の良さ: 2Dと3Dを組み合わせたコンテンツを開発する際、PixiJSは理想的な選択肢です。
05. Cannon.js (Physics Engine)
- 概要: Cannon.jsは、リアルタイム物理シミュレーションを行うための軽量な物理エンジンです。Three.jsと組み合わせて、リアルな物理エフェクトを実現できます。
- 用途: ゲーム開発、シミュレーション、インタラクティブな物理エフェクト。
- 特徴:
- シンプルで使いやすいAPI。
- 剛体シミュレーションをサポート。
- Three.jsとの統合が容易。
- 相性の良さ: 物理エンジンが必要なプロジェクトで、Three.jsと組み合わせることで強力な物理表現が可能になります。
06. GSAP (GreenSock Animation Platform)
- 概要: GSAPは強力なアニメーションライブラリで、WebGLを使ったアニメーションにも適用できます。シンプルなアニメーションから複雑なタイムラインまで、幅広いアニメーションを制御できます。
- 用途: 高度なアニメーションの作成、WebGLコンテンツのアニメーション制御。
- 特徴:
- 高性能でスムーズなアニメーション。
- タイムラインやシーケンスアニメーションの作成が容易。
- Three.jsやPixiJSなどのライブラリと組み合わせて使える。
- 相性の良さ: WebGLコンテンツでアニメーションを加える場合、GSAPは非常に強力で柔軟なツールです。
07. D3.js
- 概要: D3.jsはデータ駆動型のドキュメント操作を行うライブラリですが、WebGLと組み合わせることでインタラクティブなデータビジュアライゼーションが可能です。
- 用途: データビジュアライゼーション、インタラクティブなグラフや地図の作成。
- 特徴:
- データに基づいた動的なビジュアライゼーション。
- SVGやCanvasとWebGLの統合が容易。
- 高度なアニメーションやトランジションが可能。
- 相性の良さ: データビジュアライゼーションと3Dグラフィックスを組み合わせたい場合、D3.jsとWebGLの組み合わせが強力です。
これらのライブラリは、WebGLを使った開発を効率的に進めるために非常に役立ちます。それぞれのプロジェクトのニーズに応じて、最適なライブラリを選択することが重要です。
まとめ
今回の解説では、WebGLの基本から応用までを幅広くカバーしました。WebGLは、強力なグラフィックスAPIであり、ブラウザ上でリッチな3Dコンテンツを実現するための重要なツールです。最初は少し難しく感じるかもしれませんが、基本を押さえながら少しずつ応用技術にチャレンジしていくことで、驚くほど多くのことができるようになります。
もし、この記事が参考になったら、ぜひ実際にコードを書いてWebGLの世界を探求してみてくださいね。WebGLでの開発は、創造力を存分に発揮できる楽しい作業です。今後もさらなる技術を身につけて、素晴らしいWebGLアプリケーションを作り上げていきましょう!
Shaderの実践的な使い方と解説 webGL ViteでTypeScriptを用いたWebGLサイトの構成方法 WebGLとThree.jsで流体アニメーションを作成する