我一直在尝试学习 WebGL,所以我制作了一个简单的模型加载脚本。我认为它工作得很好而且花花公子,直到我调出 Chrome 的 devtools 时间线并看到渲染 100 个模型时我得到了大约 20 FPS。奇怪的是,CPU 在每一帧的大部分时间都是空闲的。
我的第一个想法是我必须受 GPU 限制,这似乎不太可能,因为我的着色器很短而且不是很复杂。我测试了 10 个模型,然后又只测试了一个模型,这确实提高了性能,但我仍然获得不到 40 FPS。我打开了 chrome://tracing,发现我的两个 GPU 对每一帧都没有做太多的事情。CrGpuMain中每一帧的大部分都填充了 "Processing Swap",并且 CrBrowserMain 几乎将所有时间都花在了 glFinish 上(由 "CompositingIOSurfaceMac::DrawIOSurface" 调用)。
处理交换似乎是主要问题,而不是 glFinish。
所以我的问题是,是什么导致浏览器在 glFinish 上花费这么多时间?关于如何解决这个问题的任何想法?
每个模型有 40608 个元素和 20805 个顶点,
更新 - 更正了简化网格的数量:
- 3140 个元素
- 6091 个顶点
这些模型是伪实例化的,因此每帧数据只传递给 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);
}