Today I got the last major rendering feature running. I also fixed a bug that has been bothering me for weeks. I didn't expect today, or the last two weeks for that matter, to turn out like they did.
I wanted there to be some vivid color in my world. Much of the scenery is monochromatic, so I wanted flowers. Fields of them.
Normally I write about things that go well. Like this week I wrote a bitset template class, nothing super complex, but a few hundred lines of code. To my amazement it compiled without warning and passed its also-brand-new unit-test the first time. That doesn't happen very often. Occasionally I'll write about things that went pretty badly. Then there are the things that go spectacularly off the rails.
I'm not the type to program by the seat of my pants. Before I start, I always take the time I need to research the tech, figure out what pieces I need, and decide how best to build them. This process has paid dividends consistently over the years although I have occasionally taken grief over it from people who were new. (They came around.)
I estimated that implementing my field of flowers would take two days. I was going to implement texture decals on the terrain, nothing fancy: integer scaling, aligned with the terrain grid, and compass point rotations. I needed one day to modify the terrain program to place the decals and one day to implement the decal loading and rendering. I implemented the decal layout no problem, but when I started on the rendering I realized I had made a fundamental mistake with my plan for rendering. What I had planned wasn't going to work - at all. It wasn't fixable. I had to replan.
Given that the decal layout was already working, I looked into decal projection for a couple hours, because it would give me the additional feature of being able to put damage decals on models, which would look awesome. But looking at the complexity of it, both from a geometry perspective and from a texture management perspective, I knew it would take at least a week to implement and debug. And I also realized that my original decal plan had another big issue: my terrain is 50 pixels/metre so a one megabyte texture will only cover 100 square metres. That's not really the field of flowers I envisioned.
So I thought of using my existing terrain texturing system, adding an additional layer for flowers, and adding a way to lay out the flowers with perlin noise maps. The terrain was looking awesome - I thought it might work. So I ripped out the brand new decal layout code I had just finished writing (after shelving it just in case I needed it again in the future.) It took a day to write the new code and then I ran squarely into something an artist buddy dubbed the "looks-like-crap-factor." Art has to look good, and my red flowers on white sand had huge, ugly pink smears around them where the textures blended.
So I tried a simple variation on the theme: removing the blends from the flowers. That took a couple hours to code, gave me crisp clean edges, and fields comprised solely of squares and triangles. Yuk.
I needed a mask. My first attempt was an algorithmic mask. I thought I would get sweeping curves where the blends were. It wasn't exactly what I wanted, but it would at least be a step in the right direction. It took a few hours to code (mainly because it needed additional data from the pipeline) and gave me flowers with a crisp, clean border and perfect geometric shapes almost-but-not-quite identical to my previous attempt. The "looks-like-crap-factor" was still firmly in play.
I needed to take a step back, so I implemented a new faction select UI screen and the logic on the server to save that selection.
That artist buddy I mentioned had also looked at my latest screenshots and pointed out that my shadows were too dark. If you look at the shadows from a direct light, there is actually quite a lot of ambient light in the shadow. So I also took a couple hours and modified my shadows so that they only affect the direct light, not the ambient light for the scene. My original shadows were nearly black, the new shadows are lighter and look much more natural.
So I had taken a bit of time to think about my flowers. The basic flower texturing was working well, but what I really wanted was a mask around it that had irregular flower-shaped chunks out of it. I had a plan, but generating the data to run the mask was going to require some substantial changes to my terrain texture layout system.
Now I also had a longstanding bug in my terrain texturing that would occasionally cause two adjacent terrain blocks to think that a shared vertex had two different textures on it. This would result in an ugly seam line where the two terrain blocks abutted. Now the reason for this was that each terrain block was textured separately (to take advantage of all 8 threads,) and they overlapped on two edges, but they didn't actually share memory. And the texture reduction algorithm didn't guarantee that adjacent blocks would have all the textures they would need to blend between adjacent blocks.
So I spent a couple days and drastically refactored the terrain texture layout and block texture selection system. The big step forward there was in the implementation of a couple of routines that verify that the output of each step is correct. I spent a lot of time with these routines. Having a lot of data is fantastic for debugging. As I worked on the algorithms I would run each change, and each time it would get through a few hundred more blocks successfully before failing again. It took a couple of days before it got all the way through and I am pleased to report that the new texturing is perfect. No more seams.
While I was in there, I added a step to generate the data I needed for my mask. So with my new mask data ready to go, I needed to get the rendering working. This went better than my first attempt a week and a half ago. I took a hint from old tile-based games and designed a set of 16 alpha tiles I could put around the edge of the field. Now the actual tile masks have chewed up edges, holes, and other details to make them more interesting, but they're all based off this template (transparent parts are blue, and the grid is for illustrative purposes):
We were unable to retrieve our session cookie from your web browser. If pressing F5 once to reload this page does not get rid of this message, please read this to learn more.
You will not be able to post until you resolve this problem.