WebGL の型についてなんとなく調べはじめたら思ったより難しかった話

最近は TypeScrip を使わないと生き残っていけないな。なんて思って最近は WebGL でプロトタイプとか作るときも TypeScript 使ってるんですよね。まあ、けっこう適当な感じなんですけれど。

そんで、TypeScript といったら型ですよね。それで初めて気づいたんですけれど、WebGL って独自に型を定義してるってことに。存在する型が以下にまとまっていました。

https://developer.mozilla.org/ja/docs/Web/API/WebGL_API/Types

いやー、全然わからん。仕方ないから調べますかとうことで、とりあえず自分なりにまとめてみることにしました。


## Web IDL について
まず **Web IDL type** というカラムが気になります。
調べてみると、以下にサイトにて定義されていました。
https://triple-underscore.github.io/WebIDL-ja.html

要約を抜粋してみます。

> この文書は、 interface 定義言語， Web IDL を定義する — それは、 Web ブラウザが実装するものと意図される interface を記述するために利用できる。 Web IDL は，IDL の変種であり、［ Web プラットフォームにおいて共通なスクリプトオブジェクトに対し，そのふるまいを より容易に指定できるようにする ］ための，いくつもの特能を備える。 この文書では、［ Web IDL で記述される interface が，ECMAScript 実行環境の構成子にどう対応するか ］についても，詳細に述べられる。 この文書は、［ 既に発行済みの仕様 ／ 新たに発行され, この文書を参照する仕様 ］に適合している interface の実装が相互運用可能になるための，実装者向けの手引きになるものと期待されている。

一言でいえば **Web プラットフォームにおける interface 定義言語**ということですかね。

WebGL で使われている Web IDL type は、`Boolean` 以外では**整数型**や**浮動小数点数型**になり、以下に定義されています。

### 整数型
https://triple-underscore.github.io/WebIDL-ja.html#idl-integers
> 符号あり／符号なし 整数型や，とり得る値の範囲

### 浮動小数点数型
https://triple-underscore.github.io/WebIDL-ja.html#idl-floats
> 整数型でない数量型 — に対応する値の範囲

とのこと。JavaScript の数値型といえば `Number` ですね。符号があろうがなかろうが、浮動小数点でもコミコミで `Number` です。まあ、 `BigInt` なんてもありますが、まだサポートされているブラウザが少ないですね。

あと [`TypedArray`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) というオブジェクトがあります。これは型付き配列というものでその総称です。配列内の数値は Web IDL で定義されている整数型や浮動小数点数型のようなものがあります。パフォーマンス向上のため、WebGL ではこの `TypedArray` をよく使います。



## Type の種類について
Web IDL type が大体わかったところで、それぞれの Type についてみていきましょう。

### `GLenum`
Web IDL type： `unsigned long`

これは **enum 型**です。 設定する定数は [WebGL constants](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Constants) にあります。
つまり、 WebGL constants の値はすべて `unsigned long` ということになりますね。

