この手の話はいろいろとありますが、とりあえず2点ほど書いておきます。
ちなみに、glBindBufferBaseの名前が出てきているということはOpenGL3.0以降が対象だと思いますが、自分はOpenGL2.0までしか知りません。しかし、おそらく3.0以降で通用する話だと思います。
ドローコールの削減
CPU/GPU間のデータ転送は、OpenGLの非常に大きなボトルネックになります。
と一言で言っても、気にかけるべき点はたくさんあるのですが、その中でも注意すべきは、
ドローコール(glDrawなんちゃらの呼び出し)です。
これが想像以上に処理負荷がかかります。
例えば、サイコロを100体描画します。
テクスチャは、1から6の面それぞれに用意します。
サイコロ一体に対して、一回ドローコールします。
…と、簡単にプログラムするとこんな感じになりますが、これだと6面☓100体=合計600回のドローコールを行うことになりますが、これだと非常に重い描画になります。
(試していないけど、まぁほぼ間違いなく)
テクスチャとシェーダが同じであればまとめてドローコールできるので、まず100体全ての1の面の頂点をまとめて、1回のドローコールで描画します。
続けて2の面、3の面、…と描画すると、6回のドローコールで処理が完結することになります。
更に、6枚のテクスチャを面ごとに用意していましたが、これをひとつのテクスチャにまとめます。
すると、6回のドローコールが一回で済みます。
(一般的にこの手の手法は「テクスチャアトラス」と呼ばれているようです)
描画する頂点数は変わりませんが、600回のドローコールと1回のドローコールでは雲泥の差になります。
まぁ、実際はこんなにうまく行くはずもありませんが、一般的にはこのようなドローコールの呼び出し回数を軽減する努力をします。
フラグメントシェーダの軽減化
他の方も少し話を出していますが、フラグメントシェーダの処理も処理軽減化の目安になります。
フラグメントシェーダは、描画するピクセル単位で処理を行うシェーダですので、例えば640x480の矩形領域に描画を行った際には、640☓480=307200回処理を行うことになります。
これだけ多いと、掛け算一つ、条件判定一つ増やしただけでも、GPUの処理負荷がかかってしまいます。
ですから、フラグメントシェーダは極限まで最適化すべきです。
場合によっては、演算や条件判定を増やすぐらいであれば、シェーダを別にしてしまうのも一つの考えです。
例えば、テクスチャと頂点カラーをブレンドして描画するシェーダがあったとします。
glsl
1uniform sampler2D tex; // テクスチャ
2varying vec2 uv; // UV
3varying vec4 color; // 頂点カラー
4void main()
5{
6 gl_FragColor = texture2D(tex, uv) * color;
7}
でも実際は、ほとんど頂点カラーはvec4(1.0, 1.0, 1.0, 1.0)で、テクスチャの色をそのまま表示するものばかりだった場合は、このシェーダは非常に無駄が多いことになります。
ですので、頂点カラーを使わないシェーダも使って分けて描画すれば、この無駄を削減することができます。
と書きましたが、矛盾点に気が付かれたかもしれません。
最後に「シェーダを増やせばいい」なんて書きましたが、シェーダを増やせばその分だけドローコールも増えることになるので、これらは(単純には)両立しないということです。
状況に応じて処理の軽減化を図る必要があります。
(例えば、CPU負荷がかかっているがGPUの処理には余裕があるならば、シェーダに負荷をかけてでもドローコールを減らす、など)
他にも、ミップマップテクスチャを使ったり、カメラの遠近によって処理を変えたり、いろいろと手段はあります。
市販のPCゲームレベルとなると、一筋縄では行かないと思いますので、いろいろと調べてみてください。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/11 12:47