Thursday, December 22, 2011

A Quick Update

Despite having forsaken my promise to update regularly, I intend to maintain this blog henceforth.  I've been too busy with school and full-time work to manage this space, but as of now I'm returning to moderate-full-time participation in my personal projects.  I plan to pursue the same voxel-based solution explicated in the earlier journal entries, but focusing primarily upon basic functionality and moving quickly towards a multiplayer prototype.  My earlier plan had been to pursue a "fuller" single-player demo experience, but at this point I see mostly-stable network play integrated into a basic prototype as the best starting point.  Noone wants to support anything they can't play, and noone wants to play awful buggy crap.  If I can merge those two simple goals into a release, I will be totally satisfied.  I want to release a basic multiplayer project that encapsulates the core of what I am trying to do without introducing a lot of excess complexity!

I know that sounds much easier said than done, but in practice I think it means that we'll be seeing much more interesting and meaningful posts to this blog in the near future (likely with download links!)

Wednesday, May 11, 2011

A Few Technical Problems

Slight hold on the new video and screenshots thanks to final exams and some unanticipated texturing issues.  Good news is that it gives me an opportunity to write a post about the problems I encountered and how I solved them :)

Since my world terrain uses only a handful of textures which are largely repeated and tiled, it makes sense to use a Texture Atlas to organize everything.  However, there are a few problems with this approach.  In the interest of avoiding an extremely long post, I'll only discuss the big one:
 
Mipmapping With Atlased Tiles:

Mipmapping is a fairly ubiquitous technique used to improve both the visual fidelity and performance of interactive 3D environments.  However, it doesn't like to play nicely with texture atlases.  Mipmaps require a series of power-of-two textures receding down from the highest-res base texture to the point at which that texture is reduced to one pixel.

The number of mip levels calculated usually depends on the resolution of the base mip level.  However, in the case my texture atlas, I only want the number of mip levels proceeding until each individual subtexture/tile of the atlas is one pixel, which is a smaller number than that automatically generated for the entire atlas.  The "excess" mip levels contain an invalid mishmash of adjacent tiles, which can cause some really bad visual artifacts in-game.

I solved this problem by artificially "capping" the smallest mip level that the program is allowed to sample texels from.  Normally doing this is fairly trivial, but Unity does not expose any functionality for capping the mip levels in an intuitive way.  I was therefore forced to devise a hack in the fragment shader that clamps the screen-space gradients of texture coordinates -- which are used to calculate which mip level is sampled -- to a range that I found through trial-and-error to restrict the mip level appropriately.

It's an ugly hack, but it works.  I'm tempted to praise Unity for its effective workflow that allowed me to find the appropriate range so quickly through trial and error.  Then again, I wouldn't have needed to resort to such a tactic if Unity exposed the basic functionality that I needed to begin with.

Further reading:  This GPU Gems segment was very helpful; I doubt I would have solved my problem so easily without it.  If anyone else reading this finds themselves pulling their hair out over mipmaps and atlases/tiling, give it a read-through.

------------------

That's it for this one.  Big design post on its way soon!

Thursday, May 5, 2011

Humble Beginnings

This is the first post in my dev journal for a voxel-based destructible terrain game being created with the free version of Unity.  Since I've already been working on the foundations of the game, this post will briefly outline the progress I've made so far.  After that, I'll lay out a general plan for future progression.  Furthermore, I'll try to include pretty pictures and videos as often as possible :)

What I've Done So Far:
  • Partially implemented Marching Cubes lookup table
  • Loading, surface extraction, and real-time alteration of binary voxel data
  • 256x256x128 voxel world subdivided into smaller sections
  • Support for up to 64 different tileable 128x128 terrain textures that blend at boundaries
What This Means:

When I say that the Marching Cubes lookup table is "partially" implemented, it means that I haven't yet added all the necessary code for converting voxel configurations to triangles.  Therefore, the generated terrain will have "holes" (missing polygons) in it.  I will patch up these holes very soon, but I decided initially that proper texturing was a higher priority since it could potentially influence the way the lookup table functions.  Thus, I delayed lookup table completion to avoid possibly rewriting a lot of code.

The other important point to note is that my voxel data is binary.  This means that each voxel is associated with a simple binary value signifying whether it is a part of solid surface or a part of empty space.  Many Marching Cubes implementations use implicit surfaces (such as the equation of a sphere) or Perlin noise to generate voxel data that is more complex and actually contains the distances from the surface being generated rather than a simple in/out notation.  This approach facilitates the creation of smoother surfaces.  However, I'm deliberately aiming for a very planar/geometric/low-fi look, so I like the results I get with simple binary voxel data.

Where I'm Going From Here:
  • Lighting.  No complex shadows, but lighting that doesn't clip through surfaces should be a difficult enough task.  I have some ideas about how to accomplish this, but it might be painful to implement, so I'm going to get it done as soon as possible.
  • Cleanup.  After world loading and rendering is hooked up to proper texturing and lighting, I'm going to spend a little bit of time cleaning up my code to make sure that everything remains readable and extensible.
  • Netcode.  The game I'm planning is 100% multiplayer, so as soon as I have the world rendering in its most basic playable form, it's time to hook in the networking.
  • Playable demo.  Haven't decided the exact form that this demo is going to take, but I plan on releasing some sort of relatively polished proof of concept.  This should serve a dual purpose -- firstly, it grabs some public feedback so that I can determine what needs to be reevaluated before the project progresses much further.  Secondly, it should be a nice refresher for me on the development side -- getting a destructible voxel world with workable netcode up and running isn't going to be a trivial task.  The satisfaction of being able to show something for my work, even something simple, will hopefully be a nice change of pace.
To Be Continued

It's probably clear at this point that I've discussed a fair amount of technical progress without describing my design concept for the game that's going to be formed out of all this shapeless mass.  I think that a design overview deserves its own post, so that will come soon.

For now, I'll leave off with a short video I captured of my code in its earliest state.  Keep in mind that there are still polygons missing from the terrain, and right now the whole world is just using one block type for simplicity, so there's only one texture.  My next update should include visuals of multiple blending terrain types and fewer missing polygons!