Saturday, November 4, 2017

Tachyon Chase FX devlog 1

Heya, sorry about taking a few days for this. Gonna be blunt: I slightly estimated the effort required to get Unity to be bad enough at shading for my purposes.

So, there's not any gameplay here, as such - there aren't even any physics attached to that ship yet - just a brainless controller attached to a garbage pile of geometry that rotates it while rapidly pulling it away from the camera to simulate actual gameplay. There's some method to this madness, though! I knew from the outset that what I was looking to do here - being a very fast, twitch-oriented game - needed to be readable as hell, and part of what I was looking to do with the SuperFX-inspired aesthetic is enable players to very easily read the layout of the pipe ahead of them. The simple, flat-shaded polygons allow you to easily size up each facet of the oncoming track and plan out what you're going to do in advance. Toward that end, getting a gameplay prototype to play well really necessitates I have that lighting model up and running ahead of time.

As I mentioned, though: it was kind of a pain to get to this point! There were two things that I needed from my lighting model that made this tricky:

1) Light should be distributed evenly across every pixel considered to be part of the same face. Lighting should clearly differ between faces.
2) Quads should be lit per quad, not per triangle.

This created an interesting problem. I obviously needed to duplicate vertices in order to ensure each polygon had its own set of unique vertices, calculate the centroid of each face, and store the appropriate centroid for each vertex as part of the mesh data in order to use that in lighting calculations. I wound up using the tangent channel for this - each vertex's tangent is the centroid of the face it belongs to; use that in lighting calculations and you can ensure that each pixel on the screen is shaded with the same color regardless of what part of the face it represents.

I didn't want to do all of this by hand, of course. It's much handier if I can do reasonable things in Blender and have Unity do the appropriate data transformations when I import my meshes. So I wrote an AssetPostprocessor script that does the necessary work, extracting vertices/UVs/normals/indices from the input mesh and creating a new mesh with the expanded vertex array and whatnot. This also does the work of calculating centroids per quad face, splitting each quad into two triangles, and associating each of them with the quad's centroid, so that's cool.

Then I hacked together a riff on the standard shader that used the tangent in place of the vertex position when doing lighting calculations, and - voila. That gives me this nice effect, which should seriously help communicate depth to players - important when you spend the entire game moving into the screen - and facilitate building something that feels really nice to play.