Weekly Penguin
April 23rd, 2025

Shaders, shaders everywhere

I've been so head-neck-deep into The Next Game development I almost missed the fact that it's been a month from the previous update. So, time for another progress update focusing on a specific topic.

Shader architecture of the Next Game

One thing I've been asked previously is that how does TAGAP Engine manage shaders. Well, until the Next Game, the answer was 'poorly'.

See, TAGAP Engine wasn't originally designed for shaders. When I started, using pure OpenGL without any shaders was almost in every scenario faster than rendering through them. Especially so with non-state-of-the-art GPUs. This was 2007, remember. So, the original releases didn't utilize shaders at all.

TAGAP 3 was the first one to feature GLSL shaders, but only for special cases of colour manipulation (damage flashes, freezing enemies, etc.). There were so few shaders that 'managing' them was unnecessary; I could just write all the loading and compiling stuff to the engine directly without any 'wrappers' or the like.

TAGAP 4 started that way, too, but as I moved more and more towards modern shader rendering, adding new shaders on top of the TAGAP 3 framework became borderline unmanageable. Using the already-loaded shaders is relatively smooth, but loading them in? It's about 300 lines of code for 76 GLSL files. You load in the shader file with one call, compile it to a shader program with another and then fetch the locations of however-many uniforms they have.

As a brief explanation for the non-programmers; shader uniforms are basically variables that are passed to the shader by the engine – i.e. if you want a colour to blend by 50%, a uniform could be a floating point value of 0.5, sent to the shader by the engine. You need the 'uniform location' in the shader program in order to do it.

I already knew I'd have to completely re-do the system for the Next Game, as not only does it render every pixel through shaders like TAGAP 4, but there would be hell of a lot more of them. As of writing this, the GLSL file count is 254 files and rising.

So how is it managed? It's simply three steps:

  1. Detailed shader pointer library. Each shader has its own pre-defined (enumerated) place in the shader library. Each enumerated spot also has their own uniform information sub-library for fast reference. This has been in place since shaders entered the picture with TAGAP 3.

  2. GLSL uniform unification. All the shaders share the same exact uniform names. For example, all colour uniforms are useColour*. This way there is no need to have custom uniform location retrieval for each shader, instead using semi-automated location retrieval loops.

    This wasn't the case with TAGAP 3 or 4. A wrote the shaders whenever need arose and paid no attention to the uniform naming, assuming I would be fetching their locations separately anyway. Speaking of...

  3. 'Pseudo-header comment'.

    An example of a

    This is my own hack to simplify reading in the scripts and read their uniforms. Each GLSL file starts with a comment line that tells the parser the amount of uniforms of each type there are to fetch locations for.

    You could fully automate this by fetching the uniform list of the shader after compiling. However, most drivers' GLSL compilers will optimize away all uniforms that aren't actually used in the shader program. This can happen by a programming error and I'd rather have a proper compiler error message than see wonky results and try to troubleshoot it blind. If I see an error of the parser trying to find a uniform that doesn't exist, I immediately know something went wrong somewhere.

So what's the result? With only one 'Shader_Load' command, the shader is loaded to its enumerated slot, the parser populates the uniform information and then according that, the uniform locations are fetched. It's still 1 line per shader added to the shader initialisation – but not average of four as it was before. Currently that means 762 fewer lines of code than it would've been in TAGAP 4 version of doing this.

There is, naturally, the other side of shader management; actually using them. There are several layers of optimisation done to that as well, some of them thanks to the automation systems designed for loading them in, but those are easier to demonstrate with live samples after I've deputed what the game looks like.

What am I working on right now?

After finishing up with the basics of the alternate gameplay sound design and the basic wiremesh assets explained in the previous update, I've been doing a small round of prop building. Just background props, nothing more.

However, it led into an interesting discovery. In the previous blog update I mentioned how the wire mesh system was fit for far more than just wires. Well, turns out the code I did for it was so versatile that I ended up replacing big chunks of the engine code with it.

In TAGAP 3 and 4, there are wires hanging overhead that react to explosions and gunfire. Turns out I could replace the entire rendering system of that with that of the wire mesh.

Those curved tube limbs of the TAGAP 3 enemies, sometimes seen in TAGAP 4 as hoses or loose wires hanging from broken computers? Yes, wire mesh code does the same thing, but better, faster and more dynamically.

The only part I haven't replaced with it yet is the 'wavy flag' object, used for everything from flags to vegetation in the previous two games. It, too, could be replaced with it directly, but I'll cross that bridge when I get to it – as I have other shader tricks I'd like to try on it first.

So yeah, within a month I managed to almost accidentally optimize and trim the engine of the Next Game hell-of-a-lot, thanks to an accidental realisation whilst setting up a loose electric cable.

Playlist

