-
Notifications
You must be signed in to change notification settings - Fork 6
nanite at home #83
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
base: main
Are you sure you want to change the base?
nanite at home #83
Conversation
@schell mind if you review this one too, even if it still needs some stuff done? I'd love to get it out the door tomorrow evening, latest monday midday (EU) so it's out there before rustweek (starting Mondey / Tuesday). (and sorry for being a little late with that...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd ask yourself what are you trying to accomplish? The post and content is kinda all over the place. Are you talking about your thesis or Nanite in general? Are you wanting to focus on what is new and novel or have a broader foucs? Is it a narrative / impl journey you go on with the reader or is it a retrospective about a project?
If I were writing it (knowing nothing about this space) I'd probably do something like:
Post 1: Nanite
- Intro (For my thesis wrote nanite implementation. There are many, but I used rust-gpu and X novel techniques)
- Overview of Nanite as background (either go in depth or just a paragraph and link out to someone else's explanation)
- Overview of Rust GPU and high-level benefits it had as background, allude to future posts
- Novel Nanite techniques and details
- Outcomes
Post 2: Bindless in Rust GPU
- Intro (refer to Nanite post as background)
- Bindless background
- walk through impl, highlighting clever or novel bits
Post 3: GPU-driven renderer in Rust GPU
- intro (refer back to 2 posts)
- background on what GPU-driven rendering is
- walk through impl, highlighting clever or novel bits
To me, the "hook" is the novel stuff with rust-gpu: bindless, gpu-driven renderer, etc. So I would think about dropping the first post entirely. Again, there are other nanite impls, even in rust and you are not trying to drive adoption, so I would focus on what no one else has done before. Or at least make the non-novel stuff strongly feed into the novel stuff.
It might help to try my process for writing these days:
- Come up with a tight outline.
- Iterate with and without AI to polish the outline. (I ask questions like "does this logically flow?")
- Have AI write the first rough draft using the outline in the writing style I choose (I often say "in the style of the rust book" and things like "no comma splices", "do not use flowery language", "do not use overly formal or informal language", "do not use too much jargon", etc).
- Refine the rough draft myself.
It seems to produce pretty solid and coherent work quickly.
@@ -0,0 +1,172 @@ | |||
--- | |||
title: "Nanite at Home" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd maybe make this something like "Nanite on Vulkan with Rust GPU" and use the nanite at home meme in the content (for SEO).
* split into multiple posts | ||
* this one about Nanite | ||
* next one about rust-gpu | ||
* why read this? unique perspective: Terrain gen really similar to nanite |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intro will be important to set the stage. There are multiple implementations of Nanite, including one in rust for bevy I saw fly by (https://jms55.github.io/posts/2024-06-09-virtual-geometry-bevy-0-14/). The novel bit IMHO is doing it with rust-gpu
.
## Triangles, Vertices, Meshes and Level of Detail | ||
|
||
:::tip | ||
Feel free to skip this chapter if you already know all these concepts, but I suspect there will be plenty of rust programmers unfamiliar with computer graphics. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You say this is for "rust programmers unfamiliar with computer graphics" but it uses a lot of graphics jargon (poly, mesh, shader, fragment, etc)
|
||
TODO pic of some low poly 3D model | ||
|
||
You've probably all seen a 3D mesh made up of many triangles, but how do we actually represent them? The triangles themselves are quite simple, it's just a List of u16 or u32 indices where a set of 3 describe the corner IDs to connect to create a triangle. Far more interesting are these corners, we call them vertices, as they often cary not just the position they are located at, but you can attach various other attributes to them. For example, normals can describe the "up" direction of a surface, which is important in lighting calculations. Or texture coordinates to describe how 2D images should be wrapped around our 3D mesh, think of the wrapper around chocolate Easter bunnies. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of the "you've" bit. It reads better to me with something like "A 3D mesh made up of many triangles, but how do we actually represent them?" I'd also swap mesh for model to reduce jargon or define mesh.
|
||
You've probably all seen a 3D mesh made up of many triangles, but how do we actually represent them? The triangles themselves are quite simple, it's just a List of u16 or u32 indices where a set of 3 describe the corner IDs to connect to create a triangle. Far more interesting are these corners, we call them vertices, as they often cary not just the position they are located at, but you can attach various other attributes to them. For example, normals can describe the "up" direction of a surface, which is important in lighting calculations. Or texture coordinates to describe how 2D images should be wrapped around our 3D mesh, think of the wrapper around chocolate Easter bunnies. | ||
|
||
As we're writing a renderer, we don't just want to store models, we want to render them to the screen and look at it from different directions! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You didn't introduce that we were writing a renderer, but I guess that would be in the intro? I think also the way this is written it is unclear that it is already done...you'll want to decide what the tone is (walking through the journey or taking the finished impl and talking about why it is the way it is)
|
||
To understand why we split it up into multiple clusters at the end, we need to look at what happens in the next iteration. To start the next iteration, we have to process all groups and collect all the newly generated clusters into a new mesh, like you can see on the right. Then we proceed with the first step again and select groups of 4 clusters. However, there's one detail I've left out earlier: We don't just select *any* group of 4 clusters, we want to select these groups so that there are as few outer edges as possible. Doing so will encourage the grouping algorithm to place the outer edges though longer and more simplified edges, like the edge we created earlier by splitting. Imagine the red lines as the locked borders of the new iteration, and notice how we shifted the locked borders of the previous iteration into the center of the new groups. And my the formerly locked edges being in the center of a group, they can be simplified. | ||
|
||
I like to think about it like swapping the areas around constantly: One iteration, one area is a locked border where the other is being simplified. And the next iteration they swap, and the other is the locked border whereas the one is being simplified. But instead of two discrete locations swapping, there are lots of borders throughout the mesh constantly swapping between being locked and being simplified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be reworded for clarity, it is hard to follow.
|
||
But these values are not precomputed constants, after all, moving the camera should change the LOD of objects. Instead, the values come from a function, and we must ensure that for all possible camera positions, the function yields monotonic values throughout the DAG. This depends on the exact function you are using, but generally, this means that your bounding spheres around your clusters must contain all the bounding spheres of your children. Which is a quite simple condition to uphold in practice, though computing the optimal bounding sphere around spheres is a bit complicated, but simpler approximations work just fine. | ||
|
||
## Evaluation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, this section doesn't really make sense in the flow of the other sections. We are kinda talking in general and then it's like BAM, we are actually talking about a specific implementation and your thesis.
It also feels like the whole section is making excuses rather than pointing out it is an academic project not a production implementation.
|
||
I don't think that implementing Nanite is worth it from a pure performance standpoint, except maybe for AAA studios who have the resources to build it and get it to a good enough quality. But if you want pure performance, you should first focus on getting all the basics out of the way. Like I haven't implemented any form of frustum culling, no two-pass occlusion culling, still use a G-Buffer instead of a [Visibility buffer](http://filmicworlds.com/blog/visibility-buffer-rendering-with-material-graphs/) cause it was faster to implement, could likely benefit from batching my draws and should compress my vertex attributes better. All of these will likely have better performance yields for the time invested than implementing Nanite. | ||
|
||
I could see Nanite as a tool for artists though, removing their need to manually create LODs and save money in production. However, I can't reasonably give you any recommendations, I'm not an artist myself nor do I know how much time is spent on creating LODs. But there seems to be an active need in that area, since there's multiple companies selling software just for mesh preprocessing and simplification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can't speak to it, I'd leave it out.
|
||
Closing it out, if you're curious and would like more detail on how nanite works, feel free to download my master thesis and have a read! And yes, that means I'm a recent graduate (with some work experience as well) looking for a Job, so feel free to contact me on [my github](https://github.com/Firestar99). I also want to give a huge shoutout to [jglrxavpok](https://jglrxavpok.github.io/) and [jms55](https://jms55.github.io/posts/) who have built their own Nanite engines and documented some of their work, which has helped me a lot! And [zeux](https://github.com/zeux) for the amazing [meshoptimizer](https://github.com/zeux/meshoptimizer/) library and their own [Nanite experiments](https://github.com/zeux/meshoptimizer/blob/master/demo/nanite.cpp) to reference! | ||
|
||
Maybe I'll even make another article soon, introducing my bindless system for rust-gpu, designed similarly to [Daxa](https://github.com/Ipotrick/Daxa), and how to make a gpu-driven renderer with it. But first, I'd like to see [cargo gpu](https://github.com/Rust-GPU/cargo-gpu/) getting production ready, to give a small teaser into upcoming rust-gpu tooling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these should be alluded to in the intro and these are the real novel bits I'd focus on.
## Nanite | ||
|
||
As we move from Terrain rendering to Nanite operating on general meshes, we have to replace our Chunks with a different concept: Clusters or Meshlets. | ||
While nowadays both are used interchangeably, the original nanite presentation only used the term clusters. Clusters have long been used to describe a small subset of a mesh, usually limited by the amount of triangles it contains. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While nowadays both are used interchangeably, the original nanite presentation only used the term clusters. Clusters have long been used to describe a small subset of a mesh, usually limited by the amount of triangles it contains. | |
While nowadays both are used interchangeably, the original Nanite presentation only used the term clusters. Clusters have long been used to describe a small subset of a mesh, usually limited by the amount of triangles it contains. |
Link to the presentation too.
TODO: