three.jsって、WebGLって、OpenGLなに?

three.jsって、WebGLって、OpenGLなに?

October 25, 2020

先日、three.js に触れる機会があったのですが(three.js の表面をさっと撫でた程度の、本当にほんの少し)、そもそもこれってどうやって動いているの?などと調べたらいろいろな用語が出てきてよく分からなくなったので整理します。

とはいえ、結局深いところは理解できていないので、あくまでも自己満足用の概念レベルの整理に留まっています。

three.js とは? #

javascript のライブラリです。3 D モデルなどが描画できるスゴイやつです。以下のサイトでは、three.js で製作された作品を見ることができます。

https://threejs.org/

three.js を使えば誰でもこんなことができる!………というわけではありません。上記のサイトに載っているのは、three.js を極めすぎた作品たちです。

Wikipedia では以下のように説明されています。

WebGL という Web 標準技術の登場により商用のブラウザ拡張機能に頼る必要なしに、HTML ファイル内に埋め込まれた JavaScript を介して、GPU アクセラレーションによる動的表現を描画することが可能になった。three.js は、WebGL の API を簡略化するためのラッパである。

Three.js - Wikipedia

最後の一文がすべてです。つまり、three.js は WebGL の API を扱いやすくしてくれるラッパーのライブラリです。

ということで次の疑問になりますよね?

WebGL とは? #

WebGL という用語は聞いたことがありましたが、具体的にどんなものなのかわかっていませんでした。WebGL Developer Org(https://wgld.org/)の説明を見てみましょう。

WebGL は、ウェブブラウザ上で OpenGL ES に相当するグラフィックス API の機能を利用することができる JavaScript の API です。

wgld.org

OpenGL ES という新たなワードが出てきました。wgld.org の別のページでは WebGL と OpenGL ES との関係性を説明してくれています。

OpenGL ES との関係

WebGL はそもそも「OpenGL ES のバインディングである」という記述をよく見かけますね。これはもう少し砕けた言い方をすると、OpenGL ES 相当のグラフィックス API を、JavaScript の API として実行できるのが WebGL であるという意味になります。OpenGL ES はモバイル向けの軽量な OpenGL 実装ですが、その機能をそのままブラウザ上で実行できる形にしたのが WebGL なのですね。

wgld.org

OpenGL ES および OpenGL とは? #

Wikipedia にお世話になります。

OpenGL ES

OpenGL ES(OpenGL for Embedded Systems)は、主に携帯電話などの組み込みシステムで使用されている 3 次元コンピュータグラフィックス用 API である。OpenGL ES は、従来から存在する(主にデスクトップ PC やワークステーション向けの)クロスプラットフォームなリアルタイム 3D グラフィックス API である OpenGL のサブセットである。OpenGL 同様、グラフィックスハードウェア(GPU)の機能および性能を活用した高速なグラフィックス描画が可能となる。

OpenGL ES - Wikipedia

つまり、OpenGL ES は、OpenGL の組込システム(Embedded Systems)用ということのようです。OpenGL についても少し説明が書いてありますが、改めて調べてみましょう。少し詳しい部分まで理解するため、長めに引用します。

OpenGL

OpenGL(オープンジーエル、Open Graphics Library)は、クロノス・グループ (英: Khronos Group) が策定している、グラフィックスハードウェア向けの 2 次元/3 次元コンピュータグラフィックスライブラリである。

OpenGL は、SGI をはじめ、ヒューレット・パッカード (HP)、サン・マイクロシステムズ(現オラクル)、IBM、SONY-NEWS などの UNIX ワークステーションの他、Linux、FreeBSD などの PC UNIX に加え、Windows、macOS 等で使用できるクロスプラットフォームなグラフィックス API である。

オープン標準として公開され、幅広い処理系に対応しているため、家庭用・業務用問わず広く普及している。描画デバイスの実装を隠蔽する抽象化層として機能するため、移植性が高い。また、描画演算処理を OpenGL に対応する専用ハードウェア (GPU) に委ねることで非常に高速に動作し、CPU のみによるソフトウェア描画と比較して高フレームレートかつ詳細に 3D 画像を描画できる。

OpenGL API は C 言語関数群の形で提供され、またクロノスグループが策定・公開しているのは、OpenGL API 仕様のドキュメントおよび C/C++用のヘッダーファイルだが、Fortran や Java などの他言語向けのラッパー/バインディングも存在する。

OpenGL - Wikipedia

つまり、OpenGL とは、Linux や Unix、Windows や macOS などのネイティブ環境上で使われるライブラリ(API とも書いてありますが、ライブラリという捉え方の方がより明確だと思います。)で、実態は C 言語の関数郡です。OpenGL が提供する関数を利用して、GPU に命令を出し、画面描画させることができます。

グラフィックスを扱う他のライブラリの一例として、Microsoft が開発した Microsoft DirectX だったり、Direct3D だったりがあり、これは Microsoft 系の環境上で動きます。Apple は Metal というライブラリを作っていて、これは Apple 系の環境上で動きます。こんな感じで各 OS ごとにバラバラだった状況について、Java のスローガンのような"Write once, run anywhere"な感じにしようとしたのが OpenGL だったのでしょう。

で、気になったのが、OpenGL もまたライブラリなのであれば、OpenGL は何をラッピングしているの?ということです。

シェーディング言語? #

ここらへんまでいくと、レイヤーが深くなりすぎて、調べて出てきた内容が合っているのか、自分では分からなくなってくるのですが、一応続けます。

シェーディング言語(英: shading language)はプログラマブルシェーダー向けのプログラミング言語のこと。この種の言語は色や法線のような特別なデータ型を持っている。C 言語や Java のような汎用言語とは異なり、標準入出力機能を持たないなど、特定領域に特化した DSL の一種である。

シェーディング言語 - Wikipedia

シェーディング言語の一例として、GLSL という名前が上がっていたので、調べました。

GLSL (OpenGL Shading Language) は GLslang としても知られ、C 言語をベースとした高レベルシェーディング言語である。これはアセンブリ言語やハードウェアに依存した言語を使わないで、アプリケーションソフトウェア開発者がグラフィックスパイプラインを直接制御できるように OpenGL ARB (Architecture Review Board)で策定された。

GLSL - Wikipedia

ということなので、シェーディング言語が GPU に命令を出していると思っていいのかな?

結局のところ、最終的にはすべて機械語(01 の世界)に変換されて実行されるので、命令を出すのは機械語だ、というのが正解でしょうが、これ以上深堀するのはやめておきます。

ちなみに、GLSL の説明の中に、以下の記載がありました。

Web ブラウザ向けの OpenGL ES 派生規格として WebGL が存在するが、WebGL でも GLSL が使用される。

GLSL - Wikipedia

WebGL も GLSL を使っているのですね。

ちなみに、CPU と GPU の違いは? #

CPU は複雑な命令を実行できるが処理は遅く、GPU は単純な命令を実行するが処理は速い、とよく説明されますが、これまでいまいち感覚的に理解できていませんでした。今回記事にした諸々を調べている最中にどこかで見かけたのですが、以下の例えがわかりやすかったです。

  • CPU:複数種類の関数を処理するイメージ
  • GPU:1つの関数を、引数を変えながら並列で処理するイメージ

最後にまとめると #

three.js は WebGL を扱いやすくした javascript のライブラリです。WebGL は、OpenGL ES を扱う感覚で、ウェブブラウザから GLSL というシェーディング言語を実行できるようにしたものです。これにより、GPU に命令を出し、画面描画させることができます。

…こんな感じでいいのですかね?間違っている部分もあるかもしれませんが、概念的にはなんとなく理解できたので良しとしましょう!