An important part of testing the usability and showing that it's not just a toy project is to actually create a game using the library. One will also find more bugs when starting on a new project because most of the code in big projects end up working with abstractions that rarely touch the library directly.

By not having to store this in the git repository, I can add things that would take way too much space for someone just wanting the library for basic 2D applications. The version control system can be kept locally and expand with old history as much as it needs to.

The isometric sprite engine was updated with the ability to erase background sprites and models from the oc-tree structures. This allow changing the floor's height using a tool in real-time and have the surrounding 3x3 tiles updated by creating new tiles based on pattern matching, invalidating affected background blocks and repainting the background to the screen.

The first roadblock that appeared was the design tools. I could just add some vertex weights and animate characters like in modern games using real-time triangle rasterization, but that would be slower for large crowds and less detailed. Having images of every pose and direction stored in the game's folder would take too much storage space. I might split characters into multiple parts and then just pre-render the frames on first use to be stored for later. Once a character is no longer visible, new characters can then overwrite the buffers with more current animation frames.

I would like to avoid adding sound to the library, because sound and graphics are completely unrelated things that doesn't benefit from being in the same library. The game will probably use an external sound engine, which can be replaced easily with another engine when the game ages.

Physics could be added because it doesn't have any external dependency, but general physics engines cannot do specific optimizations to improve quality and performance. I usually merge collision blocks for tiles as compressed voxel sets to reduce wasted memory, but this is difficult for a general physics shape being imported from a model with a floating-point transform and rounding errors. Custom physics will also result in much smoother walking physics, better continuous intersections for projectiles, cheaper particle effects by not affecting a general broad-phase, and prevent items from falling through the floor when knowing the minimum ground height for each location on the map.
An old trick still useful today
Added another planned optimization to the Sandbox example. Using dirty rectangles, I can avoid redrawing the height, diffuse and normal background where nothing has moved. I worried that the frame-rate would feel uneven because it increases the difference between worst and average case, but at these speeds, a one fourth's frame's jitter is lost to tearing against the screen's 144Hz refresh rate anyway.

Reached 453 frames per second instead of 295 for 800x600 pixels. With 185 FPS for 1920x1080 pixels, I'm pushing the limits of my 144Hz gaming monitor and the extra fast DisplayPort cable.

Might sound like overkill
but getting people to use CPU rendering again requires some sick performance to be convincing, because the GPU's only advantage is performance. More optimization can be done by computing deferred light using a smaller buffer one block at a time. It's currently a naive implementation thrashing lots of cache memory. These blocks would also allow skipping light sources based on early light culling tests.

What to do next
Ray-tracing cards use parallelism to acheive soft shadows by letting each pixel have another light direction. With a CPU's higher frequency, one can go for higher speeds instead and let light sources shake faster than the eye can see and then smooth out the result using temporal motion blur. A sliding window integral implementation would allow creating stable distance adaptive shadows using a pre-defined set of light offsets. As long as the light being subtracted has the same relative offset as the new light being added, the result should look stable without the need for noise reduction filters. An exponentially fading temporal blur would be cheaper, but the perceived smoothness is relative to the most visible frame.

Screen-space ambient occlusion can be stored relative to the world using the same technique as the background. By only updating ambient light around places where something moved, the cost will be close to nothing for soft shadows.

Once I'm done optimizing, this will be enough to challenge Nvidia's latest RTX cards in terms of resolution, frame-rate and visual quality.
Recently read about how important it is for open source projects to let their users find them in order to get more contributors, and I do need help with making the project grow with all the big plans I have. Then I made a search for my old engine and only found one post mentioning it, which was about how such a good product could be completely unheard of for ten years. My skills in promoting my projects can probably improve, so I've spent the last week building a new flashy website with a short top domain, so that visitors have more than just the github page to bookmark. Read about search engine optimization but failed to get it indexed by any search engine in the end. Designed some banners that people can use when linking to the website, which will hopefully keep it from being completely invisible when people explicitly search for my full name.

Decided to trademark the site's name using the ™ symbol without registering it, because it's been with me for decades any someone else using it would feel like identity theft. Buying the dot com domain should be enough to scare away any criminals trying to steal the name. If they buy a strange local domain, I can just laugh at them for getting the domain people can't remember.

Because my old site was on classic Google sites, which will soon reach the end of life, I also moved my old GPU renderer from 2010 into the new site. Many years ago, I assumed that my site could stay on Google Sites because they wouldn't go bankrupt any time soon, but instead they became crazed with power and closed it anyway. Google is really adamant about bending users to their will and did not even offer to keep the existing themes from Google sites. This was the third nail in the coffin for using Google after they ruined my YouTube account that I used to showcase my engine and locked down Google code where my code was hosted. It's back to plain HTML then.

Tried many times to get CSS to work for more than just the index page, but eventually had to give up and just paste the style into each page's head. A system for automatically generating HTML from my own text format would probably be more efficient, because I also have a top menu repeated on each page, which must be defined in the HTML body. When designing a website, I'm torn between using free tools that are tied to a service (which will be gone after only a decade), and having to write HTML by hand (can at least be copied to the next host). Should probably create my own tools for generating websites with correct character encoding and tag endings automatically, because I'll need it for the software renderer's HTML documentation. HTML is way too verbose even with CSS and Markdown is not explicit enough with all the dialects.
Floating-point operations in 3D geometry transformations aren't bit-exact between different computers rendering the sprites, but version history tools are very picky about serialized rounding errors. The sprite generation tool will now look at existing sprites and tolerate a certain deviation before deciding to overwrite existing files, so that rounding errors will no longer cause random sprites to be overwritten and bloat the version history. A fuzzy text comparison function parses all numbers to check the numerical differences.
Wrote an import function for the Stanford PLY format today. Used it to load and render the mage model I sculpted and vertex painted in Blender yesterday. The Stanford PLY format stores color together with positions and is commonly used for 3D scans, so I found it usable for generating isometric sprites.