godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.04k stars 21.17k forks source link

Sprite3D and AnimatedSprite3D is rendering very slow #20855

Closed i-void closed 3 years ago

i-void commented 6 years ago

I tried so much variations with/without shading with gdScript, nativeScript (Nim) and different import settings without luck. One archer walk animation, with 8 frame costs 14 fps (reduced to 46fps) . It slows to 19-20fps when I exported it to android also. I'm adding screen shots from my computer with GeForce 940MX screen card (I can play Anno 1404 without any lag with this screen card).

I have only one archer on the screen, and I scripted with nim (very fast programming language). I supposed in this example I made the fastest things I can do. If not please share my mistake.

Version: Godot 3.0 System: Linux Manjaro (ArchLinux derive) Frame rate drops too much (14fps for only one node). I expect it to work with 60fps.

Screen shots: animation code import-settings screen1

I have only one scene as Archer and I'm using a sprite image only. Nothing more.

semirix commented 6 years ago

I've experienced this as well. After removing them all and replacing with MeshInstance planes, FPS returned to normal.

usbhell commented 5 years ago

I've noticed this also on 3.1, quite bad fps on 2 android devices I tried (GLES2) with just a couple of sprite3d's. If I use the builtin quadmesh instead to display my texture the fps is perfectly fine.

Toshiwoz commented 5 years ago

Same here, I had to get rid of them, and now I know what to use in replacement. I've taken a bit of my time to make a sample project, that, if you run on pc, it doesn't make a huge difference, but as you export to a mobile you can see the incredible difference. On my MYA-L11 I can run at 50+fps more than a hundred plane meshes (that is not that much, but in comparison), while it can't stay above 10fps with barely 10 Sprite3D. Sprite3D_Mobile_Test.zip

I think this is indeed a quite old issue: https://github.com/godotengine/godot/issues/2096 And afaik also ImmediateGeometry displays similar, hum... symptoms.

I'm not sure, but, if the class has the _draw method, that means it overrides it right? Might be there the problem? As I can't debug (and I know very little about C++) I can't tell for sure, but can it be that it's doing too many things at every frame? Like checking properties, calculating frame offset, and more: https://github.com/godotengine/godot/blob/24e1039eb6fe32115e8d1a62a84965e9be19a2ed/scene/3d/sprite_3d.cpp#L397-L526

Calinou commented 5 years ago

ImmediateGeometry isn't intended to manage large amounts of geometry, so it should probably be replaced to use some other kind of mesh generation (like ArrayMesh?).

Toshiwoz commented 5 years ago

ImmediateGeometry isn't intended to manage large amounts of geometry, so it should probably be replaced to use some other kind of mesh generation (like ArrayMesh?).

Yeah I am referring to a few lines drawn (I was reusing part of the navmesh code for my game, and let the path as it was, found out it was slowing down a lot on mobile). But, never mind, I'll open a new issue or add to existing ones as I have time to make another test/benchmark project.

BenMcLean commented 4 years ago

I am also getting hit by this / #31023 in my WOLF3D project. As a workaround, I am looking into replacing all my Sprite3Ds with MeshInstances of a QuadMesh. Sure would be nice if Sprite3D was actually fixed though

sp00mm commented 4 years ago

I'm also having this issue. They almost should put a disclaimer on the sprit3d node. Now I'm going through ~20+ nodes and changing them to meshes. It would be REALLY nice to have a feature like the 2d sprite where you can convert it to a mesh2D with just a click.

semirix commented 4 years ago

Does Sprite3D need a refactor? Surely an object that simple should not be so slow to render.

clayjohn commented 4 years ago

@semirix it should probably just be removed and made into a thin shell for a billboarded quad.

Calinou commented 4 years ago

@clayjohn What about AnimatedSprite3D? It's surely possible to emulate its functionality using a MeshInstance + QuadMesh, but it sounds tedious to set up.

Seel commented 4 years ago

Yeah... as someone working on a mixed 2D and 3D game I really want that sprite functionality.

fossegutten commented 4 years ago

I can only draw about 100 Sprite3D before i drop below 100fps, but i can draw almost 1000 QuadMesh.

t-mw commented 4 years ago

For anyone trying to work around this by using an AtlasTexture on a MeshInstance material, here's a shader and script that might help: https://gist.github.com/t-mw/0b78167372ed97e7c78e3f3844f3ae75.

tommiemartin commented 4 years ago

