私は WebGL を学ぼうとしてきたので、簡単なモデル ロード スクリプトを作成しました。Chrome の devtools タイムラインを表示して、100 個のモデルをレンダリングするときに最大 20 FPS を取得していることを確認するまで、すべてうまく機能していると思っていました。奇妙な部分は、各フレームでほとんどの時間 CPU がアイドル状態だったことです。
私が最初に考えたのは、私は GPU に依存しているに違いないということでした。これは、私のシェーダーが短く、あまり複雑ではないため、ありそうにないように思えました。10 個のモデルでテストし、1 個だけで再度テストしたところ、パフォーマンスは向上しましたが、それでも 40 FPS 未満でした。chrome://tracing をプルアップしたところ、両方の GPU がフレームごとにあまり機能していないことがわかりました。CrGpuMainの各フレームの大部分は"Processing Swap" で満たされ、CrBrowserMain はほぼすべての時間を glFinish ("CompositingIOSurfaceMac::DrawIOSurface" によって呼び出される) に費やしました。
glFinish ではなく、Processing Swap が大きな問題のようです。
私の質問は、ブラウザが glFinish に多くの時間を費やしている原因は何ですか? この問題を解決する方法についてのアイデアはありますか?
各モデルには 40608 個の要素と 20805 個の頂点があります、
更新 - 単純化されたメッシュの数を修正:
- 3140要素
- 6091頂点
モデルは疑似インスタンス化されるため、データはフレームごとに 1 回だけ GPU に渡されます。頂点の数が多いことが問題ですか?
デモはここにあります。
レンダリング コード:
Thing.prototype.renderInstances = function(){
if (this.loaded){
var instance;
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexbuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.normalbuffer);
gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute, 3, gl.FLOAT, true, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexbuffer);
for(var i in this.instances){
instance = this.instances[i];
setMatrixUniforms(instance.matrix);
gl.drawElements(gl.TRIANGLES, this.numItems, gl.UNSIGNED_SHORT,0);
}
}
};
頂点シェーダー コード:
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
uniform mat4 uMMatrix;
uniform mat4 uVMatrix;
uniform mat4 uPMatrix;
uniform vec3 uLightDirection;
varying float vLight;
void main(void) {
mat4 MVMatrix = uVMatrix*uMMatrix;
//Toji's manual transpose
mat3 normalMatrix = mat3(MVMatrix[0][0], MVMatrix[1][0], MVMatrix[2][0], MVMatrix[0][1], MVMatrix[1][1], MVMatrix[2][1], MVMatrix[0][2], MVMatrix[1][2], MVMatrix[2][2]);
gl_Position = uPMatrix*uVMatrix*uMMatrix*vec4(aVertexPosition, 1.0);
vec3 lightDirection = uLightDirection*normalMatrix;
vec3 normal = normalize(aVertexNormal*normalMatrix);
vLight = max(dot(aVertexNormal,uLightDirection),0.0);
}