Making a 3d, game in assembly Spring and Summer 2020
I changed the lane markings to be drawn by a pixel shader instead of separate vertices. This ended up looking a bit better, but it had some aliasing issues as can be seen in the video clip below, but this was fixed later on.
Now it was time to introduce cars to the game so I had to implement some sort of 3d model rendering in my renderer for that. For this I made my own pipeline for loading 3d models.
I wanted my low poly models to be rendered without any textures. So the colour would have to be stored for each vertex as a vertex colour. I had already done it this way with the roads, terrain and water that are generated from code.
I Used the .ply format since that was the easiest format to parse due to it being available as a text format, and it also included vertex colours.
Since I only use static memory in the game I did not want to dynamically load any models into the game. Instead I made a script in C# that parses .ply files and saves them as a .asm file. This file includes all the vertices and indices for the model in the way my render engine reads it. Then this file just needs to be included and then I can start using it in the code to render it.
Then I implemented shadows using a shadow map. This was quite a big hassle to get working but after much debugging and frustration I got it working. The Nvidia Nsight Graphics debugger was my best friend during this. I set the projection matrix for the light to only fit what is visible from the camera. This keeps the shadows looking good when looking down on the ground. However when looking towards the horizon the shadows are very low res since the shadow map resolution is not high enough to fit everything visible to the light at a good resolution. I plan to fix this in the future by implementing cascading shadow maps, but that will be looked at in a future post. The video below shows the 3D model of the car in the game together with the shadows. You can see how the quality improves when looking down on the ground compared to when looking more towards the horizon.
Then I started working on path finding for the cars. For now I have implemented a simple depth first search for a path between two given nodes. This will only find a path and not necessarily the shortest one. I also added spawning of cars with paths between two random nodes of four nodes. This would allow me to start working on traffic behaviour for the cars. The video below shows a demo of the path finding behaviour of the cars.
Then I worked on the sky. It is just a simple sky quad. It follows the camera when it is moving and rotates so it is always in front of the camera and therefore unaffected by its movements. The sideways rotation is cancelled out by removing it before creating the view matrix. Also the translation of the camera is removed from the view matrix for the quad. I had to add a bottom quad to not have the background be shown, since the edges of the quad became visible when rotating the camera up and down.
The sky also needed a sun which took lots of work to get working. Spent a lot of time trying to get the perspective to work as I wanted when the sun was at the edge of the screen. But due to how field of view works and that the sun can’t really be at the far away position that it should be I had to settle for some weirdness. The same issue was in Minecraft as well and I had never noticed it before now, so it will most likely be fine. The sun shader was hard to get decent looking. The key seems to be pow and distance from the centre. I leave a video for you below showing the sun shader and a little bit of the sky quad.
Then I implemented an axis aligned grid for keeping track on where the cars are in the world. This was used for interaction between cars so I only need to look at the grid squares around the car and see if any other cars are there instead of looking at all the cars for each car. So each frame a car looks at the grid squares around its own square if there are any cars on them, and if it is it checks if it is in risk of colliding with it. If the car is in collision course to another car it then brakes at the appropriate time to avoid the collision. I have a debug view active that shows the collision grid in the video below. Any squares that are free are white or black in a repeating pattern to easier see the grid. The squares that are taken by a car are red and the squares that a car “sees” around it are blue.
During this time I also had some trouble with the large static arrays with the Microsoft assembler. The assemble time is increasing exponentially with the size of the arrays which is really weird and started to cause build times above 15 minutes for what used to take less than a second. This bug seems to be looked at by the visual studio team. For now I have moved that code to be assembled with NASM which does not have any issues whatsoever with the large static arrays and assembled them in an instant. For more updates follow my twitter or subscribe to our Youtube channel.