Well well well. Seems like it’s time for
This was not easy, and yet it was made so much easier by having done it once before last year. I added support for a directional light, a dynamic (aka not hard coded, so pratically infinite amount of) point lights and spot lights, full PBR, and I also made a little handy editor to go along with it, although that’s not in the renderer that’s just in the demo project. Anyways, this was an incredible journey filled with pain and suffering like never before, and I’m so glad I’m through it all.
And if this was a challenge, I don’t know what shadow mapping is going to be, which is going to be basically right now, I’m going to add tanget space normal mapping and then it’s already shadowmapping. I’m mentally unprepared, but oh well what can I do?
This change is not too visible, but it is a major change in the engine
Everybody who worked in any sort of 3D graphics knows what materials are. And those know, that the next step after this is lighting. This wouldn’t have been that big of a change, if not for one issue. I’m developing on linux, and every once in a while my GPU drivers uninstall themselves, so everything runs on the integrated graphics on the CPU. That happened, but I thought that the code just became really slow because I was sending 6 images to the GPU every single frame, and that slowed it down. So I spent a bunch of time making a large optimization, and it worked like a charm, it ran fast. Then I found out the entire thing was running on the CPU and I didn’t even need to optimize it. Anyway, it’s here, and it’s fast
This is the finale to the post-processing saga, because I’m finished with tonemapping and color grading. Everything will look really good and cool and whatever, altough I’ve been coding non-stop for 2.5 hours and I don’t really care to give an explanation right now. I don’t have to explain color grading everybody knows that, and tonemapping is the process of mapping the internal HDR render image to an LDR (whatever it’s called) image that the display can actually render properly, how cool is that?
I’m almost done with all of the post-processing effects, and this was by far the hardest of them all, but I managed to push through it. I’m really proud of myself, because I finally understand Vulkan enough where I didn’t need any sort of outside help to debug this error. I think I can finally call myself someone who understands Vulkan now. Anyway, now I just need to make tonemapping and the effects are done. After that I just make the simplest pipeline to composite it all, and I’m done with that as well.
This was the most fun I’ve had debugging something in a while. This was really simple to implement, although I can’t really say a lot. The initialization was the same as the other effects, the actual logic of it was pretty similar, the shader wasn’t too hard to write too, but added up it was pretty bad. I accidentally left one of the push parameters in the CPU code as an int, but a float in the GPU code, which I ended up having to chase down for quite a while. The values are over the top on the image so it is more visible on the screenshot, of course I won’t leave it like this.
I just kinda wanted to, and thought why not?
I have to admit this took 11 minutes, and the rest of the 5 minutes I spent in this devlog was spent debugging 3 new errors so I can make a post about this feature too. It took so little because I literally just copied and renamed the gaussian blur functions, and changed the shader. Still, I have box blur now. Actually, I think there’s quite a difference between the 2 blurs, quite cool. Of course now that I look at it it’s barely visible in the screenshots.
I thought how cool would it be if I just did a whole 10 hour devlog with all of post-processing in it, but I realized I wouldn’t be able to show off all the cool stuff I’ve done, so I’m doing it effect by effect, anyway,
But not just that, I also brainstormed out the entire post-processing system, and “implemented” it. I didn’t exactly implement it yet because I need to finish all the effects, but it’s there. I still have to finish: box blur, bloom, vignette and tonemapping, and I also want support for custom effects, but that’ll be really easy so I don’t want to put it on this list.
I always viewed anit-aliasing as this mystery thing that can make a game prettier and I’ll never know how it works. I have to say, it was way easier than expected, most of the time I spent was on some stupid bug or general debugging. You can’t really see the difference in a small screenshot, but it looks so much better full screen.
I have to admit this feature was kinda easy to implement, because most of it was ripped straight from my last game engine, but I did it because I think it is a really smart way of handling how a 2D system should work. Everything relies on the Surface class, the display itself is a surface, the loaded images are surfaces, and those surfaces can draw to eachother. This makes the system easy yet expandable. I think it’s kinda cool. It was heavily inspired by how pygame does things.
And just like that, the next major update is done!
and I have some great ideas for it
This is a change that cannot be seen, but the composite pipeline is actually working. This is a really simple step in the graphics pipeline, it takes the images from the previous passes and combines them to make a final image. This will be useful for future features like 2D drawing, post-processing, the skybox, etc., so I’m happy I managed to implement it. It’s not something that can be seen with the naked eye, but believe me it’s there and I’m so happy for it.
As always, this is next to some generic bugfixes here and there, but it’s been 1.5 hours and I forgot what I fixed and what I didn’t so if you happen to care enough this is open-source just like go and check it out.
I’m well into developing the skybox system along with a compositing pass, but since I needed to write so many new shaders for this update, I decided to write a simple shader compiler, and I kinda want to show it off so it’s not lost in the giant list of changes that I’ll push in the next update. That’s it, I rest my case, that’s all I wanted until I’m finished.
You’ve probably seen this feature in some random wannabe gamedevs post on tiktok saying how they “optimized their game” by enabling frustum culling in Unity and calling themselves genius for it. Well it wasn’t as easy as pressing a button for me.
I generate an axis aligned bounding box (AABB) for every object when loaded. Every frame I generate 6 planes for each boundary of the camera, the left, right, bottom, top, near and far planes. Then I also calculate the world position AABB for each mesh, which is just translating the original AABB and making a new one from that’s boundary. From that, it’s actually quite simple to compare if the box is inside the frustum or not, though it’s kinda hard to explain so I won’t bother, but I just run that for every object,
and it basically makes it, so if an object is not inside the camera’s vision, then it just makes it disappear.
I implemented a fully automatic mipmap system. Basically, mipmaps are lower quality version of a texture that appear the farther you are from an object. The image I attached is of mipmap layer 4, but of course this was set manually to showcase the system working.
I wrote a giant list on what I want to implement into this framework to make it full. I’m pretty sure I’ll be done in about 150-200 hours, which I have about 40 days to make before the end of this thing. That is 3.75 - 5 hours of coding in a day. Anyway, here’s the list:
TODO FEATURES:
I have to admit I’m pretty proud of myself. I implemented the proper transformations for objects, I also made a good camera system, and I fixed the uv mapping of objects, so textures finally work properly. All this in under an hour.
To be completely honest this engine development thing is going a lot more awful than I could have imagined. I tried to implement a proper camera and transformations for the objects, and now nothing works, yet I barely changed anything. I have been staring at this function for like 2 hours, I’ve tried everything, and nothing works.
I finally finished the guide (🥳🥳🥳), so it’s time to make the game engine I want. My first improvement was adding a render queue, which basically means I can render anything in a much user friendly way.
Thanks to the major rework of the allocation of descriptors, I have
managed to implemented textures into rendering. I haven’t made
texture loading yet, since it’ll be an engine feature and I’m working on
project setup, so enjoy the beautiful pink-black checkerboard pattern
on Suzie, the Blender monkey.