Slow FPS on camera rotation

I have implemented a basic set of controls in a THREE project, WASD for the usual forward back left right etc, I have used the arrow left and right for camera rotation, however, if I start my project and use the WASD keys it sticks to 60fps if I start to rotate it goes to 1FPS for about 2 seconds then ramps back up to 60 and after a few rotations it stays at 60FPS.
Here is the code for rotation:

PLAYER_TURN_SPEED = Math.PI * 0.02; += this.PLAYER_TURN_SPEED; //Left arrow key -= this.PLAYER_TURN_SPEED; //Right arrow key

This is obviously in a keyboard handler called every frame render.

Any ideas? camera.position works fine but camera.rotation kills the FPS for about 5 seconds then goes about its normal self.

Maybe because objects out of camera frustum was not added to videocard and then rotate camera they adding to videocard. Try for all meshes set


Hi @Chaser_Code thanks for the suggestion, however it doesn’t appear to make a difference unfortunately.


Logically, if the rotation goes back to its normal in terms of performance after a while, after starting badly, and assuming something different in the scene is rendered on every frame, then something about your “initialization” (of either the objects or the animation) is the issue and causes the “lag”.

Out of curiosity, do you preload your resources? Meaning, do you load, download, upload or whatever the images, videos, audios that you use in your case before you let the user animate stuff? Ideally, you’d only animate / rotate / etc. once you have everything ready in terms of texture sources loaded, the textures applied to the materials, the meshes already created, and so on.

Hi @Yin_Cognyto.
I create the scene (load the map) once, then I call the update function which starts rendering, once the map is loaded nothing changes apart from player position, at the moment it is a bunch of meshes with different colours on, no textures, no sounds the only thing the update function is doing extra is checking for keypresses.

Well, the process looks fine, from what you said. Changing the “map” or the “player” (if there is an object for that) objects to something simpler and easier on the system might help identify which one of them is causing the slowdown when rotating. Normally, high resolution texture images might probably produce such slowdowns, but if you said that there are only colors, it’s not that.

A good idea would be to check the code for the keyboard handler as well, to make sure stuff is not done more times than necessary, and the render process waits and only renders things within the requestanimationframe() context. I might be wrong, but from what I know, a: += this.PLAYER_TURN_SPEED;

at, say, key down event, is not quite the same as:

requestAnimationFrame(function() { += this.PLAYER_TURN_SPEED;});

The former is doing things “right now” without waiting, while the latter just send a request for an animation frame to be rendered before the next repaint (which could mean after a couple ms, so not immediately). The latter therefore allows the system to do other things in the meantime, until it actually renders the changes.

Other than that, I’m not sure what the problem would be - maybe others have better ideas.

I have a keyboard array and the keydown and keyup events populate a boolean in the index of the key code, for example this,KeyboardMap[keyCode] = true; - and this.KeyboardMap[keyCode] = false; for keydown and keyup respectively.
Inside the check_keys function which is called from the frame render loop I have:

