6
votes

I have a webgl application, I've written using threejs. But the FPS is not good enough on some of my test machines. I've tried to profile my application using Chrome's about:tracing with the help from this article : http://www.html5rocks.com/en/tutorials/games/abouttracing/

It appears that the gpu is being overloaded. I also found out that my FPS falls drastically when I have my entire scene in the camera's view. The scene contains about 17 meshes and a single directional light source. Its not really a heavy scene. I've seen much heavier scenes get render flawlessly on the same GPU.

  • So, what changes can I make in the scene to make it less heavy, without completely changing it? I've already tried removing the textures? But that doesn't seem to fix the problem.
  • Is there a way to figure out what computation threejs is pushing on to the GPU? Or would this be breaking the basic abstraction threejs gives?
  • What are general tips for profiling GPU webgl-threejs apps?
1
Check the WebGL Inspector tool to determine your draw calls. Also, what machine are you on? Also, sometimes it is not about the number of objects and instead in the number of vertices. How many vertices are you drawing, also how many textures do the objects use and how many shaders? Try one grey shading material and see if it works way better. You could also improve the scene by using BufferGeometry, if you havent done this yet. There is also a function to convert from THREE.Geometry to THREE.BufferGeometry for exampleGuyGood

1 Answers

6
votes

There are various things to try.

Are you draw bound?

Change your canvas to 1x1 pixel big. Does your framerate go way up? If so you're drawing too many pixels or your fragment shaders are too complex.

To see if simplifying your fragment shader would help use a simpler shader. I don't know three.js that well. Maybe the Basic Material?

Do you have shadows? Turn them off. Does it go faster? Can you use simpler shadows? For example the shadows in this sample are fake. They are just planes with a circle texture.

Are you using any postprocessing effects? Post processing effects are expensive, specially on mobile GPUs.

Are you drawing lots of opaque stuff? If so can you sort your drawing order so you draw front to back (close to far). Not sure if three.js has an option to do this or not. I know it can sort transparent stuff back to front so it should be simple to reverse the test. This will make rendering go quicker assuming you're drawing with the depth test on because pixels in the back will be rejected by the DEPTH_TEST and so won't have the fragment shader run for them.

Another thing you can do to save bandwidth is draw to a smaller canvas and have it be stretched using CSS to cover the area you want it to appear. Lots of games do this.

Are you geometry bound?

You say you're only drawing 17 meshes but how big are those meshes? 17 12 triangle cubes or 17 one million triangle meshes?

If you're geometry bound can use simplify? If the geometry goes far into the distance can you split it and use lods? see lod sample.