I started looking at this as well but my knowledge of rendering isn't to the point where I can be much help. Is this currently using immediate geometry to create quads on which the frames are drawn? Seems like the goal would be to put a SpriteFrames resource in 3d space which looks like would somehow need to inherit from a visual instance.

Seems like ios (ipad mini 2) handles lighting, normal maps and sprite3d objects much better in its pipeline where as even a couple sprite3d objects on galaxy s7 causes huge fps drops.

I feel this is pretty huge even for 2d games where you see games like hollow knight leveraging 3d for parallax effects. Also anything mixed mode like using meshes instead of sprites for character skins / items.

Another workaround I've used is to create an animated texture resource in a spreadsheet for parsing and import it into the engine. It has a max of 256 frames and very limited control but works for basic playback.

Really hoping this gets cherry picked for the 4.0 release.

Calinou commented 4 years ago

Is this currently using immediate geometry to create quads on which the frames are drawn? Seems like the goal would be to put a SpriteFrames resource in 3d space which looks like would somehow need to inherit from a visual instance.

Yes. We should probably use ArrayMesh instead of relying on ImmediateGeometry. I don't know how difficult it would be; maybe it's actually really easy. I don't know if anyone actually attempted to rework it to use ArrayMesh :slightly_smiling_face:

Seems like ios (ipad mini 2) handles lighting, normal maps and sprite3d objects much better in its pipeline where as even a couple sprite3d objects on galaxy s7 causes huge fps drops.

iOS devices have better performance and better GLES3 support across the board, so that makes sense.

I feel this is pretty huge even for 2d games where you see games like hollow knight leveraging 3d for parallax effects.

Godot supports pseudo "3D in 2D" since 3.2, without having to rely on the 3D engine for this.

Really hoping this gets cherry picked for the 4.0 release.

It's the other way around :wink: Pull requests in the master branch get cherry-picked to the 3.2 branch if they're backwards-compatible.

clayjohn commented 4 years ago

I'm going to just replace the backend of the Sprite3D with a proper mesh instead of using ImmediateGeometry.

clayjohn commented 4 years ago

PR is up now! Please test it if you are having performance issues with Sprite3D!

39867

akien-mga commented 4 years ago

Fixed by #39867 in the 3.2 branch.

It's not fixed in master yet though, so keeping this issue open. A different fix will be used there.

berarma commented 3 years ago

This has already been fixed, hasn't it? Can we close it?

akien-mga commented 3 years ago

See my comment above yours: https://github.com/godotengine/godot/issues/20855#issuecomment-654278054

berarma commented 3 years ago

See my comment above yours: #20855 (comment)

Sorry, I thought it was a hanging comment. I didn't realize master is 4.0.

Calinou commented 3 years ago

This was resolved for master by https://github.com/godotengine/godot/pull/50014, closing.

To confirm this, I benchmarked 3.x against master to compare the current rendering performance of 900 Sprite3Ds in a blank scene (no lights, fallback environment).

Benchmark

OS: Fedora 34 CPU: Intel Core i7-6700K GPU: GeForce GTX 1080 Resolution: 2560×1440 Godot versions: 3.x a05aefb74, master fe6c65a1a

Testing projects:

master - Vulkan Clustered

Project FPS: 1198 (0.8 mspf)
Project FPS: 1195 (0.8 mspf)
Project FPS: 1198 (0.8 mspf)
Project FPS: 1198 (0.8 mspf)
Project FPS: 1199 (0.8 mspf)

master - Vulkan Mobile

Runs faster than Vulkan Clustered thanks to its lower base cost. However, its performance will fall behind compared to Vulkan Clustered in a more complex scene with many lights.

Project FPS: 1380 (0.7 mspf)
Project FPS: 1376 (0.7 mspf)
Project FPS: 1380 (0.7 mspf)
Project FPS: 1379 (0.7 mspf)
Project FPS: 1349 (0.7 mspf)

3.x - GLES3

Project FPS: 1691 (0.5 mspf)
Project FPS: 1704 (0.5 mspf)
Project FPS: 1667 (0.5 mspf)
Project FPS: 1690 (0.5 mspf)
Project FPS: 1689 (0.5 mspf)

3.x - GLES2

Despite the GLES2 renderer's lowest base cost (out of all the renderers tested here), this is by far the slowest result.

Project FPS: 546 (1.8 mspf)
Project FPS: 548 (1.8 mspf)
Project FPS: 550 (1.8 mspf)
Project FPS: 548 (1.8 mspf)
Project FPS: 550 (1.8 mspf)