8

たとえば、次のような頂点シェーダーを使用するとします。

#version 400 core

uniform mat4 projM;
uniform mat4 viewM;
uniform mat4 modelM;

in vec4 in_Position;

out vec4 pass_position_model;

void main(void) {
    gl_Position = projM * viewM * modelM * in_Position;
    pass_position_model = modelM * in_Position;
}

頂点ごとに行列の乗算を行うprojM * viewM * modelMのか、それとも一度計算して一様変数が変更されるまで再計算しないほどスマートなのか? 「十分にスマート」でない場合、CPU で均一に依存するすべての値を計算し、それらを均一変数として GPU に送信する以外に最適化する方法はありますか?
また、後で問題なく OpenGL ES 2.0 に移植できるソリューションにも興味があります。

4

4 に答える 4

10

したがって、私が理解しているように、一般的な答えはありません。ただし、ハードウェアでいくつかのテストを行いました。インベントリに 2 つの GPU がIntel HD Graphics 3000あり、NVidia GeForce GT 555M. 私は自分のプログラム (プログラム自体は java/scala で書かれています) を頂点シェーダーの行列乗算でテストし、次に乗算を CPU プログラムに移動して再度テストしました。

(sphereN - glDrawElements(GL_QUADS,...) で描画された 2*N^2 クワッドを持つ連続的に回転する球体で、1 つのテクスチャを持ち、照明やその他の効果はありません)

頂点シェーダーでの行列乗算:

intel:
    sphere400: 57.17552887364208 fps
    sphere40: 128.1394156842645 fps
nvidia:
    sphere400: 134.9527665317139 fps
    sphere40: 242.0135527589545 fps

CPU での行列乗算:

intel:
    sphere400: 57.37234652897303 fps
    sphere40: 128.2051282051282 fps
nvidia:
    sphere400: 142.28799089356858 fps
    sphere40: 247.1576866040534 fps

テストによると、頂点シェーダーで (均一な) 行列を乗算することは、少なくともこのハードウェアでは悪い考えです。したがって、一般に、対応する GLSL コンパイラの最適化に依存しない場合があります。

于 2013-03-18T11:19:45.437 に答える
1

すべての OpenGL および GLSL の最適化はベンダー固有です。glsl コンパイラからの最終的な出力が何であるかを判断するのは非常に困難です。

ベンダー固有の情報については、http: //renderingpipeline.com/graphics-literature/low-level-gpu-documentation/を参照してください。

あなたのコードでは、いつでもマトリックスを新しいuniform:に「パック」matModelViewProjectionし、アプリケーションで乗算し、頂点シェーダーに送信できます。

于 2013-03-17T15:06:12.173 に答える
0

それは完全にドライバー次第です。OpenGL は仕様です。実装を行う権利を支払うと、使用するサンプルの実装が提供されますが、それだけです。

それとは別に、行列の乗算の制限を考慮する必要があります。実行することは実行することとprojM * viewM * modelM * vertex同じではありませんvertex * projM * viewM * modelM。これは、行列が右から左に乗算され、順序が重要になるためです。そのため、シェーダーprojM * viewM * modelMは頂点間で共有するように事前計算できませんでした。これは、誤った結果をもたらすためです。

于 2013-03-17T15:15:46.967 に答える