Meshparts, beams or particles to replace HUGE QUANTITY of decals?

Hello there, I have a simple question for an effect I seek to achieve.

I would like to have ENORMOUS amounts of bullet holes, liquid spills, ash trails, blood splatters, etc.
But using decals for this would be absolutely HORRENDOUS for performance.

If you would want to have like 3000+ bullets holes, spills and ash from explosions rendered on screen it would rack up draw calls like crazy and produce overdraw as well as the result.

So instead I thought of using alternatives.

Meshparts

I know for a fact that Roblox can instance meshparts if they’re all the same, this easily allows you to have thousands of them visible on screen at once.

Plus, meshparts have collision so I can do basic raycasts and some math to merge things like liquid spills and blood splatters together and improve performance.

The cons

  • When using meshparts I will likely be restricted to only using very basic shapes, using too many triangles for puddles and bullet holes can tax the GPU too much perhaps so liquid spills might have to look a bit sharp and have visible corners.

Beams

Beams might be a viable option as a replacement for decals.
They pretty much are decals, you can even animate them and you don’t have to apply them to the surface of a part.

The cons

  • I have no idea how beams work behind the scenes.
    No idea how much draw calls it requires to draw a whole bunch of them but I suspect since they work differently that they’re more optimal than parts.

  • Potential overdraw if many are overlapping?

  • Not affected by lighting as far as I know or lighting looks very basic / unrealistic.

Particles

Particles have gotten quite some upgrades over time.
If I recall you can even align them to an axis now or disable the billboarding effect so they pretty much behave similar to decals.

Particles are also very efficient as it easily allows you to have tens of thousands of them.

The cons

Particles have a maximum lifetime of 20 seconds, I’d have to spawn a new particle effect every 19 seconds to also reduce the weird flicker that appears when a particle spawns right after one despawns.

I’d also have to do some scripting to I can spawn particles with animations first but then “pause” the animation so the particle can act as a true decal.

What answers I seek

I seek to replace decals and find the most ideal replacement.

I’m fine with using meshparts really, I can model low-poly splatters in Blender.
But it only works for some art styles.

If I wanted more realistic bullet holes, spills, etc I’d have to use something more decal-like that allows the use of textures with transparency.

I want to avoid decals at all costs though because rendering a few thousands on them on screen just won’t do.
They’re terribly optimized for use in large quantities.

With all kindness, correct me if I’m wrong somewhere and if you’re someone with more knowledge and expertise on how Roblox’s graphics engine works then please educate me.

If you know better methods or alternatives I’d gladly hear them.

3 Likes

I’m not entirely sure of the performance hits from doing such a thing, but using floating mesh decals would be the method I’d opt for.

As you mentioned, mesh instancing is great. And having a flat plane of 2 tris is always going to be more performant than having a part (12 tris) with a decal instance creating another 2 tris on top (14 tris in total)

One thing you do have to keep in mind though is that having 3000+ instances is going to have a greater memory hit than the actual meshes themselves, which would have the equivalent of 6000+ tris. Heck, with so little tris you could likely upload your entire map’s worth of decal meshes as a single mesh without going over the 10k tri limit. Same mesh data, least amount of instance overhead, single draw call, but every time you update the map and need to move decals around you’ll have to author another decal layer and upload it. Also, the entire layer would pull from the same decal image.

Another aspect to keep in mind is the images you’re using. While a very large splatter of blood might warrant its own 1k image to maintain texel density, I severely doubt bullets holes smaller than 1 stud² will need such a high resolution. So merge multiple decals into a single decal atlas where possible. Why have 10 different images for 10 different bullet holes when you can just use a single atlas? Edit: Doing so reduces the how much texture data a client has to store. It won’t effect instancing or reduce draw calls so it won’t speed up rendering frame-by-frame, but it will help with memory.

Keeping all this in mind, you might find that the optimal solution would be to have a couple of mesh decal layers across the map, with each mesh layer using its own shader/texture. So a Blood layer that uses a single blood SurfaceAppearance, or a bullet hole layer using the same TextureID atlas. Of course, you then can’t selectively cull an area’s decals or use mesh instancing to reduce draw calls - but that’s alright. You’ve already reduced draw calls to a single call per mesh decal layer. If you have a layer for all the map’s blood, all the map’s bullet holes, all the map’s grime - that’s only 3 draw calls! And if you use a SurfaceAppearance for each layer, you can get some incredible visual results while minimising the cost.

If you want to dynamically place mesh decals at runtime, such as bullet holes from player-fired guns, then you can at least try to minimise draws by using the same template for each bullet hole decal using the same MeshID and TextureID/Shader to make the most of instancing. Lots of these decals will still have a performance hit and they won’t be as optimised as the static decal layers, but they’re still more performant than using parts with decal instances tacked on.

TL;DR: Use floating mesh decals, and use them smart; minimise the number of images you need and keep instancing in mind when working with dynamically placed decals during runtime.

3 Likes

I really appreciate the advice, I might consider this for map building.
Though the reason I would want lots of decals I should’ve clarified.

