Concerning: Mental roadblocks

Productivity down the drain, or rather, into the fog

This one isn’t particularly interesting, has no technical tidbits in it. I want to write about something that’s been pestering me for a while.

Work has been progressing very slowly over the last couple of weeks, on average almost imperceptibly. It is a source of frustration for me everytime I experience such a slowdown, for one reason in particular - I feel like it is impossible to me to both identify the cause behind it and even put into words what this slowdown could possibly be caused by. Even now, trying to properly describe the issue at hand in a relatable manner simply causes my mind to repeatedly go blank. Despite this weird ‘obstacle’, I figured I’d try to deconstruct some hypothetical causes.

I’ve discovered that in some cases, the simple act of writing helps by introducing some structure to my thoughts and actions for some time. This should be no surprise to anyone - to transmit thoughts, they have to be formulated and molded to fit the target medium as best as possible. That effort in itself serves as a filter on a lot of mental or emotional noise one might be dealing with on a daily basis.

This piece is not structured in any meaningful way, mainly because I do not know where the shape of the problem starts. Let me instead focus on two specific instances of mental roadblocks that I encountered recently. I think they are similar in their foundations, but each evolves in a different direction to arrive at unique surface conclusions.

The first one pertains to implementing shadows. The whole process, from deciding to focus on them, to actually obtaining a working demo, took nine days. Seven of those were spent just fumbling around either reading internet articles related to the subject or looking about in the implementation of the renderer, for a couple minutes a day. No practical decisions or coding was done in that time.

The second one is related to the map editor, specifically to representation and manipulation of geometry. Knowing that I’d like to introduce constructive solid geometry and support for boolean operations on it, I started looking into concepts old FPS engines have done things with - specifically, brushes. A similar process, as was the case with shadows, was undertaken here as well - many days were spent on researching prior material, looking up references, reading the code for Trenchbroom, etc. This is still ongoing; I’ve recently given up on the original idea of brushes and decided on a workflow involving meshes processed into hulls, with the in-game editor facilitating very primitive manipulations of those, at least in the beginning.

What these two instances, and many before them, have in common, is the period of confused marination over source material. Judging solely based on what I’ve written so far, it might sound like I was simply spending time on learning about the subjects involved, but this conclusion ignores the struggle. I’ll try to describe what was going on in more detail.

Even before the moment when I decide on what part of the game or the engine to focus on next, there is already a vague idea in my head regarding what shape a particular new feature might take and how to implement it. Usually, the less vague this idea is, the higher the likelihood of successfully implementing it quickly is. It is, however, hard to notice this vagueness or fuzziness at first. Things seem simple, problems and inconsistencies imperceptible. Soon after starting, however, it becomes clear that the initial ‘simple idea’ doesn’t really fit either the engine’s current, nor any satisfactory new model of implementation. Usually either the data doesn’t fit together, doesn’t cover all the nominal or edge use cases or the algorithms involved require a lot of wrangling spaghetti.

Being an avid fan of the Wookash Podcast, the original Handmade gang and other usual suspects over the last year, over time I became quite aware of various shortcomings of my code and of my skills as a programmer. I started noticing what looked like unnecessary complexity in many places in my projects and became annoyed at how rough my tooling is around the edges. It’s hard to appreciate the effort put into constructing ‘proper’ and technically useful abstractions, when some indies roll out complete games based off of a couple arenas and a couple single header libraries like Sean Barrett’s. It’s even harder to ignore the difference between fifteen second long recompile-and-test loops when comparing them to, quite literally, Up + Enter + F5 to recompile and run a game in almost a split second, which is what Jonathan Blow presented on his Jai/game programming streams.

Comparison is the thief of joy. When I fumbled around with Godot a couple years back, preparing a simple 3D FPS demo, I’ve done things in ways that were straightforward to me at the time and, looking at that code now, I can’t help but wonder how anything worked in there at all, with the peformance that it did. On the other hand, looking at Chavelleh now, I’m worried I’ve fatally overcomplicated it before I had any real use case in hand.

These doubts seem like primary suspects that slow me down to essentially a halt for days at a time. I’ve spent more time wondering whether I should port the engine to C, C3, Zig or to wait for Jai than actually implementing any useful features. I searched for Blow’s e-mail address in many places, to ask for access to the beta, with no success.

This form of FOMO compounds on the confusion caused by overly ambitious plans for first implementations. I never developed a habit of starting with naive approaches. My mind immediately attempts to construct a complete solution, including coverage of all possible edge cases. The moment I realize there is no such solution, that is simultaneously ‘clean’ and ‘general’ or ’extensible’, work grinds to a halt.

With shadows, for example, there is a difference in how shadow maps are generated for directional and for point lights - the former requires a single map, the latter builds a cube map. The fact that they would need two different ways of representing and handling that data - that the shaders would have to be very fundamentally aware of those two types, because they require different types of samplers - made me feel a fairly unique type of anxiety and contempt for any solution involving shadow maps, because of how hard it was to generalize it. It was only after I ’negotiated’ with myself to start with directional lights and see about resolving this problem later that I’ve managed to sit down and just bang out code for two days to produce a nice looking demo.

It seems that I have developed a ’taste’ that not only does not produce very efficient results, but also prevents me from obtaining any results at all at times. It is said that the perfect is the enemy of good; that piece of advice seems very fitting here, but to me it is unacceptable, for two reasons. First, ‘perfect’ isn’t a goal or an objective, but a direction, or a process. Reaching a ‘perfect’ state is most often impossible for humans, because, as I see it, introspection is natural to us and it causes the goalposts to constantly move. Without accepting that it is impossible to reach, it’s easy to get bogged down in details and form some ’toxic’ mental habits that harbour procrastination and self-doubt. [Notabene, I just now became aware how ironic this description is.] Second, I am maybe overly aware of the dangers of accepting what could be considered ‘good enough’. ‘Good enough’ is the cornerstone of the capitalist product-first mindset that gave us so much awful software over the last twenty years. For me, this endeavour isn’t a career; I do this out of passion and as a form of rejection of that acceptance of mediocrity. People using my software deserve the best I can give them and while I certainly let myself slip quite often and do not put enough attention into practices that could be constituted as ‘giving my best’ a lot of the time, I like to hold onto that narrative to serve as a guiding light.

As righteous and inspiring all that might sound, it likely reinforces the mental barriers that prevent me from just programming things. I do not know how to square this circle. I want to be a good programmer, I suppose; I want to believe that I am. It is likely that until I get rid of that desire, progress will be stuttering a lot.

If you know the address to send a question about the beta access to or have direct or indirect access to the compiler itself, I am willing to deal in golden shekels. Even knowing that its the bad workman who always blames his tools.