I thought I'd give a bit more of an update now that I've returned from a short "break". Unfortunately, I've had to pay some bills these last few weeks so I wasn't able to make much progress, but while I was working on other things, I've been thinking about how to handle the Vulkan renderer moving forward.
When working on something like this, the main goal is just to get it to work and then iterate on it. Well, I managed to get it to work. Sortof...
It was mimicking the surface blitting from SDL with some fairly basic shaders. I even went so far as to make the texture coordinates as integers instead of floats, using a fixed sampler, and then I was able to pass in the same coordinates from before and it would render the text, windows, and so on. Palettes were handled by uniform buffers and the palette ID was passed in as part of the rendering pipeline. I even went so far as to fix the aspect ratio in the game surface to windows surface shader.
However, the structure of it all bothered me. It wasn't very flexible and it felt a little like I was cramming functions into objects just for one single thing. That's not good design!
So, I've started cutting it up into smaller and smaller bits. While I'm at it, I want to make it API agnostic as well. If you want to render using DirectX12, that is something someone else can handle, but it should be possible.
Why go through all this effort? Easy! In the process of creating the new renderer, I've created a handful of "managers". Under normal circumstances, I don't like calling things "Managers". The term itself is ubiquitous since technically everything you write in code manages something, but it actually makes things super easy to manage resources. I'll hold my disdain for calling things Managers for now, and I'll just tell myself it sounds better than calling it "System". However, I digress. So, with that out of the way, practically every resource gets it's own data type and manager. All the Windows, Buttons, Text Boxes, Images, Palettes, Fonts and more! When I get to Battlescape, I'll be repeating the same pattern.
For instance, the base game only had 3 fonts that I know of. There's the DOS font that you see at the startup of the game while Mod.cpp loads, then there's the two in-game fonts(Large and Small). Now, I've got a FontManager. You can register your own font, complete with multiple pages and unicode support if you need it. Using the Large or Small font is still there, but now they are explicitly used by their handles. Also, I've kept the "turn big font into small font if it doesn't fit onscreen" for now, but I'm seriously debating if I should keep it in. Anyway, I digress. With the FontManager, I can now tie that into the entity inspector and scripting to allow me to register and use my own font if I want to.
However, one thing that struck me while I was doing the Window Manager is that I can now allow modders to create their own custom frames. The old way of drawing the frames was to use FillRect with preset values. With Vulkan, that doesn't work so well. I mean, you CAN do it, but I didn't want to. Vulkan works best if you create resources and then upload them to the GPU once, and only once. Draing the frame using FillRect is possible, but since the frame itself is animated when popping up, I didn't want to have to push up images every frame when I could just pass up coordinates. I can just upload a texture, specify the 8 cardinal and diagonal directions, then render those at the window coordinates. Instead of hardcoding that 5x5 corners, and the 5x1 sides, and 1x5 top and bottom, I can just let the WindowManager create the frame and the WindowFrame can be driven by the data. Data, as you can probably guess, can be modified through mods.
Why this long-winded explanation? Well, it's because in the process of redoing all the Window stuff with the new Vulkan images, I realized that a dedicated modder could use this framework to simply replace the border texture by specifying a file and the coordinates, then they can have ornate frames around in-game windows. Cool, eh? (I know, not the "killer feature" for this branch, but I thought it was nifty)
I'm going to spend a little while longer on Vulkan, mainly because I still have a week or two of real work to pay the power bills, but also because I'm having a bit of fun with it. I really enjoy trying to make the interfaces as elegant and clear as possible, and being distracted by real work has given me the opportunity to really just slowly refine what I have into something much cooler!