I'm creating a first person shooter in Webgl and currently debugging an early version in Chrome 31.0.1650.57

The application is running poorly at about 7-8 fps, and when I cpu profile I get the following:

enter image description here

And from that it looks like the cpu is spending 72% time doing... nothing? How come requestAnimFrame is giving me that low fps then? My shaders are really really simple (basically 1 liners)

My game loop is essentially

function drawScene() {
    requestAnimFrame(drawScene);
    map.render(playerPosition);
}

The graphics are also currently very simple. I've included a screenshot of the application as well, along with the full .cpuprofile file.

screenshot

Can anyone explain what the idle time could be caused by?

UPDATE: The map is stored as a bunch of "faces", where each face is a gl.TRIANGLE_FAN. I'm not sure how I can draw multiple gl.TRIANGLE_FANs (each with a different "center" element) in 1 call to gl.drawElements.

I tried to modify the code so that I upload the vertices to the gpu once, and then just upload indices into the array of vertices, but this causes the gl.drawElements to draw 1 giant gl.TRIANGLE_FAN, which is not correct since all the gl.TRIANGLE_FANs don't share the same "center" vertex.

Can I somehow convert the gl.TRIANGLE_FANs into gl.TRIANGLES or gl.TRIANGLE_STRIPS?

I realise that OpenGL has a glMultiDrawElements which does exactly what I wan't (Let's you pass in the size of each primitive), but it doesn't look like it's supported in Webgl.

有帮助吗?

解决方案

Looking at your profile, I notice you're spending a lot of time in bufferData. This suggests you're re-uploading data every frame, and some of the rest of the function names suggest you're doing per-surface drawArrays calls.

Both of these things are bad for performance. I suspect that your missing time is going to GPU-CPU synchronization and data transfer, rather than GPU compute time or CPU compute time (the last being what your profile measures).

  1. You should upload geometry to the GPU (bufferData) only once and not every frame (unless something is actually changing, or new objects are added to the scene, etc.), and

  2. you should try to minimize the number of drawArrays calls per frame (few batches of many vertices, rather than many batches of few vertices).


You have said that the constraint is that your level data is made of individual triangle fans. You will need to convert these triangle fans to individual triangles and combine those triangles into a single buffer. There is nothing in WebGL to do this for you, but if you have vertices of a fan 0 1 2 3 4 ..., where 0 is the central vertex, then converting them to triangles is just specifying the vertices (by an index buffer, or by copying the vertices) in order

0 1 2 0 2 3 0 3 4 ...

Then you can combine many fans into a single draw call.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top