そのため、現在、複雑なモデルを適切な速度でレンダリングしようとしていますが、問題が発生しています。単一のモデルをレンダリングすると、プログラムに追加の作業を行わなくても、フレームレートが低下します。私のモデル(シーンに1つしかない)は大きすぎるようです。バッファにアップロードする頂点配列には444384のfloatがあります(したがって、モデルには24688の三角形があります)。
//Create vertex buffers
glGenBuffers(1, &m_Buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
int SizeInBytes = m_ArraySize * 6 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, SizeInBytes, NULL, GL_DYNAMIC_DRAW);
//Upload buffer data
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * VertArray.size(), &VertArray[0]);
A)サイズを小さくするとパフォーマンスが向上し、B)レンダリングコードをコメントアウトするため、VBOのサイズが違いを生むことを私は知っています。
glPushMatrix();
//Translate
glTranslatef(m_Position.x, m_Position.y, m_Position.z);
glMultMatrixf(m_RotationMatrix);
//Bind buffers for vertex and index arrays
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), 0);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 6 * sizeof(float), (void*)12);
//Draw
glDrawArrays(GL_TRIANGLES, 0, m_ArraySize);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
//Unbind the buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glPopMatrix();
約2000〜2500 FPSが残りますが、このコードのコメントを外すと、約130FPS、つまり8ms /フレームになります(これだけで十分ですが、プログラムで他のこともできる必要があります。これはCPUを集中的に使用する可能性があります)。85kの三角形を持つより複雑なモデルでは、50 FPS未満、つまり約20ms /フレームになり、その時点でプログラムは目に見えて途切れます。
私が使用している1組のシェーダーは、現時点ではごくわずかです。それが問題だとは思えません。念のため、ここにあります。最初に頂点シェーダー:
void main()
{
vec3 normal, lightDir;
vec4 diffuse;
float NdotL;
/* first transform the normal into eye space and normalize the result */
normal = normalize(gl_NormalMatrix * gl_Normal);
/* now normalize the light's direction. Note that according to the
OpenGL specification, the light is stored in eye space. Also since
we're talking about a directional light, the position field is actually
direction */
lightDir = normalize(vec3(gl_LightSource[0].position));
/* compute the cos of the angle between the normal and lights direction.
The light is directional so the direction is constant for every vertex.
Since these two are normalized the cosine is the dot product. We also
need to clamp the result to the [0,1] range. */
NdotL = max(dot(normal, lightDir), 0.0);
/* Compute the diffuse term */
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
gl_FrontColor = NdotL * diffuse;
gl_Position = ftransform();
}
そしてフラグメントシェーダー:
void main()
{
gl_FragColor = gl_Color;
}
グラフィックカードとしてGTX660Mを使用してプログラムを実行しています。
私の知る限り、VBOはOpenGLで大量のポリゴンをレンダリングする最速の方法であり、インターネットは多くのマシンが一度に数百万のポリゴンを計算して表示できることを示唆しているようです。比較的わずかな27kの三角形のレンダリングを最適化するため。将来、大量のコードを書き直して再構築するよりも、今それを実行したいと思います。
裏面カリングを有効にしました。モデルのすべてまたはほとんどが画面に表示されることがあるため、fustrumカリングが役立つかどうかはわかりません(現在、オブジェクトをカリングしていますが、個々のオブジェクト内の三角形はカリングしていません)。カメラに面していないビューポートの面をカリングすると少し役立つかもしれませんが、その方法がわかりません。それを超えて、レンダリングを最適化するために何をすべきかわかりません。頂点バッファはまだ実装していませんが、速度が10%程度しか向上しない可能性があることを読みました。
他の処理が行われている状態で、許容可能なフレームレートで画面上に一度に数万または数十万の三角形を達成するにはどうすればよいでしょうか。VBOレンダリングのパフォーマンスを向上させるために何ができますか?
更新:以下のコメントに従って、次のように配列の半分だけを描画しました。
glDrawArrays(GL_TRIANGLES、0、m_ArraySize / 2);
そして、アレイの4分の1:
glDrawArrays(GL_TRIANGLES、0、m_ArraySize / 4);
毎回描画されるアレイの量を減らすと、文字通り速度が2倍になります(それぞれ12ミリ秒から6ミリ秒と3ミリ秒に)が、モデルは完全に無傷で、何も欠けていませんでした。これは、私がどこかで何か間違ったことをしていることを示唆しているようですが、何が起こっているのかわかりません。モデルを作成するときに同じ三角形を4回以上追加しないとかなり確信しているので、他に何ができるでしょうか。どういうわけか、バッファを複数回アップロードしている可能性がありますか?