No point in dancing around the issue, I am out of money and trying to figure out what the next step is. Whatever happens, I am continuing to work on VQ, as that does not cost me anything but time. But I might need to allocate much of that time to a paying job, unless I can figure something else out.
The one thing that I have decided, for certain, is that I am returning everyone’s money: Kickstarter backers, investors, patrons, and preorders (and anything else). I made this decision before I even launched my Kickstarter campaign, although I’ve only talked about it with a few people. I am taking this step regardless of success or failure.
If I have to work another job, I will probably begin this return process as soon as possible (and it will take time to accumulate everything). Otherwise I will begin returning money when profitable. I am still planning to release something in the short term, as well as the source code.
I can understand if anybody is disappointed or angry, but I assure you no one has a heavier heart than I do. I invested over $100k of my own money, debt, and equity into this, in addition to about $500k of work (accounting for overtime and opportunity cost). I spent about a decade working in this area without any sort of return (other than it being "fun"), and over the past 3 years I put in well over 10,000 hours. I dragged my family through all of this as well. Nonetheless, if there is anything more I can do, please let me know.
This is not the end, but it is still a depressing position to be in. Still, I can’t help but be grateful to have been given an opportunity to work full time on something like this.
As I have mentioned in the past, writing a game engine is a feasible (if unwise) thing to do, if you pick your battles carefully. I simply had too many battles, and too many directions I tried to tackle at once. My todo list never once shrank faster than it grew. Only at the tail end of this did I decide (for better or worse) to burn my entire set of goals and focus on one "simple" goal (although I must stress that nothing is simple).
If I sound like I have a bleak outlook, I don’t. I still believe in this and I have something that I am proud of. This is the first time in my life I have worked on something of this magnitude, spanning 50k to 100k lines of code, and not wanted to scrap the entire thing. I’ve tackled a lot of new ground so I suppose the road is destined to be bumpy, but I continue to learn from my mistakes.
If anyone has any ideas of what I should do next, I am all ears. At the very least, I feel obligated to be transparent about my current situation. There is no outcome that I fear, I mostly just want to do what is best for everyone, even if that simply means getting a job and paying everyone back. I will probably investigate past offers I have gotten for funding, but I don’t know if that will necessarily bear fruit.
One last thing I would like to make clear is that nobody owes me sympathy, and I am not even asking for it. My situation is a result of my own choices, and the only thing that I can make better is the future. All things considered, I think this journey has been great so far, and I am curious to see what the future holds.
On a happier note, let’s discuss what I’ve been working on recently.
I’ve talked about (on Twitch) why I ended up doing yet another technical revision. If it seems crazy that I am doing another revision on the rendering, it might be, but also consider that teams with more members, more experience, and more money are going through the same thing that I am (see this video , if you have not already).
My former method, with the ray marching, was becoming a dead end (on my GPU, a GTX 980, it was dipping to 30 FPS in some cases, at 480×270 no less). It was not scaling, and it was getting to be too large (I had to break it down into two shaders because I exceeded the instruction limit). I had the choice to kill it or try and resurrect its performance somehow. The first thing I tried (and I tried many things) was to get performance acceptable. I couldn’t (at least not without creating other serious issues), so I started a new method, which is pretty close to the second iteration of the engine (when it first transitioned from isometric to perspective mode). However, I still use the SDF / ray marching stuff where it makes sense, with animated things and quickly previewing objects, neither of which has a huge performance impact on its own. Overall not a lot of ground lost, especially since I am still using a good deal of code from the SDF stuff (not to mention that the rendering is a relatively small aspect of the code base).
I have transitioned voxel generation to the CPU, using a flood-fill approach that ignores nonvisible voxels and "air" voxels. It is much more flexible and less restrictive than using the GPU for generation. There is no instruction limit, there is not as big a penalty to branching, and there are many more sparse operations that can be done (for one, flood-filling is a sparse algorithm much better suited to the CPU). I also moved to a unified object and destruction model, where all objects and modifications are handled by one algorithm and modifications are voxel-independent, making it easy to do an "infinite" fast undo/redo queue. There is also caching of generated objects, so you only need to generate things once and they get dumped to a scratch disk (ideally these results will be compressed in the future).
I have a new rendering trick that I worked on independently, but I also heard that the team at Media Molecule is doing something similar on Dreams (actually it is pretty funny because our problems and solutions have crossed paths many times, even though we are both working more or less "in the dark"). For lack of a better term, I call it "deferred rasterization."
Polygons are fast, but they consume a lot of vertex memory (one cubic voxel might consume up to 8 vertices and 36 indices depending on the layout). That is up to 272 bytes of data for a single voxel. The naive alternative is to use points (like GL_POINTS) – a single point for a voxel would only consume 16 bytes if a 4-component vector were used, or 32 bytes in my case (two 4-component vectors).
But the problem with naive points is that they have massive amounts of overdraw (assuming they are large enough to fill gaps between them). Especially when looking at objects whose sides run parallel to the view vector. Also, naive points do not look very good – they are essentially tiny billboards.
My (reinvented) solution is to draw points as small as possible (1 pixel large), and grow them in screenspace, using ray casting to determine the cubic boundaries of each point. This is done in a horizontal pass and a vertical pass, as you would do with most kernel type shaders like a blur shader, to reduce the number of texture lookups. In my tests, it is approximately as fast as polygon rasterization of voxels (or faster), but uses a fraction of the memory.
The results speak for themselves. I can now run at 1080p at 120 FPS or greater (again, note that my last method only performed "ok" at 1/4 1080p, 470×270 – at 1080p it dropped below 20 FPS). And I still have plenty of room left for optimization. It also looks cleaner, visually (the SDF stuff often looked too noisy and had many artifacts, not to mention that jutting edges (such as grass) were too costly). I should be able to do VR if I can ever spare the time to implement it. Running at low resolution, I can get 600 to 1000 FPS, so this should scale decently (I know milliseconds are more meaningful, but more people understand FPS as a number).
There are many additional tasks and a lot of cleanup that I am doing as I prepare for the first release. I have had to rework a lot of the physics code because it was simply too unpredictable and not really well suited for voxel collision (Bullet is a great library, but be very careful what you choose to use it for). I couldn’t bring myself to write a custom voxel collision handler for Bullet, so prior I was "faking it" and the voxels were not producing "real" collisions or contact pairs – they were simply causing objects to hover above them as if they were exerting a magnetic force. This led to many issues and collision and friction produced a user control feedback that felt wonky. There is something be said for simple, predictable, slightly unrealistic physics though.
I will put together a proper update video as well soon, but for now here are some shots and videos: