WebGL best practices

この文書は WebGL を使ったコンテンツの向上のための Tips について書きます。これらの提案に従うことで、多くの機器への互換性を高めたり、パフォーマンスを上げることにもなります。

避けたほうがいいこと

  • WebGL のエラーを出さないように注意しましょう。エラーは getError() で得られますが、Firefox では webgl.verbose の設定を有効にすることで、ウェブコンソールに WebGL のエラーと警告を出力します。ユーザーのコンソールにエラーを吐き出す必要はないでしょう?(訳註:パフォーマンスの理由もある。下参照)
  • #ifdef GL_ES は絶対に使ってはいけません。初期の例ではこれが使われていましたが、WebGL では必ず true になるので必要ありません。
  • フラグメントシェーダで highp 精度を使うのはやめましょう。mediump を代わりに使いましょう。highp を使うと今のモバイルのハードウェアのほとんどで動きません。Firefox 11 からは getShaderPrecisionFormat() 関数が実装されるので、highp 精度が使えるかどうかだけでなく、それぞれの精度の名称について実際の精度を知ることができます。

覚えておいたほうがいいこと

  • WebGL の機能の中にはクライアントによって制限があるものがあります。そういうものを使う前には getParameter() を使って調べましょう。例えば、2D テクスチャのサイズは webgl.getParameter(webgl.MAX_TEXTURE_SIZE) でわかります。Firefox 10 からは webgl.min_capability_mode の設定があり、最低限の機能の環境をシミュレートすることができます。
  • 特に、頂点シェーダでのテクスチャの使用は webgl.getParameter(webgl.MAX_VERTEX_TEXTURE_IMAGE_UNITS)がゼロより大きくなければ使えません。現在のモバイルのハードウェアではまず使えないでしょう。
  • WebGL の拡張が使えるかどうかはクライアントに依存します。できるならそれらの使用をオプションとし、サポートされていない環境にも対応できるようにしましょう。Firefox 10 からは webgl.disable-extensions の設定があり、拡張のない環境をシミュレートすることができます。
  • OES_texture_float 拡張がサポートされていたとしても、浮動小数点数テクスチャへのレンダリングはサポートされていないかもしれません。モバイルのハードウェアではまず動かないでしょう。サポートされているかを調べるには checkFramebufferStatus() を使ってください。

一般的なパフォーマンスの tips

  • CPU と GPU の同期を必要とするものはすべて、とても遅い可能性があり、メインのレンダリングループでは避けたほうがいいでしょう。getError()readPixels()finish() などの関数がそれです。getParameter()getUniformLocation() といった WebGL のゲッタも遅いので、JS 側で変数にキャッシュしてください。
  • 大きい描画を少数だけしたほうがパフォーマンスが向上します(訳註:小さな描画をたくさん行うより)。1000 回の小さなものを描画するなら、一回の drawArrays()drawElements() でやりましょう。一回の drawArrays() で離れたオブジェクトを描画するなら、3 点が一直線上にある三角形が使えます。
  • 状態の変更が少ないほどパフォーマンスが向上します。特に、複数の画像をひとつのテクスチャにまとめて適切な座標を使うことでバインドしているテクスチャの変更が少なくて済みます。
  • 小さなテクスチャは大きなテクスチャよりパフォーマンスが良いです。そのため mipmap が有効です。
  • 簡単なシェーダーは複雑なものよりもパフォーマンスが良いです。特に、if 文を減らせば速くなります。割り算や log() などの数学の演算もコストが高いです。

参照