Part 4 of https://geofflester.wordpress.com/2016/02/07/factory-pt-1/
Alpha card objects
In most games, you have some objects that have on/off alpha transparency, generally for objects that you wouldn’t model all the detail for (leaves, flowers, etc).
^ Exactly like that, beautiful isn’t it?
Years of art training not wasted at all…
Also referred to as punch-through / 1-bit / masked materials, btw.
So, you can see that the see-through portion of that polygon is pretty large.
When rendering these types of assets, you are still paying some of the cost for rendering all of those invisible pixels. If you are rendering a lot of these on screen, and they are all overlapping, that can lead to a lot of overdraw, so it’s fairly common to cut around the shape to reduce this, something like this:
What does this have to do with the factory?
Aren’t you supposed to be building a factory?
I get distracted easily…
I’m not really planning to have a lot of unique vegetation in my factory scene, but I am planning on generating a bunch of stuff out of Houdini.
When I create LODs, that will be in Houdini too, and the LODs will probably be alpha cards, or a combination of meshes and alpha cards.
When I get around to doing that, I probably don’t want to cut around the alpha manually, because… Well, because that sounds like a lot of work, and automating it sounds like a fun task 🙂
Houdini mesh cutting tool
The basic idea is to get my image plane, use voronoi fracture to split up the plane, delete any polygons that are completely see-through, export to UE4, dance a happy dance, etc.
For the sake of experiment, I want to try a bunch of different levels of accuracy with the cutting, so I can find a good balance between vertex count, and overdraw cost.
Here’s the results of running the tool with various levels of cutting:
Here’s what the network looks like, conveniently just low resolution enough so as to be totally no use… (Don’t worry, I’ll break it down :))
The first part is the voronoi fracture part:
I’m subdividing the input mesh (so that I end up with roughly a polygon per pixel), then use an Attribute VOP to copy the alpha values from the texture onto the mesh, then blur it a bunch:
I scatter points on that, using the alpha for density, then I join it with another scatter that is just even across the plane. This makes sure that there are enough cuts outside the shape, and I don’t get weird pointy polygons on the outside of the shape.
Here is an example where I’ve deliberately set the even spread points quite low, so you can see the difference in polygon density around the edges of the shape vs inside the shape:
Counting up the alpha
So, earlier, I mentioned that I subdivided up the input mesh and copied the alpha onto it?
I’ll call this the pixelated alpha mesh, and here’s what that looks like:
Next, I created a sub network that takes the pixelated alpha mesh, pushes it out along its normals (which in this case, is just up), ray casts it back to the voronoi mesh, and then counts up how many “hits” there are on each voronoi polygon.
Then we can just delete any polygon that has any “hits”.
Here is that network:
After the ray sop, each point in the pixelated alpha mesh has a “hitprim”, which will be set to the primitive id that it hit in the voronoi mesh.
I’m using an Attribute SOP to write into a integer array detail attribute on the voronoi mesh for each “hitprim” on the pixelated alpha mesh points, and here’s that code:
int success = 0; int primId = pointattrib(0, "hitprim", @ptnum, success); int primhits[] = detail(0, "primhits"); if (primId >= 0) { setcomp(primhits, 1, primId); setdetailattrib(0, "primhits", primhits, "add"); }
After all that stuff, I dump a “remesh” node, which cheapens up the mesh a lot.
And back to UE4…
So, with all the above networks packaged into a Digital Asset, I could play with the parameters (the two scatter values), and try out a few different levels of cutting detail, as I showed before:
I’m creating a rather exaggerated setup in UE4 with an excessive amount of overdraw, just for the purposes of this blog post.
For now, I’ve made the alpha cards huuuuuuuuge, and placed them where I used to have the flowers in my scene:
Then, all I need to do is swap in each different version of my alpha card, and then GPU profile!
The camera shot, without any alpha plane cutting optimization, took about 12 ms.
Test1, which is 27 vertices, seemed to be the best optimization. This came in at about 10.2 ms, so a saving of more than 1.5 ms, which is pretty great!
I was actually expecting Test2 to be the cheapest, since it chops quite a bit more off the shape, and at 84 vertices I didn’t think the extra vertex cost would even register on a GTX 970. Turns out I was wrong, Test2 was marginally more expensive!
This just goes to show, never trust someone about optimization unless they’ve profiled something 😛
Test3, at 291 vertices, costs about another 0.3 ms.
Conclusion
Of course, the savings are all quite exaggerated, but in a “real world” scenario I would probably expect to have a lot more instances, all a lot smaller. In which case, going with the lower vertex count mesh seems like it would still make sense (although I will, of course, re-profile when I have proper meshes).
Lots of more fun things to do with this: get it working on arbitrary meshes (mostly working), see if I can use Houdini engine and integrate it into UE4, etc.
Still not sure how much vegetation I’ll have in my factory scene, but I think this will still be useful 🙂
This is a great blog! I am also a gamedev TA and I really enjoy reading all of your stuff. Thanks for posting it all!
Thanks very much, glad you like it 🙂
Been offline for a few months but hoping to get back into it soon!