How to render large amount (millions) meshes with decent FPS and Memory ?

Hey guys,

We are trying to develop a cross platform application that should render objects created at runtime dynamically.
Case 1: 1 Million Unique geometries (meshes).
Case 2: 300 Million Triangles in a single mesh.

Both these cases results in worst FPS and Memory when rendered using MeshRenderer and Graphic.DrawMesh with API.

Graphic.DrawMeshInstanced, Graphic.DrawMeshInstancedIndirect and other instancing API will not work in our case as we have unique geometries.

Even though above instancing APIs doesn’t fulfill our requirements we tried those out of curiosity. Graphic.DrawMeshInstanced produced below par FPS. Graphic.DrawMeshInstancedIndirect doesn’t support in WebGL.

What is maximum triangles and meshes count that can be rendered with target FPS as 30 ?

Any other suggestion which can fulfill the above requirement ?

It does not work like that. You can drop fps to single digits with one triangle if you use the right shader.

In this scenario you’re likely aiming too high.

I can’t find the most recent data on number of meshes per second the most recent GPS can process, but there’s a suggestion RTX 3XXX can go up to 20 billion triangles per second. With your 300 million triangles that SHOULD produce 60 fps, but in practice it won’t, because for that you’d need to render the mesh only once, and in the scene the mesh will be rendered several times. For example, in forward rendering mode it may be rendered extra time for additional lights, it WILL be again for each shadowcaster and so on.

When the lighting is involved, you’re increasing number of triangles effectively being drawn.

So in your scenario you’ll need to start cutting corners. First see if you can even render it with unlit shader, no lights and shadows disabled.

If you can’t, that’s it - end of the line.

Most likely you’d need to introduce impostors in scenario #1 and try to split mesh #2 and calculate occlusion data for it.

Also you’d need to spend time in frame debugger to see what is eating your framerate the most.

2 Likes

You need to trick the player that he sees a high detailed world but in reality he does only see a small part of it. LODs, impostors, streaming etc. Also the upcoming nano tech asset will probably help

Unreal Engine 5.

7 Likes

I know this is a Unity forum, but if you might also want to research Unreal engine 5’s nanite feature. Apparently it’s a software system that automatically bakes multiple optimizations for large. densely-triangled environements. I don’t know if they need to be static meshes or not.

I would test the performance of case 2 (a 300 million triangles mesh) with a non dinamically generated mesh and if that is good make it procedural, if not lower the requirements.

You mean the “wrong” shader, right? :smile:

Anyway, I was going to say that 1 million unique (!) meshes is a terrifying amount! Consider investing in a server farm that handles the rendering. :wink:

Seriously, it would help to know where these (insane) requirements come from and what these meshes are, what they represent, what the goal of the app is. Maybe you are rather looking for a break-through idea that makes the whole thing a lot easier rather than the brute-force everything is a mesh approach.

For example, point cloud rendering is one way to achieve highly detailed photo-realistic real world scans in realtime 3D but at the cost of extremely high memory usage and some visual oddities. Voxelization is another alternative, but with similar drawbacks. Or maybe you simply don’t need every mesh to be unique. Maybe it could be done with textures or shaders instead?

Dear Aravind_B_SST, Just a 2 cents.

In this forum thread, the creator is making a Nanite equivalent for Unity; it answers most your questions. Albeit, Invertex, explained, after I asked (having heard Nanite is space disk dependent), the reasoing, that it can increase the size of your game drastically (depending if organic or hard surfaces), an UE5 dev had said that it was 10x times bigger with Nanite on. Invertex said it is 1.5x-100x bigger; so that dev said a 10GB Nanite-using game would be 100GB roughly. I don’t think hard drive space is such a problem today; with 10-15TB drives available (but still not SSDs/NVMes…fast ones…) but old SATA mechanical/platters drives…space is there if you get a old tech SATA drive. Soon, SSDs/NVMes will also be several TBs; so in that sense, the problem is moot (gamers lacking hard drive space to install many ‘huge’ games requiring 150-300GB…or more even; like COD requiring such; of course, it often means extreme high quality assets and oftenly little or no compression/less optimization per asset, and hundreds of thousands of these assets); What I’m saying is that…if your game is not huge, Nano tech is a great tool to have (as it does what Nanite does, but in Unity) and will save you a ton of time (of not having to do these optimizations to make your game playable (in fps) on lower hardware too).

