Hatena::Groupjavascript

JavaScriptで遊ぶよ

2011-12-22

WebGL best practices

20:12

MDNにこういうドキュメントがあると教えてもらったので翻訳してみます。

元のライセンスは"Creative Commons: Attribution-Sharealike license"で、僕の翻訳について著作権は主張しません。(なので https://developer.mozilla.org/ja/ に転載したい人がいればご自由に)

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