DartでWebGL

#DartでWebGL

Dart Advent Calendar 2日目、よろしくお願いします。

DartでWebGL書いてみて、その感想でも書こうかと思います。
さて、WebGLといえばOpenGL ES 2.0のJavaScriptバインディングですが、
もちろんJavaScriptで書かなければいけないというわけではありません。

私は少し前までCoffeeScriptで書いてましたし、TypeScriptなんかでもかけるみたいですね。

## 最近書いてるもの

WebGLってAPIが低レベルすぎて面倒なので割りとスニペットというかオレオレフレームワークというかそういうのがあるといろいろやりやすいので作ってます。
![teapot.jpg](https://qiita-image-store.s3.amazonaws.com/0/5907/24ee5f2d-81a2-752e-18db-389a9766ef0f.jpeg)
https://dl.dropboxusercontent.com/u/27815754/webgl_framework/webgl_framework.html

ソースコードはこちら
https://github.com/nyamadan/webgl_framework

## Dartを使う理由

### 入力補完に強い
JavaScriptと違いオプショナルな型が存在します。
そのおかげなのでしょうか入力補完に優れているように感じます。
まぁ、これはWebStormがすごいだけかも知れませんが。

### ビルドが不要
JavaScriptはGruntやglupのようなツールが充実してはいますが、やはりビルドは鬱陶しいものです。
CoffeeScriptを書くためにまずはGruntfileを用意して、というのは結構面倒でした。
その点、DartはChromiumで動作するためコンパイルする必要すらありません。
デバッガもソースマップではなく、ちゃんとDartとしてデバッグすることができます。
まぁツール周りはWebStormが面倒見てくれるのでWebStormがすごいだけかもしれませんが。

### ベンダprefixが省略可能なことがある
WebRTCってまだwebkitっていうprefixが必要なんですよね。
でもDartだとこの辺を省略してかけたりします。
FirefoxでもChromeでもちゃんと動作するのできっと自動でprefixつけてくれているのですね。

### SIMD対応
WebGLではベクトルや行列演算を多用します。
これを高速化できるAPIはありがたいですね。
https://www.dartlang.org/articles/simd/

### サーバーでも動作
ブラウザ側での動作する行列演算スクリプトなんかをサーバーに持っていけるのって時々役に立ちますよ？

拙作のShader Playground(非公開)なんかはサーバーもクライアントも全部Dartで書いてます。

### Futureが標準実装
ES6のPromiseに当たる実装がすでに標準実装として用意されています。
サードパーティライブラリなどがコレを使って実装されていることが多いため、自分で書いたFutureとつなげやすかったりすることがあります。

### 互換保ちつつメソッドの手直ししてる
テクスチャに画像を流し込むtexImage2D`って関数があるのですがこれの定義がえぐい。

```js
    void texImage2D(GLenum target, GLint level, GLenum internalformat, 
                    GLsizei width, GLsizei height, GLint border, GLenum format, 
                    GLenum type, ArrayBufferView? pixels);
    void texImage2D(GLenum target, GLint level, GLenum internalformat,
                    GLenum format, GLenum type, ImageData? pixels);
    void texImage2D(GLenum target, GLint level, GLenum internalformat,
                    GLenum format, GLenum type, HTMLImageElement image); // May throw DOMException
    void texImage2D(GLenum target, GLint level, GLenum internalformat,
                    GLenum format, GLenum type, HTMLCanvasElement canvas); // May throw DOMException
    void texImage2D(GLenum target, GLint level, GLenum internalformat,
                    GLenum format, GLenum type, HTMLVideoElement video); // May throw DOMException
```
from https://www.khronos.org/registry/webgl/specs/1.0/

型が変わるわ、引数の数はかわるわでイマイチ引数をどう渡したらいいかわからない。

Dartだとこの辺の関数はそれぞれ別の関数として用意されてるのでどんな引数与えたらいいのか困ることも少ない。
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:web_gl.RenderingContext#id_texImage2D
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:web_gl.RenderingContext#id_texImage2DImage
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:web_gl.RenderingContext#id_texImage2DCanvas

## Dartのイマイチいけてないところ

### デバッガーが不安定
割とすぐクラッシュする。なんでや！

### そこまで型に厳しくなくても
intとdoubleの区別が結構厳密です。0.0と0が区別されます。
doubleを期待してるところにintを与えるとエラーになり、toDoubleしたりします。
ずっとゆるい言語書いてきたのでそれぐらいゆるしたげてよーってなります。
とくにjsonでデータ交換するとintだかdoubleだかの情報が失われてしまうので面倒です。

### サーバーフレームワークって何がいいのかよくわからない
わからない。
node-expressみたいにサクッと環境用意できるのが好きなんだけど、そういうのあるんですかね。

### なんか日本で流行ってない感ある
俺の気のせいでしょうか。

# 最後に
なんやかんや書いたけどやっぱり一番はビルド不要というのが気に入ってる一番の理由です。
やっぱりGruntfile書くの面倒です・・・。

あと最近Dartでこんなんもつくって遊んでたりします。

![mmd.jpg](https://qiita-image-store.s3.amazonaws.com/0/5907/e8139ad4-f5cc-f4ab-80eb-229d7adb46e9.jpeg)

ちょっとこれはまだ動く状態までいってないけど気長に手を加えていこうかなって思ってる。

明日は再び @laco0416 ですね。よろしくお願いします！