If your game is huge…then it’s more problematic; because, you will Eat hard drive space, if using Nano tech. You will have to Design your game to use more ‘organic’ shapes that cost little in Nanite space (instead of hard surface that are costly and wasteful for Nanite space disk demand). More so, than if you Don’t use any Nanite/Nano tech…you could optimize your assets and it would take Less space than if converting your assets to be Nano-tech ready (because from what I understood it is not an ON/OFF switch/script (that applies this effect on everything realtime)…
you must ‘preconvert’ the 3d models-- to Nano-tech format–to have Nanotech scriot read the assets/work.
So that is extra-work.

It’s the same as using Impostors (as others said)/and/or LODs…(check also that your impostors have shadows…this is crucial I found many impostors…with no shadow possibiliy, and especiall, Self-shadowing, very important. or else your objects impostereed…receive’ no shadows on theirselves)

One thing I do recommend the Nanotech or the Impostors…over LODs, is in ‘the distance’…it is Visible in the distance that some models reduce in detail (using LODs) and it shows; quite clearly. I mean, the model is far in the distance, so is small (in terms of % size on the total rendererd image), but, it still shows in some models;

It means, that you can’t Reduce polygon count - Too Quickly…or it shows. Like, the model becomes blocky, with distance; but if too quick; it’s not quite visible. So, the best is to a gradual reduction of polys with distance; so it’s not evident. Like I was watching a scenery with very low poly LODs in the mid-to-far distance…and it looked Very Low Res…like PS2 graphics…not kidding. So, if you reduce the poly count too quickly - graphic LOD ‘distance’ - will make a game look much more ‘last gen’; because you don’T see far in the distance/and/or the models in the distance are too low res/chunky.

This is where the Impostors shine; but it’s a long tedious thing but done with/in combinatino with LODs, it’s the best; and you combine that with (as you said) GPU instancing; or use ‘mesh combining’ (but careful with this; mesh combining a ton of models…to make 1 Big model…is great…except it can explodwe memory demand; like that’s what I read from devs who said they combined 100,000 thousand little models…to 1 model…and it was just way too much memory demand - GBs RAM…that single model (comprosing all the models - combined as 1) ate the memory);
So you have some tools, that do ‘regional combining/local combining/sector combining/cell combining’; where like, objects are combined…but ‘in cells/chunks’…in a 3d grid…so it’s not 100% 1 mesh, it’s rather, let’s say 5 parts…and these 5 parts (represent the 100,000 objectS, combined as 5).

Impostors are not 100% solution…like, at close-up, it shows; you need at least 4K res for ‘close-up’ of Impostors…or they look ‘Flat cards’ (like old 2.5D build games…Duke Nukem 3d…etc…) facing the camera no matter its angle…
2d billboards.

At 8K, now they are quite sharp/detailed and quasi the same as regular 3d model; but rendering 8K impostors…is long.
You must do this (once, only) and then it’s done. but this will take substantial hard drive space (these 8K texute impostors are not small; you must optimize them; like using ‘crunch/compression’ on the image itself; using like DX5 or BC7 compression, tha reduces their space disk size); but, still, as said, it is not as good as The 3d model itself; but, in the distance, it is better; because it is the Exact same detail of the model Close - or - Far from the camera;
while LODs always reduce poly count; and thus, make chunky low res models in the distance.

My take; a combination of these techs is best. And it depends of your needs/what you wish;
do you Need to ‘preserve model detail’ – in the distance…or you don’T care…and low res in the distance doesn’t matter -it’s far…so who cares…

(in my case, I care; becaeuse I noticed it and AAA games rarely have this Low res in the distance look; like the models do you use LODs but it’s not Drastic reduction neither).

As other said; you have no choice but to show only ‘a parcel’ of the world at any time; but only showing a little chunk; you reduce resources; so ‘hide/unhide’; use occlusion (GPU occlusing…CPU occlusion is not cheap); frustum culling… etc…tricks that ‘hide’ everything friom view; but, also, can Remove from memory so not just hide; but Deactivate;
like, removing the asset from memory and then Reloading it - upon seen. So this way you reduce memory need (because ‘hiding’ the objecty…does not remove it from memory…only hides it…you have to ‘unload asset’ but then you have to ‘reload asset’ so that it’s back in memory…depending- if in view/needed or not).

1 million objects…will liklely need serious optimizations (if not using the DOTS/ECS techs…); like mesh combining; lods, texture compression; occlusion; culling; unload/load - depending distance/view; hide/unhide; make only a small periphery…of any active/in view assets…

I wish to add; AAA games, I noticed, have Far view; like you can oftenly see in the distance they use tricks like ‘fog’ in the distance and ‘camera cutting end’; like after a certain distance, objects disappear there is nothing else; ‘camera distance clipping’;

And, oftenly, I noticed; in smaller games; that ‘cut-off’ is wayy too close (along with low poly models in distance); and this can feel claustrophobic or is a sign the game is not AAA; because AAA game ‘push the distance’ you can see far;; and that means using LODs/impostor for that to preserve the models in teh far distance; look at a game like assassin’s creed origins or red dead redemption 2; they have a very far LOD distance and the game runs well despite so; ‘seeing far’ is a sign of AAA game; even Escape from Tarkov (a Unity game) has very far LOD distance and you can see ‘miles’ in the distance. That’s not ‘free’ in resources, it’s very taxing to have this far objects be seen clearly in the distance.

Hence, the trick is ‘fog’ to ‘hide it in the distance’ and thus make a much ‘closer’ ‘camera clipping/end’. But, as said, games that do that, are either going for claustrophobic look or are doing it on purpose (can’t ‘view too far’ in the distance → too demanding in hardware resources/the engine can’t). The other trick is to make, as said, a more claustrophobic-design game…mostly 'hallways/corridor (‘corridor-shooter’); where there is No ‘outdoors/wide space’…
it’s all happening inside/in hallways…etc…you don’T need to see far…walls block the view.

Just 2 cents.

PS: There is more good to using Nanotech, than not. Your gamers will need hard drive space, buy New hard drive that has many TBs (SATA)…and if they buy ultra-fast NVMe/SSDs…well your game will fit in it…and that’S about it (you will eat the space on it; since it’s oftenly only 1-2TB); they will have to play 'install/uninstall/install/uninstall…as they will have to ‘pick&choose’ between which big games to install).

PPS: One more thing, it was said, Nanotech/Nanite is still hard for non-static stuff (like great for buildings/non moving stuff…but still not great for vegetation or any moving thing); like this ‘virtual texturing/virtual model’ tech is still too slow; and in that sense, it forces needing a NVMe/SSD…like you need it because it is ‘model streaming’ tech…and as such you drive must have very fast reading (like a NVMe…not an old SATA). This will cause ‘momentary catch-up/low-res textures’ as the scene displays and ‘updates itself/textures are read…and become hi-res…as they are read’…just like virtual texturing does; it catches up --as it reads/the stream (of the textures) on the disk. But, the Great thing about that is Memory cost (RAM); is it Much low RAM cost…using virtual texturing than using regular texture - put on GPU VRAM memory; still, if you compress/using compressing/crunching tech like BC7 or DX5 texture format…plus lossy ‘cruching’…you save a lot of VRAM space need (and stick to 4K res…instead of 8K textures). But, it still, not as good as using virtual texturing tech; or, for 3d models…using Nanotech. That’s what Invertex explained, you are trading memory space…for disk space. So, that’s the big caveat, it’s disk space and speed of reading; for Nanotech.

PPPS: Others mentioned shadow casters, very important, shadow casters/pixel lighting can tank frame rate, and
also shader complexity; use Defered mode, better for that (more pixel lights possible); check shadow caster count;
check Batch count and Draw call count; these will increase very rapidly and overwhelm the engine; still…there’s no magic button to make them lower; several AAA games - have 50,000 drawcalls…and they work/they made it work somehow. (problably using ECS/DOTS tech etc…). Plus, use DSS, ‘image resolution scaling/dynamic scaling’…like reduce complexity of everything depending the hardware and/or redude the Rendered Resolution.

2 Likes

That’s only if their geometry can even be processed by nanite. The whole thing smells like something weird or a special use case, like polygonizing a CT scan or displaying some sort of external data.

Because a videogame normally would not need this kind of numbers.

What’s your target hardware? Is the geometry being generated procedurally or is it being imported at runtime? Do you actually need that high poly density? If you’re trying to push 300,000,000 polygons to render, that’s the equivalent of rendering a polygon for every pixel of a 1080p display nearly 150 times over.

You’re not giving nearly enough information here.

Running this GitHub - joeante/Unity.GPUAnimation: Simple but very fast GPU vertex shader based animation system for Unity.Entities on a 1070 laptop I was about to do 10k dragons with 120mil vertices at 30fps

But building a game with it is a whole other deal.

The OP’s issue is that he wants unique geometry for those triangles. 10k dragons would use instancing and will be cheaper to render.

2 Likes

Exactly, it sounds like visualizing some infrastructure project with raw data coming from CAD engineers. There it’s no surprise to go above 100M triangles per model.

8660619--1166172--upload_2022-12-14_11-4-21.png

I took from a presentation of the company that developed their “rendering codec” and all toolset on the top of Unreal to handle such datasets. They’re presenting a visualization of ITER reactor construction.

And it seems like a reasonable solution. Even with Nanite, as engine rendering can handle huge meshes, tooling might not be prepared for such an insane triangle count. Just importing a few million triangle meshes to the engine can take a lot of time.

(Ignore stupid presentation name, it actually has nothing to do with metaverse blablabla, pure engineering talk)

https://www.youtube.com/watch?v=Iag2lJj82m4

nanite/nano tech clusters meshes. I wonder if it wouldn’t be able to swallow the biggest of CAD files actually.

I have my home in SketchUp with alot of detail, when nano tech arrives I will try to se how well it runs :slight_smile:

Hi Everyone,

Thanks for all the replies.

I am a rookie in Unity, apologies for incomplete data in the OP and I will try to provide a detailed explanation on the requirement why we are doing this.

We are not building a game here but trying to build POC using unity that renders CAD 2D data.
Mostly these data are lines but a lot of them will come based on the size of building.

A very very small region of floor plan example that needs to be rendered is attached below as screenshot.

As the data source is from external application we have no control on the maximum meshes or lines that needs to be rendered. We are not expecting to render whatever input that is thrown at the application (certainly the amount of triangles/Lines rendered will be dependent on how good the hardware is) but at least we need to know the correct way/approach to render this in Unity.

Initially we tried out rendering these data using LineRenderer and MeshRenderer (with topology as lines) but we faced a lot of Memory overhead due to Game Objects with Renderer component.

Test Results: GPU - AMD Radeon R7 450 4GB
Case 1:
No of Triangle: 100,000
MeshRenderer Used: 1
FPS: 1
Case 2:
No of Triangle: 50,000
MeshRenderer Used: 1
FPS: 2
Case 3:
No of Triangle: 50,000
MeshRenderer Used: 5
FPS: 15

Then to simplify things we just rendered a chunk of Line Geometry (100K Lines, Mesh Topology) inside a single Unity.Mesh with Graphics.DrawMesh API our memory issues were solved but we still faced issues with FPS.

We got better results in Graphic.DrawMeshInstancedIndirect but unfortunately the data that we get doesn’t allow instantiation to work as it is unique Geometries. We understand 300 Million is too much for any GPU based on your feedback and its not realistic to render 300 Million Lines we agree that. But we are only looking for the best approach that can render the maximum amount of unique lines.

could try gl lines too:

do you need to be able to select those lines or parts of them? (or its just for viewing)

yes we need to select them and also hide them as well

If you need CAD, its PIXYZ you need to use unity even moderately well. Otherwise look at Unreal 5. (and yes PIXYZ is an extra and expensive cost)

1 Like

You’re doing something strange here. With only 100k triangles, unity should run circles around it.

Profile the application, see what is happening. Line renderer is not really good for drawing lines (it is meant to be for drawing WIDE lines), plus there’s a chanc that it is updating every frame. For wireframe rendering you’d need to be using line primitives, really.

https://docs.unity3d.com/Manual/Profiler.html

You’ll also want to segment your line data, most likely - for faster performance. This isn’t hard and can be done with a script.

Unity has CAD solutions if yer willing to pay for Pro and a few add-ons from the engineering bundle.