Playlist is a regular feature in our Penguin DT blog; A chance to highlight cool games both old and new that I've been playing. As always, I believe that in order to make games, you need to play them, preferably with a broad scope when it comes to genres, so each day I dedicate at least an hour to actually playing games. The rest of the free time? There is no such thing, it all belongs to TAGAP!

The 1-for-1 of going between 'old-gen backlog' and the 'next gen backlog' continues. These won't be in order, but still, you get the picture.

One of the next gen titles you may have already seen: Ufouria The Saga 2, aka the Weekly Penguins 921 and 922. I already did a write-up there so I won’t copy-paste it here.

As for the rest, I've been through quite a lot of games, so I'll do it in a properly organised list form for once.

  • Alone in the Dark (Pieces Interactive / THQ Nordic)

    The absolute highlight of this batch of games – and my PS5 experience as a whole so far – is the new Alone in the Dark. As a fan of the series from the days of the original trilogy, it is everything I wanted from it and perhaps even more.

    The new AITD manages to recreate the atmosphere of the first game, but with modern mechanics. And by that I don't mean 'yellow paint', but proper 3rd-person controls and combat system that isn't the clunkiest thing on the planet. And no, the game is an action game by any means, in fact some of the mechanics are more for escaping the combat and run from the horrors.

    Besides, you'll likely end up investigating clues more than fighting enemies. It's a big part of the game and its atmosphere. Reading diary entries, articles of forbidden knowledge, patient records, etc. – most of it is part of a puzzle somewhere. It may not be for everyone, but to me it really enhanced the investigatory vibe of the story. And fear not, if reading tons of text from the screen is tough to your eyes, every clue can be played back as if read by the note's / article's author.

    Fantastic art, great acting and characters, brilliant writing, tasteful reimagining of the classic and a delightfully presented 1920s Lovecraftian setting.

    Go grab it!

  • Space Marine II (Saber Interactive / Focus Entertainment)

    It was... OK? The art and the scale of the battles is impressive, the story is great and seeing Titus in action again warms my cynical heart. However, it is also a co-op only title, to the point it tries to push you to getting a console subscription every time you boot it up. If you say 'no' like any sane person would, you have to deal with bots you can't give commands to. This results to me having RE5 Sheva Alomar flashbacks (if you know, you know). The combat on higher difficulty settings is rewarding, but near impossible when the enemy waves have been designed for competent players, not the bots whose only sure-fire function seems to be reviving you when you fall.

    So if you do multiplayer, then it'll be fantastic. If you prefer single player, it is still decent, but will remind you of the not-so-great parts of Xbox 360 era gaming. This makes me really worried for both upcoming Saber franchise resurrections – Painkiller and Turok – as both are similarly co-op only with some obligatory 'Alomars' for SP folks.

  • Journey to the Savage Planet (Typhoon Studios / 505 Games)

    Finally there was The Journey to the Savage Planet. It was meant to be the 'old gen' title, but it also has a free next gen upgrade. I don't know if there's any real difference, as the game is very stylized – in a good way, mind. I can't remember the last time I laughed this many times during a game thanks to its writing and performances – it's really damn well written and funny game about being an employee in one of those big sci-fi movie space corporations.

    The game is great time, too. It's basically an open world metroidvania-lite. Is that a thing or did I make it up? Anyway, the bizarre and surreal world opens up more and more as you research more tools and investigate the environment. Now I'm really curious to see the sequel. So glad to see this up-and-coming series didn't die when the devs got completely screwed over by Google (the studio was among the ones who joined Stadia thanks to Google's kaiju-level promises).

  • Graven (3D Realms)

    Oh, almost forgot this one, even though I mentioned in the previous blog. The first act is beyond fantastic, the second has some rough edges but is still great... and the third broke everything. No, really, the AI stopped working the moment the level loaded and the quests failed to complete. And thanks to everything these days copying Soulsborne bollocks, Graven too has no multiple saves, just the one continue slot, meaning that was that. It's a lengthy game and no matter how much I loved the opening acts, I don't really care to replay them all and risk the game lobotomising itself again.

    I'm beyond sad to see the game go down this way, but it was one of the multitude of victims for the Embracer Saudi gambling fiasco from some time ago. At least this one saw the light of day in some form, unlike Deus Ex which was killed for the third and final time by greedy corpo BS.

What's next?

The Next Game; Doing a proper inventory of what needs to be created for the game to be revealed. I have insane amounts of content, but there are still a lot of elements lacking for making full scenes I intended to use for the debut trailer. It won't be for TAGAP Day, but there is hope for the Second TAGAP Day in November.

On Playlist; Continuing the 1-for-1 style seems to work. I have two piles set up to pick games from at random, so we'll see what comes next!

Until next time,

Jouni Lahtinen, the head penguin