-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vulkan Mobile: Decals pop away when there are more than 7 decals on a mesh resource (instead of the expected 8) #70231
Comments
Related to #49639. @elvisish Please upload a minimal reproduction project to make this easier to troubleshoot. |
Try walking (WASD) rotating the camera (mouse) and clicking the mouse to shoot at surfaces (sorry they're misaligned on the walls, haven't had time to fix that). |
|
Still broken on latest beta 10, decals are totally useless for me right now (since they're a purely visual effect, they haven't got any use other than displaying correctly). |
I can confirm this on 4.0.beta b6e0603 (Linux, AMD Radeon RX 6900XT with Mesa RADV). I can't reproduce this after switching to the Forward Plus (clustered) backend, so this is an issue specific to the mobile backend. The presence of a DirectionalLight3D in the scene doesn't affect this issue (the MRP doesn't have any, it's only a preview in the editor). Edit: This is actually (probably) not a bug. Decals start flickering after you place more than 7 of them because the mobile backend is limited to 8 decals per mesh resource. The only thing I find unusual is that decals start to break after you have more than 7 of them, rather than 8 of them. I can reproduce that in a blank project too. In general, for small decals such as bullet holes, I recommend placing a MeshInstance with a PlaneMesh instead. This is faster to render, allows for any shader to be used (including BaseMaterial3D parallax) and has no limitations on the number of "decals" you can render, regardless of your backend (even OpenGL). Rendering errors due to decals flying in the air are unlikely to be noticeable during gameplay given the decals' small size.
|
Is it possible to raise the limit of the decals per mesh resource? I used mobile as it seemed like a good renderer for retro graphics that don't need high overhead but can still use Vulkan. I also used decals as it it's annoying when bullet holes are misaligned on surfaces; still, good to know that PlaneMesh is faster to render as I assumed Decals would have been far mroe optimised for this kind of thing. |
No, it's not technically possible to do so due to how the renderer is architectured. |
Could it be re-architectured so it does work on mobile? I can't imagine any reason why mobile couldn't benefit from decals working as well as Forward+? Also, I think there should probably be a warning if Mobile is used with decals. |
The Forward Mobile backend uses a single-pass approach to light and decal rendering, but without clustering (as clustering is expensive on its own, and not suited to mobile GPUs). To keep performance high and shader compilation times reasonable, it's not possible to support a high number of lights/decals per mesh with a traditional single-pass forward approach. Either way, you should be splitting your level into several meshes in a real world project (so that it can benefit from frustum/occlusion culling). You need to find a balance to avoid having too many draw calls though. Usually, you want each room in the level to be its own MeshInstance3D node. |
Impossible, I'm using TBLoader which imports the map as one giant mesh and since Godot has no built-in way of making level geometry, this is currently the best solution (outside of building in Blender, which has other drawbacks). @codecat might be able to explain why TBLoader worked best loading as one big mesh (I believe there was an early attempt at using multiple meshes that was abandoned). |
This is something that should be addressed within the add-on. Having the entire level be a single mesh is going to cause performance issues in complex levels – you can see this being an issue in the tps-demo. It is possible to procedurally perform mesh splitting, but it's difficult to get right: https://github.com/lawnjelly/godot-splerger |
Qodot (which TBLoader is based on though greatly improved) also loaded as one big mesh, it's a shame decals can't be limited on mobile mode to 8 per surface instead of mesh. |
I feel like it should be possible to make the limitation a per-surface limitation. @BastiaanOlij would know more. But I think the decal list ends up getting assigned to a surface anyway so there shouldn't be any real benefit to storing it per mesh instead of per surface |
@clayjohn I think it already works per surface but I could be wrong. Not sure that would help in this case as there is still a high chance the surface covers a lot of area. I'm with @Calinou on this, this is a flaw in the approach of the level loader. Having your whole level be one big mesh on any sizable level will be a huge issue performance wise as nothing can be culled and all geometry is handled. Also even if we "solve" this limitation, it would mean every fragment drawn for the level mesh would be looping through all decals, so you'd have a huge performance issue. While there are options to do a version of clustering in fragment shaders (one of my old engines works this way) I'm not sure how well that would perform on mobile hardware. |
Cruelty Squad (PC Gamer Game of the Year 2021) was made using Qodot which uses a single mesh per level and had no performance issues, so it does work. |
I suppose it depends on the complexity of the level geometry. You could use TBLoader to load parts of the world as separate meshes by just creating different layers in TrenchBroom (each layer has its own node & |
Not sure if that is a fair comparison in this case, yes it works, it works well, if you keep the lighting within the limits. I'm not even sure if Cruelty Squad uses lighting or if it does it probably just has a single directional light. |
Is performance affected by lights? I thought the limit of lights per mesh was raised even before 4.0, or do you mean if shadows/light maps are used?
Even though gridmaps are highly optimised, culling/portals can't be used on them either so you'd have a similar problem if trying to cull manually; though it probably does some of this for you internally, wouldn't multiple decals per grid map still be an issue? (I'm not sure as I haven't tried yet) |
Lights are expensive to calculate. In the clustered forward renderer we run a pre-process that allows us to see which fragments (pixels) are effected by which lights, so we only do light calculations for lights that actually impact a fragment. So even if you have 1000 lights, if only 2 light this fragment, you're only doing 2 lighting calculations. Even on a big mesh that is lit by many lights, because we're able to do this filtering on a per fragment basis, the lighting calculations are kept to a minimum. But this approach does not work well on mobile so on mobile we use a more traditional way where we determine which lights effect a mesh. This means that for every fragment we have to process every light that effects the entire mesh, even if that fragment is only lit by one or two of those lights. It also means transfering that information to the GPU before rendering each mesh, which is limited without having a performance impact. So it's a double whammy, we're limited to how much information we sent, so that limits the maximum number of lights, and every light we check has an impact on performance, especially on large meshes hit by many lights.
Gridmaps use multimeshes behind the scene. A multimesh is used for each tile. So the same goes here, if a gridmap spans over a large area, it's efficiency starts to suffer as the balance tips from limiting drawcalls, to parsing a lot of geometry that isn't even on screen. |
Godot version
4.0 beta 8
System information
Windows 10
Issue description
Adding some decals to a scene works well, until trying to rotate the camera or move around them.
2022-12-17.23-20-30.mp4
Steps to reproduce
Create a basic decal with a texture and leave everything at default.
Add the decals to the scene.
Rotate the camera and move around.
Minimal reproduction project
min_rep_decals.zip
The text was updated successfully, but these errors were encountered: