Optimized mesh and single chunk?

Ugur posted this 12 July 2016

Hello there, i bought a few voxel packages and am currently evaluating which to use for what. So with pica voxel i like the animating part and editing in the unity editor is largely nice (besides for some actions there is no undo or it does not work as expected), and i like the animating part, too.

One thing i don't like is the performance of the result, so i wanted to ask if that will be changed in one of the upcoming updates any time soon since it would really settle whether i have to use something else or can use pica voxel.

So as example regarding the performance: -I made a few voxel models in magica voxel which i then want to use in Unity. Now when i try this in Voxelmax (another voxel package), then the work flow is i import the magica voxel model, then i press the button called build optimized mesh and then i press the button to turn it into an obj and then that model has 3.5k tris and leads to 3 drawcalls (with standard shader and directional lighting/shadows affecting those). It's a single obj then with single gameobject/renderer/mesh/material used so that's how it has a low drawcall count.

When i try the same in pica voxel, so i import the magica voxel model, then there is no build optimized mesh option and i can only press the button to make a mesh only copy. But on import it does not make it into a single voxel volume (my magica model uses a volume of 45,45,45 but only 17,10,24 are filled) and so it also does not make it into a single mesh on convert to mesh only copy, so i end up with a game object with many nested chunk gameobjects and also the meshes are not optimised in poly count so it then has 4.9k tris and 11 drawcalls. 4.9k tris instead of 3.5k and 11 drawcalls instead of 3 is of course much worse. I should mention that i want to use this mesh in many instances so then that gets multiplied and is then ultimately a huge difference in performance and resource usage.

So yeah, again, i don't mean this to blame on pica voxel, as i said, it has many upsides on other ends, a very important one to me for this project is for example that it also (unlike voxelmax on magica model import) puts the coloring in the vertices instead of using a texture palette, this allowed me to create a shader for the pica voxel model to swap all palette colors at runtime easily and at great performance in the shader, whereas for the voxelmax solution one would have to generate lots of palette textures etc and it's not flexible and on top does not even use the magica voxel's color palette texture and strips unused items from the palette which may seem like a nice thought but trashes any reusable palette swapping across different models using the same palettes (but using different colors in those palettes).

So yeah, it would be great if this part of many separate chunks created (causing many separate objects increasing drawcalls) and not having the mesh polycount optimised could be improved in pica voxel, then i'd be very happy to use it, so any chance for those anytime soon?

Order By: Standard | Newest | Votes
GarethIW posted this 15 July 2016

Hi there! Sorry for the delay in response, I've been at a conference this week and I'm just getting back to my usual routine today :)

I completely understand your frustration with draw call batching (or lack thereof). This is more of a Unity issue than a PicaVoxel problem. I expect you are familiar with how batching works in Unity as described in the manual here: https://docs.unity3d.com/Manual/DrawCallBatching.html

Unity is really bad at dealing with vertex-coloured meshes with lots of vertices. Not only do you have the 65k vertex limit (which is why PicaVoxel relies on chunks to get around the limit), you also have the problem where the more vertex parameters you have (i.e. position, colour, uv, normal etc.), the fewer verts you can draw before batching breaks.

If you were to use OpenGL or DirectX directly, it would be really simple to draw many vertex-coloured voxel models in a single or at most a very few calls. It's something I've struggled with while making my own voxel-based games (both with and without PicaVoxel).

I haven't looked at VoxelMax for a while but it sounds like the optimization step is something done at edit time, because building a texture and uv mapping would be pretty expensive at runtime.

PicaVoxel was always designed for manipulation of voxel data at runtime, so I don't really have any plans to offer tools for creating static material-based meshes. There is, of course, nothing to stop you using VoxelMax to create models that are part of the background and then using PicaVoxel for cell-based animated models and anything you want to explode or build at runtime.

I do have one suggestion for your very specific case: You said that your model is 17x10x24. PicaVoxel has a maximum chunk size of 161616 = 4096, but you can set that to be non-cubic. Your model would fit in a single chunk of 171024 = 4080. So if you cropped your model to that exact size in Magica (or in PicaVoxel after import) and then change the chunk size in the Resize window, you could fit it in one chunk. I realise that is very specific to that particular model, but it will allow you to draw with one chunk instead of 4 in that case.

I hope that at least offers an explanation and perhaps helps a little.

Ugur posted this 15 July 2016

Hello there, thanks for your indepth reply =) and no worries about it being a bit delayed, i understand and hope you had a good time at the conference =) Your suggestion of going for a smaller volume size to reduce the amount of chunks would be cool for other use cases, but in this one i can't since the players (models) are not just that size but can actually be a bit bigger in some cases, too. I meanwhile tried many (if not all) other asset packages which allow to import from magica voxel. All others still current used the way of not coloring the vertices but instead creating a texture, so yes, that conversion is done at editing import time, not at runtime. It has the big advantage that thanks to that the poly/vert count can be lowered even much more since then the algorithm can combine more parts. So that way i could have obj models after converting which have massively lower poly count (in return use a texture but the filesize and mem usage of that is performancewise not important on desktop etc). Also only 1 drawcall of course (or 3 with lighting etc). One big downside of that approach is that the texture has to be set to point (so no) filtering because else it looks bad when i change the palette of the texture in the shader at runtime (at the color transition edges it's off then) And when setting it to point filtering in return then the edges look slightly jaggy. It's no huge biggy, but yeah, lookwise i totally prefer the vertex coloring solution and yeah, it's also more flexible in usability in a few ways.

