A little background
How much art can you make without making any art?
Well, that's what I figured I'd explore with AFK. It uses a pseudo-random number generator (the rather nice boost::random::taus88
) and splits the world into cubic cells. The seed that determines the contents of each cell is a combination of the cell co-ordinates and a master seed generated or supplied at start-up.
And the results: https://www.youtube.com/user/KaiEkkrin
There's plenty of scope for tweaking what is done with the random numbers, but all the actual detail you see is generated on the fly. It's cached, rather than built up front (because AFK's worlds are much too large to hold in memory), or wholly generated for each frame (because that would be too slow).
Along the way AFK does some other interesting things:
- Rather than having fixed detail settings, it measures how long it's taking to generate each frame and adjusts the detail accordingly, aiming for a frame rate between 30-60 frames/second. (The algorithm is a little over-damped right now, causing the frame rate and level of detail to oscillate. I'm working on it.)
- The amount of detail is theoretically infinite, although in practice it's limited by the amount of precision that can be represented by the int64_t world co-ordinates (and their conversion to float).
- The world enumeration runs across many CPU threads (currently up to 64), using a queueing system in place of a recursive call to drill down through the world tree.
- Because OpenGL implementations (especially AMD's) run slowly when fed a large number of draw calls, AFK draws the landscape and all the visible shapes in just a couple of calls, using instancing with a large buffer texture to produce the desired geometry.
- Random world features are generated in OpenCL, then passed to OpenGL for drawing. AFK supports CL-GL buffer sharing, but it's disabled by default, because I've yet to find a GPU on which it's a performance improvement. Instead, I allocate a small number of very large textures mirrored between the OpenCL and OpenGL (the "jigsaws"). Each frame, rectangular areas are allocated to contain the new computation tasks for the OpenCL, and these rectangles are copied to the OpenGL after completion. (Again, for performance, the number of calls needs to be minimised.)
- Generated world detail is cached in the lockless hash map structure
AFK_Polymer
. I created this structure rather than usingstd::unordered_map
with a lock because each frame, the world enumeration needs to do a very large number of concurrent lookups. In this situation, my custom structure's benefit (I measured a 10x higher lookup rate vs.std::unordered_map
with a lock on an 8-thread system) outweighs its drawback (it occasionally generates more than one value for the same key).
The small blue chevron that serves as "protagonist" right now is a cheat, because I encoded its geometry by hand. I'll remove it as soon as I can generate a random shape that fits its place nicely.
23 January 2014
v0.2.1-test release
I've released a Windows build of AFK here: https://github.com/KaiEkkrin/afk/releases/tag/v0.2.1-test
Shape render is still turned off; I don't want to keep the current shape system anyway, and I'll probably rewrite it extensively before releasing a build with it enabled.
I'm interested to see how well AFK does on other computers. If anything goes wrong (or even if it doesn't!) send me the file that gets written when you run it with "--log-file log.txt". If the level of detail drops to a minimum and stays there, try encouraging it to work harder by increasing the frame time target, e.g. with "--target-frame-time-millis 24.0".
And yes, it's sub-optimal in many ways that I know about already (and no doubt some that I don't) :).
11 January 2014
Windows merge, etc.
Getting a new job has meant I can't do so much to AFK these days, but I'm still going. I've merged Windows support even though it's incomplete: shape render is turned off right now, because it crashes. I've also discovered Nvidia's OpenCL implementation is always synchronous, which means my attempt at making correct asynchronous OpenCL calls didn't work even though I thought it did. Asynchronous is currently disabled by default pending fixes...
18 November 2013
Stability fixes
I haven't had so much chance to work on AFK this month, so there's nothing new in right now, but I've reworked a lot of the CPU code to try to improve its stability. Async, jigsaw, caches and the Claim stuff should all be more reliable now, and the "Polymer" cache structure is currently entirely lockless, using atomics and fences to synchronize. Lessons learned, etc etc.
22 October 2013
Points
I've been wrestling with filling the gaps in my 3D edge shapes, adding lots of code to no effect (and also, to be fair, procrastinating by refactoring the jigsaw, working on the Windows port, and all that kind of thing). Because most triangles are correct and there's such a huge volume of data, I've found it very frustrating to try to figure out the corner cases where the triangles get omitted.
In an effort to find the causes of those gaps, I built a shape renderer that uses points instead. I was intending to use it only as a debug thing, but after I fixed the point sizes and removed my debug colours the result is remarkably good:
https://www.youtube.com/watch?v=BDxZB5DGOHo
So good, in fact, that I'm now considering giving up on the fixed triangles baked by the OpenCL edge kernel in favour of refining this render instead.
As of now, the master branch will render shapes to points by default. It can be put back to the triangles render by setting RENDER_SHAPE_AS_POINTS to 0 in shader.cpp.
17 October 2013
A nuts 'n' bolts update
I've pushed a heap of changes that make the shape shader use the 3D textures directly for colours and normals, and removed the flattened-to-2D versions. The result doesn't look any different, but it should clear the way for a more sophisticated edge detector that can generate extra triangles to fill in those pesky gaps.
Jigsaw-out-of-room errors should be rarer now, too.
11 October 2013
AFK's first upload
Wow, it's in a bit of a strange state right now, isn't it? All those holes in the objects? Yeah, that's because I'm deforming single cubes to fit the shapes, and it runs out of triangles in the cube to fit. I've actually got a local branch right now where I'm working on a fix to enable the geometry shader to generate the additional faces. It'll be up in a week or two, I hope.
But art is never finished, only abandoned, so I figured I'd go public right now just in case :).
After that, I should really make an effort to get it to build on Windows. I know that half my mates can't run my useless wonderful project because they don't have a GNU/Linux install.
The current defaults betray the Tetris-like skeletons of the default shapes a bit much, by the way. Try this:
./build/release/afk --shape-edge-threshold 0.05
for something less... cuboid.