Thursday, October 23, 2014
Excellent day!! That said, it really did, unfortunately, have to be a technical one
Sorry folks! I've
got to get this asset caching mechanism in place, as it's starting to drive me crazy that the overhead testbed takes ~5 seconds to load / reload. I know, it might sound crazy, but that's just enough of a latency to break my flow (it's a whole different ballgame from, for example, the UI testbed, which is basically
instant). Yes, that's the first and foremost reason that I'm being driven to make the change
now, but, as I've said before, it's something that
must be done before release.
I've broken off bits and pieces of the problem before, but today I've built a full road-map of everything that must be done, and started to grind through the absolute most-challenging bits. It's a beast that goes deeper than I ever imagined, but, like most deeply-rooted beasts, solving it has a vast landscape of positive implications for other systems!
Most of the work lies in unifying and simplifying the key structure that underlies all rendering operations -- the
renderable class. The diversity of ways in which various bits and pieces are rendered at the moment presents a serious problem for a unified treatment of graphics assets, which is a requirement for a unified caching mechanism. The thing is, at the end of the day,
every graphics asset ultimately comes down to a
mesh (the geometry that's rendered) and a
shader (the program and program data with which that geometry is rendered). Hence, there's really no reason for graphics assets to be as diverse as they are now. The complexity must be compacted down to simplicity, but, as always, doing so requires finding the perfect insights.
Today I have developed what I believe to be the total set of insights required to remove the beast, and have already successfully applied the biggest one to solve one of the most deeply-rooted problems: the problem of special-case renderables that require data to be retrieved each frame from a game object (this applies to basically all 'dynamic' effects like weapons, thrusters, missiles, etc.) As a side-bonus, I've actually managed to do something today that I've always wanted to be able to do: draw a big wall of separation between the LT rendering engine and the Limit Theory game
That is, the rendering engine no longer knows anything about the game. That's how it should be, and the fact that I was able to do it today is a really good indication that I've made a leap in the right direction.
At the end of this process, we'll be left with a lot more than really fast asset caching. We'll also gain an elegant, unified geometry pipeline that will be trivial to manipulate in script. We'll gain (well,
already have gained) a powerful mechanism whereby world objects can pass data through the render pipeline (in fact, rather similar to the way that widgets can pass messages through the UI!) Perhaps, above all else, the collapse of so much complexity will inevitably yield performance benefits. Shader programs will become much more simple and faster to bind / unbind, renderables will lose several levels of indirection (making all geometric operations faster), and the less-abstract memory layouts will make it easy to perform a vanishing act on those slight stalls that occur occasionally when an unloaded renderable comes into view.
Remember: the tech and the content live in a harmonious dance. We must do what we must do to reach LT enlightenment (AKA 1.0!) I'll make it as fast and painless as I can, and will be sure to continue allocating plenty of time to content as I go
On a (more!?) abstract note, I'm starting to finally develop some unified, confident outlooks on many of the programming ideas that I've been struggling to understand over the past two years. Building something as large as a game engine and game, especially when done alone, affords an incredible opportunity to see and try to understand general patterns in software architecture. Over the years I've come to better and better understandings of those patterns, oftentimes writing about them in the dev logs and performing the resulting 'code-ripping' to embody the ever-increasing elegance of my understanding of those ideas. Today I happened to glance over a manifesto of data-oriented design, and, despite my opposition to the near-religious zealotism of those who seem to be pushing this style of coding nowadays, some connections did start to click in my head with really, really general patterns that I've been trying to understand. Things like sparse properties, component-based composition, parallel processing, property lookup trade-offs (virtual tables vs. dynamic maps), easy serialization of pointer-laden memory constructs, etc. It all started to come together into a unified picture of something very beautiful. Now is not at all the time to explore this beauty. The LT Engine is largely finished, and I will perform no more gratuitous code-rippings. But the future is looking brighter and brighter as I accumulate ever-more ideas to bring to bear on future works (like LT2!
) My walk with code has been a long, sometimes-arduous, but always-rewarding experience. It's far from finished -- I doubt I'll ever be truly satisfied with my understanding of this elegant world of computation. But every year, at the very least, I'm glimpsing more and more of the underlying beauty and unity that exists somewhere out there in the ether of the code-that-could-be. What an exciting life. I really do love my job
(Again...got a bit carried away
)
PS ~ Only as I was writing the devlog did I realize that the insight implemented today actually
finally affords an elegant solution to distant object fading! Wow!! Can't wait to try it with asteroids ASAP!!! Awesome!