Anyway, so i understand for Pica Voxel you don't intend to go the way of creating optimized obj model mesh files using a texture for runtime/edit time since that would then not allow editing anymore, that part i understand. Though i think it would still be cool to have that in there for when one creates a mesh only copy =) (That something like that is not there to get an optimized mesh only copy for things one only wants to edit at editing time and not runtime is the reason i create the models in magica voxel right now in first place instead of nicely inside the unity editor in pica voxel). But then, when not going texture map instead of vertex coloring in either case, there's still the part that i feel like some other things could be optimized there in pica voxel to end up with less polies/verts/chunks.

For example in my models, in magica voxel i doodled around inside the model but in usage i actually don't want all the voxels/polies/verts inside the body there anymore of course, i only want those to remain which make up the outer surface. When the inner voxel cubes/faces etc could all be stripped away automatically, then it can also have way less voxels/faces/polis/tris and could also fit into a single chunk (and hence then also only 1-3 drawcalls instead of something like 11 for many chunks) since then way under 65k vert limit. Regarding the 65k limit it should also best check the actual verts instead of just assuming all cube positions would be filled.

Do you know what i mean? These other packages for magica vox model conversion due to going the texture using way can optimize even further (and i made stats on all and so voxelmax is not the best choice there anymore either, it's conversion only package =) ) since they can also on the outer surface combine more parts which use the same color since they don't retain the editable voxel(size) anymore, so that part you can't have in pica voxel since you want to allow keeping it editable (though again, could have it for a mesh only copy to also combine those tris).

But the part of allowing to strip all inside faces/voxels, so all which are not seen since occluded by outer faces anyway, that would already be a huge help in both performance optimisation regarding poly/vert reduction and also in ending up with less chunks or only one chunk and hence way less drawcalls and would make a lot of sense in pica voxel, too i think, what do you think?

GarethIW posted this 15 July 2016

What you're asking for there is essentially occlusion culling.

With PicaVoxel, there are three points at which hidden faces could be culled:

1) At import/edit time. This would be the only one that I could feasibly support. I could provide a tool that would scan the model and remove faces for any voxels that cannot be seen from any point on the outside of the mesh, essentially by doing a raytrace for each face.

This would be fine until you make any changes to the model, at which point you'd need to run the scan again. Still fine for edit time, but then in the case of PicaVoxel you come to the next point at which occlusion culling could be done...

2) At runtime, when a model is changed (by exploding or adding voxels). For example, your model is a building. You have drawn the rooms inside the building and also the outside walls which are occluding the insides. At edit time, you've run the occlusion scan so that none of the internals have faces currently in the mesh.

Now you explode an outside wall, so that suddenly you can see the insides. You would now need to recalculate all of the chunks that make up the inside of the building, because any of the faces on the inside could now be visible from the hole in the outside wall. You would then need to run an occlusion scan on all of the faces that are inside the building but still not visible at any angle through the hole. This calculation would take far too long to be done at runtime.

3) Real-time occlusion culling: Unity itself does not provide any realtime occlusion culling, you have to bake it at edit-time. I know of no method to do realtime occlusion for a model that has as many faces as a typical voxel model.

My advice has always been to fill your model's insides completely when no internals are required at runtime.

I've always been honest and said that I'm not a maths or graphics guru - PicaVoxel came about because I was getting requests from people when livestreaming development on my game if I would release the engine someday. I'm going to be completely honest again here and say I'm not sure of any way that I can further reduce call batching while retaining the completely dynamic nature of PicaVoxel at runtime. I'm always open to code improvements from the community though! I'm also completely willing to refund if you don't think you'll get any use out of PV because of this.

Ugur posted this 15 July 2016

hello Gareth, yeah, it is sorta like occlusion culling =) And yeah, it would only make sense to toggle that option on for meshes one doesn't want to explode at runtime. Not sure how fast one could get it to run, if it would be forced to be toggleable to be done once during editing time or could be done on startup of the game in play mode if not too heavy. I'll play around with it regarding that once i have some spare time for that. And no worries, you've made quite some cool things there already =) And no, i don't want a refund, i quite like Pica Voxel, that's why i even took the time to write suggestions for further improvements =) And it's cool you put it up when people asked for it =) Your game looks great btw, looking forward to play it =) It seems like the cool new voxel version of a game i liked a lot a bunch of years ago =) cheers, Ugur

Last edited 15 July 2016

BlueCandleGames posted this 17 July 2016

Hey I might have a partial solution.

What if you attached box colliders to the chunks of the same size as the chunk size, and do a raycast from the camera to check for obstructed chunks? Disable the rendering of chunks that are not visible to the camera This should have the effect of "hollowing out" volumes by disabling the rendering of inner, invisible chunks.

I'm not sure how practical this would be though. The raycasting may carry some pretty significant overhead, and you might disable chunks that are obstructed but casting shadows, distorting the shadows. I guess you could fix issue #2 by casting more rays at an opposite angle to the camera to check back-facing chunks but that will compound issue #1.

Our 137 members have posted 527 times in 128 discussions