Quick update since it’s fairly late and I’m off to bed.
Been playing around with Unity3D this past weekend (had Friday off too), and must say I’m impressed. It’s surprising how much flexibility they can achieve while still presenting a fairly consistent ‘API’. That having been said, there are plenty quirks and a few kludges, particularly with what I’m working on. But less than other frameworks I’ve used, and those didn’t provide half of the features Unity does. So, great!
This exploration really begun when I realized you could in fact perform GPGPU (general purpose computing on the GPU) through unity using DirectCompute (D3D11 only). One thing led to another, and I decided to see if I could generate some terrain on the GPU. ~15 hours later and, well, here we are. Now, I’m not going to say it was particularly straightforward… in fact, it feels a bit hacky. Particularly because, in order to leverage the physically-based surface shaders (Unity 5+), I needed to use a mesh. So after dispatching my thread group to the Compute Shader on the GPU which calculates the height at each point on the terrain using Simplex noise, when it comes time to actually draw the patches, I had to draw a “dummy” mesh (with the same # of vertices as those I computed on the GPU) that has junk data for the vertices, and use a custom vertex shader in front of the stock surface shader to transform those vertices to the ones I just computed in the Compute Shader. That’s the big hack - but it works, and I’m sticking with it.
(By the way… Unity limits the number of vertices in a mesh to 65k. Not even 65,535, which would be 256x256, but 65K… grumble. So I’m doing 224 vertices per edge, so 224x224 - 224 is a multiple of 32 (x7), which was efficient for my Compute Shader’s thread group layout. anyway…)
The terrain heights never leave the GPU - once calculated they’re stored in a “structured buffer”, and the vertex shader reads into the same buffer to transform the dummy mesh’s vertices. Once that vertex shader completes, it passes its results to a stock Surface shader, allowing me to get all that physical rendering goodness for free (Had I not wanted to use the stock surface shaders, I could have avoided using the dummy mesh).
I did a basic benchmark on my GTX 580m (which is starting to show its age), and was able to maintain just over 65 fps while calculating 36 new patches (of 224x224 = 50,176 vertices each) every frame @ 14 octaves per vertex (which is probably way overkill). I think that’s pretty good! Of course, in an actual planet engine, once the patch was calculated I’d hold onto it as long as I could (to be freed only when VRAM was needed for a newer patch), whereas here I’m dumping and rebuilding the data every frame. Now, mind you, I’m not reading any data back to the CPU - that takes much longer. I’ll eventually need to do so for at least two reasons: 1) To calculate bounding boxes - but there I think I’ll do a parallel reduce on the GPU (basically it determines the min/max vertices in a parallel manner) on each patch, and then retrieve that data (so 2 floats per patch vice 50k… that will be much faster) - and just use the min/max possible height in the meantime, since that will have to be an asynchronous process otherwise the whole pipeline will stall. 2) is the harder one - physics. If I’m going to do any kind of collision detection, I’m going to need to either do it on the GPU (which would solve all the problems, BUT I think would be completely outside the scope of unity and require basically all physics calculations, not just collisions, to take place on the GPU…), or be very very picky about what terrain data I send back to the CPU (those transfers are slow, and laggy, and will chunk the framerate in a heartbeat. So probably stuff like only sending the patches nearest to the camera, and doing so at a lower vertex resolution than max LOD, etc). I don’t plan to worry about that just yet, but it definitely is a consideration when doing GPGPU.
Anyway, like I said I’ve been really impressed with Unity. I’ve basically achieved the same amount of work in the past 3 days as I did in 3 months working on my planet renderer. Now, granted, A) I was writing an entire engine, not just a planet generator, B) I could only dedicate 5-10 hours/week, and C) I was a much more novice programmer. Not to mention, I’ve been able to leverage the lessons learned from that project (and recently refreshed thanks to this thread!), as well as several bits of code. Regardless, it’s without a doubt easier to develop code in Unity due to both the existing libraries and the ability to ‘visually debug’ - clutch stuff!
What’s next? I’m probably going to go all the way on this one, and implement the full scope of techniques we’ve been discussing throughout this thread. Once all that technical stuff is done, I’m going to explore the more artistic side of things. Hopefully I can get Unity to recompile a shader at runtime, so I can hot-edit the terrain generation functions and play with different functions, etc. Maybe even explore ‘non-procedural’ content mapping - i.e. using a base DEM or texture to ‘influence’ the underlying generation algorithm.
Heck, I might even make a game out of it. I’ve wanted to build an RTS/Civilization-style game for awhile, and doing so on a procedural planet would be fun.
So, yeah! I’ll post a screenshot, but it’s ugly. Everything’s using 1 texture, and I haven’t tweaked the noise function parameters at all (actually the terrain generating noise function was a direct copy-paste from my last project!) - but everything is functioning and the terrain is being generated on the GPU which has been the whole point of this test so far.
That’s all I’ve got for now! Let me bring this excited, sleep-deprived rant to a close. Talk to you soon!