So basically, in game when characters take damage, toxic waste is spilled or guns are fired, I basically want blood splatters, acid puddles, etc to stay around forever until it reaches a cap or the map unloads.

I don’t want to break immersion and have satisfying and light weight liquid droplet physics and whatnot.

I might plan on coding a light weight mini-liquid/particle physics engine that allows for paint, blood, acid, sludge, mud, etc to stick to objects and drip off walls, ceilings, etc.

I also find despawning ragdolls and whatnot to be very immersion breaking so instead I have them slowly move into the ground and spawn a puddle around them like they’ve “melted” so the game stays immersive.

I sometimes might have puddles and splatters slowly shrink and disappear to clean up excessive material and put less strain on the computer in densely packed areas.

But generally splats and puddles are supposed to be around forever unless a cap is hit after which I might despawn or reuse the oldest or least relevant ones.

1 Like

Gotta bump it because no answer still.

decals are the correct answer… Probably what you want to do is use very small images like 64x64 if possible. or use a sprite sheet, which contains all the sprites used…
plus you probably want some sort of upkeep system that removes overlapping decals.

I appreciate the advice but resolution isn’t the issue here, I seek to replace decals.

Decals are terribly optimized, even if you were to use 8 x 8 pixel decals, it wouldn’t save you from the draw calls.
The biggest issue with decals is that you simply can’t have a lot of them.

Even with an janitor system that removes overlapping decals, if I have say… 1000 of them it will still generate a crap ton of draw calls which is bad for the CPU.

Overdraw is always gonna be a potential issue if using transparency.
But I’m looking into how to reduce the draw calls when having permanent stains.

1 Like

yeah but it seems like thats as fast as roblox is for now… i dont think using surface GUI’s would be quicker. and i dont think mesh parts would be quicker either… all will probs start straining at 1000 instances…

I guess you could make a voxel map like minecraft, and have specific textures for each part, that are changed depending on how much is liquid is spilled on it… and use decal for smaller details like bullet holes

1 Like

Meshparts actually are the fastest solution.

If you read my post I stated that meshparts can be clustered.
You can easily have like 10,000 of them if they’re low-poly.

The issue with meshparts is just that they’re very… blocky and low-poly looking so it would only work for cartoony styles.

I’ve considered beams though since they’re somewhat similar to particles and MAYBE are also rendered the same way which might make them a better alternative to decals IF I’m correct.

But I need help figuring that out.
My PC is way too high end, so ideally I’d need a way to test this and get accurate performance results.

i dont know where you read that decals are the worst possible choice bc for this use i dont see why you couldnt. tbh you could just do a hybrid of meshparts & decals and cherry pick which ones you want for each effect- you wont really matter cuz i doubt youll be doing any :IsA() functions or type indetifiers for small little fx

ive had this same mindset going into making a forest for Autodesk Maya- something that exceeds memory usage that roblox can take by like 300% and im telling you right now even at low poly your vram/memory usage (or just good performance in gen) will increase exponentially. my solution was just using planes for leaves and optimizing the base of trees to be max 80 faces, and then just texture the leaves thru images. Decals might be the way to go.

Experience and a bit of research.
Roblox uses old and outdated methods for rendering decals.

There even exists old leaked source code of how it’s rendered that’s still pretty relevant to this day.

Whenever I was testing places and showcases with friends and other people, we often found out that most lag in experiences was caused by many decals.

It’s difficult to explain, but decals are just rendered in a way that makes them more expensive than particle effects (which also are transparent but they work different).

I’m also a guy who’s interested into graphics programming and the way transparency is often handled just makes decals generally expensive.

Unreal Engine actually has MULTIPLE options for rendering transparent textures, including mask and blending options.

Some are cheaper than others at the cost of possible artifacts.
But i know for a fact that Roblox does not render transparency effectively.

Using low-poly meshparts on the other hand should be fine.

Why?
Because Roblox uses instancing. You can for example easily render many spheres and cylinders, which actually have more polygons than a model I make in Blender, yet because they’re instanced they’re cheaper to render.

Roblox handles 2000+ meshparts (or regular parts) easier than decals which I actually have tested.

1 Like

So after doing a bit of researching myself and thanks to another person in a Discord server I did end up finding a possible candidate for the “many decals” problem.

Presenting ImageHandleAdornments which essentially are just decals/billboard images that can hover in the air or be put anywhere you wish.

  • They do not have to be attached to a part (set adornment to Terrain) but can be if you want them to behave as attachments.

  • They’re very cheap to render as they’re essentially just decals but without lighting and do not require a basepart.

  • They can ALSO be used as an custom particle effect (e.g. particles with collision using raycasting).

  • The lack of lighting is a bit of an downside but can fortunately be calculated pretty cheaply by, for instance, using dot product to calculate how much they’re facing towards the sun / a light source.

  • I tested it and you can have 10,000+ of them, as long as they do not overlap and aren’t all within the camera’s frustum at the same time they should not lag.

    Worst case scenario if they do end up lagging but you still need lots of them you could implement your own LOD or culling system for them.

3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.