例えば [`WebGLRenderingContext.drawArrays()`](https://developer.mozilla.org/ja/docs/Web/API/WebGLRenderingContext/drawArrays) の `mode` で使います。描画するプリミティブの種類とかですね。WebGL ではこういった形で定数をよく使いますので、`GLenum` は最もよく使う型かもしれません。

### `GLboolean`
Web IDL type： `boolean`

**真偽値**です。

> A Boolean.

潔い説明ですね。JavaScript の Boolean まんまなので、だったらそのまま使えばよいじゃないって感じです。意地でもはってるのでしょうか？まあ、おそらくですが OpenGL から派生したものだから、それに合わせて interface を定義しているのかなと思いました。

例えば [`WebGLRenderingContext.vertexAttribPointer()`](https://developer.mozilla.org/ja/docs/Web/API/WebGLRenderingContext/vertexAttribPointer) の `normalized` とかですね。まあ、真偽値があれば `GLboolean` だと思っておけばよいのではないでしょうか。

### `GLbitfield`
Web IDL type： `unsigned long`

直訳すると「**複数の論理ビットを格納するビットフィールド**」とのことですが、なにを言っているのかわからない。このあたりの低レベルなメモリ操作とか全然しないんでなかなか理解できない。まあ、分かる人にわかるはずですし、とりあえずスルーします。

例えば [`WebGLRenderingContext.clear()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/clear) で使われているとのことです。描画をクリアするときに指定する `gl.COLOR_BUFFER_BIT` などの定数が `unsigned long` であるということですね。

### `GLbyte`
Web IDL type： `byte`

ここからしばらくは比較的わかりやすいですね。Web IDL の型をそのまま定義している形です。
**8 ビットの範囲で -128 ～ 127 の整数**を扱えます。

探したんですが、使われているところが見つからない・・・。
果たして使い所はあるのだろうか？


### `GLshort`
Web IDL type： `short`

**16 ビットの範囲で -32,768 ～ 32,767 の整数**を扱えます。

そしてコレも探したんですが、使われているところが見つからない・・・。
`byte` もそうなんですが、定数では `BYTE` や `SHORT` と名のつくものは定義されているのんですよね。たまたま `enum` 以外では `byte` や `short` を使うところが無かった感じなんでしょうか？


### `GLint`
Web IDL type： `long`

名前の通り、いわゆる一般的な **int 型**ですね。
**32 ビットの範囲で -2,147,483,648 ～ 2,147,483,647 の整数**を扱えます。

例えば [`WebGLRenderingContext.drawArrays()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays) の `first` で使われています。頂点配列の開始位置のオフセットですね。頂点の情報を扱うだけあって大きな数値も扱えるようになっているのでしょう。

### `GLsizei`
Web IDL type： `long`

**サイズ関連に使われる型**とのことです。

例えば [`WebGLRenderingContext.texImage2D()
`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texImage2D) の `width` や `height` などのサイズに使われています。また、 [`WebGLRenderingContext.drawArrays()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/drawArrays) の `count` にも使われています。これは頂点の数ですね。これまた符号いらなくないとか思っちゃいましたが、まあ、それは置いておいて、余裕で 10 億以上いけますね。凄いパーティクルができそうです。マシンスペックさえ足りればですけれど。

### `GLintptr`
Web IDL type： `long long`

これは**ポインタ用の型**とのことです。JavaScript を書いていてポインタなんて聞くとは思っていませんでした。正直あまり理解してないですが、そいうことだそうです。

`long long` は初めてでてきましたね。
**64 ビットの範囲で -9,223,372,036,854,775,808 ～ 9,223,372,036,854,775,80  の整数**を扱えます。桁を数える気をなくすほどデカい。

例えば [`WebGLRenderingContext.vertexAttribPointer()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer) の `offset` などに使われています。インターリーブ配列の際にバイト数でオフセットを設定するものです。バイト数でってところが、ポインタ用ということと関係しているのでしょうか？

### `GLsizeiptr`
Web IDL type： `long long`

これは**ポインタ用の型**とのことです。説明が `GLintptr` と全く同じなんですよね。Web IDL type も一緒だし。説明責任を果たして欲しい。まあ、名前からすると `GLsizei` のようにサイズ関連に使うものかと思う。

例えば [`WebGLRenderingContext.bufferData()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData) の `size` などに使われています。まさにサイズ用って感じですね。バッファのデータサイズをバイト単位で設定するところですが、たいていの場合は `TypedArray` をそのまま入れちゃってるんじゃないでしょうか？他に使ってる箇所もピンこなかったのであまり縁はなさそうですが、バイトでサイズなら `GLsizeiptr` と覚えておくと良いかもです。

### `GLubyte`
Web IDL type： `octet`

なにげに `octet` って初めて知りました。聞いたことすらない。
**8 ビットの範囲で 0 ～ 255 の整数**を扱えます。
つまりは 1 バイトですかね。ってことを考えると凄く馴染み深いかも。RGB とか。

そんでコレも何に使われているかわからないです。んー、`short` 以下のは扱えないけどとりあえず定義してるとかなかなぁ？

### `GLushort`
Web IDL type： `unsigned short`

これは `GLshort` の符号なしバージョンです。
**16 ビットの範囲で 0 ～ 65,535 の整数**を扱えます。
この数値なんか見覚えあるなと思ったのですが、特定のパターンでスタックオーバーフロー起こすときの数ですね。つまりその箇所は `unsigned short` になっているということかな？

まあ、予想通りというか使われている箇所をみつけられなかったです。

### `GLuint`
Web IDL type： `unsigned long`

これは `GLint` の符号なしバージョンです。
**32 ビットの範囲で 0 ～ 4,294,967,295 の整数**を扱えます。

例えば [`WebGLRenderingContext.enableVertexAttribArray()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/enableVertexAttribArray) の `index` に使われています。attribute を有効化するインデックスを指定します。

### `GLfloat`
Web IDL type： `unrestricted float`

こらは浮動小数点型ですね。Web IDL の説明を抜粋します。

> 可能なすべての有限, 非有限［ 単精度 32 ビット IEEE 754 浮動小数点数 ］の集合に “非数（ not a number ）” （ 各種 NaN ）を加えた集合

気になるのは **[IEEE 754](https://ja.wikipedia.org/wiki/IEEE_754)** ですかね。浮動小数点の計算の規格です。JavaScript でもなく、Web IDL でもなく別で制定されている規格です。多くの言語などで採用されています。

[**単精度浮動小数点数**](https://ja.wikipedia.org/wiki/%E5%8D%98%E7%B2%BE%E5%BA%A6%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0) についてはリンク先をみてくださいませ。

例えば [`WebGLRenderingContext.uniformMatrix[234]fv()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/uniformMatrix) の `value` に使われています。普段は `Float32Array` を指定していますが、`GLfloat` をシーケンスとして指定できるそうです。シーケンスってなんだろ？


### `GLclampf`
Web IDL type： `unrestricted float`

こちらも `GLfloat` と同じく、**単精度浮動小数点数**です。
ただクランプされているそうなんですが、どういうことなのか分からないです。

調べてみると [`WebGLRenderingContext.blendColor()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/blendColor) に使われていますね。RGBA のそれぞれの値とのこと。**0 ～ 1 の範囲**なのでクランプされているのはその範囲なのかもしれないです。一応、他に使わている箇所をみても


### `GLint64` （WebGL 2）
Web IDL type： `long long`

WebGL 2 で追加された型です。
**64 ビットの範囲で -9,223,372,036,854,775,808 ～ 9,223,372,036,854,775,807 の整数**を扱えます。
`long long` 型はさきほども出てきましたが、ちょっと意味分かんないくらいの桁数ですね。正の数だけで 900 京以上あります。`GLintptr` と `GLsizeiptr` はポインタ用だから、それ以外で `long long` 型を使う用がなかったので追加したとうところでしょうか？

[`WebGLRenderingContext.getParameter()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter)の `pname` つまり、パラメータ定数の一部で使われています。WebGL 2 用の `gl.MAX_CLIENT_WAIT_TIMEOUT_WEBGL` とかで他にもいくつかありました。タイムアウトに関する内容のようなのですが、細かいことはわからなかったです。ただ、時間を扱うから大きな数を必要とするのかもしれませんね。

### `GLuint64EXT` （extensions）
Web IDL type： `long long`

これは拡張機能で使えるようです。
`GLint64` が実装される前に拡張機能で追加されたのかな？と思いましたが、説明をみると符号なしなんですよね。でも Web IDL type は `unsigned long long` ではなくて `long long` です。どういうことでしょうか？わからん。

こちらも同じ様に [`WebGLRenderingContext.getParameter()`](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter) の `pname` に使われています。対象のパラメータ定数は `ext.TIMESTAMP_EXT` だけでした。これは現在時刻とのことですので、やはり時間に関するものは 64 ビットが良いのかもしれません。


## 調べてみて
もともと型には強くないので、数値型の規格から学ぶ形になりました。なんとく知っていた部分もありましたが、ある程度ちゃんと知ることができてとても良い機会になったなと思います。

WebGL の型については結局ちゃんと分からないままの部分も多くて、ちょっと悔しい感じです。僕が分からなかった部分や曖昧に説明してる部分について、何か分かるようであれば教えてもらえると嬉しいです。あと、間違ってる部分もありそうなのでマサカリ待ってます。