if(this.KeyboardMap[65] === true) {  //Key A
this. camera.position.x += 0.2;

This is all that is doing the events are processed separately.
The only thing I can think of is that by rotating the camera is “seeing” the meshes beyond the current walls, as the small area i start in shouldn’t be even using 727 draw calls, let alone near 2000.

I believe you clarified the 700+ draw calls in your other thread, but the main idea here is that it’s not really the number of draw calls that is affecting performance, but how much time do those calls take and how intensive they are for the CPU / GPU - taking time and resources from other operations in the process.

In other words, you can have 100 draw calls and not “feel” a thing, or you can have a single draw call and notice performance dropping. I guess it has to do also with the size of the thing that it is drawn, e.g. a huge geometry will naturally be more expensive to draw than a smaller one. Merging geometries does help whenever possible, but if you merge things into a mega geometry (or have it already) that covers lots of space, it might not be beneficial.

Add to that the fact that there are a bunch of other factors not directly related to Three.js or even the browser that can affect the perceived performance, and you end up with a puzzle that is a bit difficult to solve in a way that you are absolutely sure of things. The rudimentar way of commenting out or disabling things and see the effect might sometimes be more helpful than a ton of “guiding principles” regarding what you should or should not do (that’s why I’m usually amused by the nowadays fashionable “best coding practices” that folks throw out at you when they have nothing else to say, but that’s outside the scope of your topic).

As a side note, in my current project I have 15 draw calls per frame, things work well in terms of FPS and the CPU / GPU usage doesn’t rise significantly (GPU does a bit, however it’s way faster than the CPU at what it does), but I still feel things can be improved, even though I get no FPS drop or anything similar.

@Yin_Cognyto Hi, I understand what you are saying but the meshes are planegeometry, a single 20 * 4 in my test case plane. It isn’t some monstrous geometric monolithic spider web. I can’t merge geometries as I need separate textures on each wall or the ability to, I can perhaps do some merging once that is done if they have the same texture, I have tried disabling the floors and ceilings and then the walls, the walls make the most difference, I tried single side and double side plane, everything remains the same. From my testing I can see that looking at a plane causes 29 draw calls with frustum culling enabled, so something is still drawing when it shouldn’t be, that’s what it seems to me anyway but I am not in any way an expert.
Since reducing the FAR plane of the camera it seems to have improved it, and it still draws everything in one scene, so that tells me it is further proof that it is drawing things “afar”.

In one of the links I posted in the other thread I read that if the geometry extends beyond the viewing “zone” (what the camera can see), its parts that are beyond and “invisible” are still drawn, just because they belong to a geometry that is partially within the screen bounds. That might be the case with a plane seen from close, for example. It doesn’t explain 29 draw calls, of course, though it might explain that only geometries that are entirely outside view get the benefit of frustum culling and the like. Now, I’m not sure that things are precisely like that, but that’s what I’ve read there.

Speaking from a logical point of view, something that might explain more draw calls than expected would be the effects those objects produce in the viewing area, for example shadows, lights, or other similar things, no matter how insignificant they might seem. Other possibilities related to walls having a more significant impact would be that there are more walls (at least 4 in a typical room) and you only have one floor and one ceiling, or that there are more faces and face normals pointing relatively in your direction, or a bigger surface to render.

Trying to implement a part of your project in a different environment - like a jsfiddle or a codepen - could force you to change some coding approaches and add things one at a time, and that might help you discover better where the problem lies (it happened to me as well). If it’s the same thing and effects, at least you’ll know it’s not because of the code and it’s something related to Three.js and such (although I doubt that this is the case for such simple, as per your description, objects and geometries)…

Well the meshes are positioned with map coordinates so one wall might go from X: 120, Z: 50 to X:140, Z: 50 etc, but I would have thought that anything not inside the camera / frustum’s view would just not get rendered, even if offscreen!

There are typically 3 walls the 4th goes to another area where the drawing is continued, so if there is a map with a room, a tunnel and another room it would draw the first room with 3 walls and nothing for the entrance to the tunnel, the tunnel would have 2 walls (outer) and the 2nd room would be the same as the 1st room with 3 walls and a gap for the tunnel, if that makes sense?

I have implemented it in a completely separate project and rewritten it from scratch and it has the same outcome.

Yep, on a first look, you’d expect anything off screen to not be rendered, albeit if you think more about it, it kind of makes sense: you have to close geometries, produce effects object-wide, transform object as a single entity, etc. All these are difficult to do by treating parts of a single object separately.

What you said makes sense too, regarding the walls and trying via a separate project. The only thing that doesn’t make sense - from the available information - is for such a problem to happen. :thinking:

You must be doing something that’s not deemed good practice here. Simply looking at examples such as MultipleElements & MemoryTest you can see multiple scenes, multiple cameras, multiple geometries and multiple materials all being drawn with a constant high frame rate, this is not to mention instancing that can be done to concatenate replicated geometries and materials. Again without seeing a live example of your code setup you’re kind of on your own in terms of learning.

Haha, yes, that last bit doesn’t make sense.

Thanks for you reply, i’ll take a look at the 2 links you put.
I am fairly happy so far with what I have done, I might be able to branch off with the same rendering code but a hardcoded “map” for a look at the code, I know it is hard to “remote debug” I am grateful for all of the “blind” suggestions.

I’ve taken a look at the examples you mentioned, one is just what looks like a single mesh, and the other has 4 meshes, I have said before that if I can’t have different textures on the mesh then I can’t use instancing, my map has nearly 3000 meshes, but they are not all visible at once, whilst things seems to have settled down with some options it is still drawing more than it can see.
Thanks for the links but they are not relevant to what I am doing due to reasons explained above. I’ll see if I can put something together as I am most likely not explaining it correctly.

You don’t need to use the “data” from the game to post something - just replace your “get x,y” system from the data files with a similar process from some position strings that you can copy paste into your example.