Tech Talk: Rendering in DT3K
I have long been fascinated with different pseudo-3D graphics techniques. If you don't know what this means, I recommend having a look at this wonderful post by the Ion Maiden team, which illustrates the evolution of pseudo-3D games leading up to the Build Engine. I will be talking a lot about Wolfenstein 3D, Doom and Rise of The Triad to get some points across, so if you don't know these very well, please check it out!
I also feel like we need to touch briefly on pseudo-3D techniques for racing games, which predate FPS games. There are those which I will call line-segment games, which draw a road made of horizontal lines starting from the bottom of the screen, shrinking in size as they approach the horizon, giving it the perspective of depth.
Pé Na Tábua, an older racing game project of mine based around line-segment rendering.
There are also those I will call mode-7 games, made popular by Super Mario Kart and its use of the Super Nintendo's capabilities of drawing flat textured surfaces which could be skewed and rotated.
Wacky Wheels: a Mario Kart clone on DOS.
Historically, racing games were never based around the solutions that first person shooters like Wolf 3D and Doom used for 3D rendering. They kept building upon those basic primitives of earlier racing games until making the jump to fully-fledged 3D geometry. There were two exceptions to the case that I know of.
First are Super Karts and Manic Karts, a franchise of racing games on DOS, which use a raycasting engine obviously similar to Wolfenstein 3D, where the game map is grid-based, all corners are 90-degrees sharp and the playfield is confined within walls. I find these games pretty fun and I believe the devs did a great job in creating interesting, engaging environments around these limitations, with clever use of floor and wall textures.
Then there's Quarantine, which is arguably the biggest inspiration for Death Taxi 3000, at least in a stylistic sense. It is a futuristic cab driving game for DOS as well, but with guns and loads of excessive violence. In that sense, it feels much more like an FPS with tank controls rather than a racing/driving simulator.
I did believe from my recollections that Quarantine was a Wolf 3D-like game as well, since the world map was grid-based and the buildings all seemed to have the same height. However, going through the game again I did find examples like the screenshot above, where you have surfaces of different heights stacked on top of each other and even 45-degree angled walls, leading me to believe Quarantine's renderer uses a sector-based approach like Doom.
So now that we talked about all those different rendering techniques, where does Death Taxi 3000 fit? Basically, think Rise of The Triad. It is not sector-based like Doom, but a beefed-up Wolfenstein 3D-style raycaster with tricks such as wall height modifiers, transparent textures, masked walls, lighting and fog effects and parallax backgrounds.
There is also one detail crucial to understanding DT3K's environments: the resolution of the tilemap is incredibly high. Each pixel you see on the floor textures is an actual grid unit. Unlike a Wolf 3D map where a tile is a cube of even dimensions, a tile in DT3K is much taller and narrower.
This design choice in particular brings the con of a huge performance penalty, as the raycasting loops -- where the game is not actually drawing anything, but calculating the distance of walls to the player -- take a lot longer due to the finer resolution.
However, I can partially work around this performance issue by having the game not have any sprite rendering whatsoever, drawing cars, street lamps, traffic lights and other map decorations as walls. Sprite rendering on a raycaster engine use up a considerable amount of CPU time as they are done separate from the rendering of walls, requiring the list of visible sprites to be constantly sorted for distance from the player/camera, then drawn from the furthest to the closest, usually with real-time scaling.
Not saying that trade-off is worth it for the performance alone, but for the type of game I wanted to make, I couldn't see myself working with "cardboard cutout" sprites for traffic.
Transparency and masked walls are very important tricks. To explain better this concept: masking is to walls as transparency is to textures. A raycasting loop needs a hard stop, and that is either an opaque wall or a distance limit. A masked wall does not stop the raycasting loop, it only interrupts it to draw a wall segment, and the transparent bits on the texture are not drawn. Then the raycasting resumes until it finds an opaque wall, and a mask buffer is used so that the background walls are not drawn over the foreground ones.
On this screenshot of looking inside a garage building you can see those tricks in action: there are parts on the scene where you can see the sky backdrop, while inside the actual garage you can see a color-filled roof. I achieved that by adding a ceiling bit to the grid data structure, which tells the game to draw the wall at half the regular height, and fill the rest upwards with the roof color.
Sorry for the older screenshots, this post has been drafted over a year ago and I finally decided to clean it up and publish it. If you made it this far, then please check out the latest updated shareware release!
Get Death Taxi 3000 (Shareware)
Leave a comment
Log in with itch.io to leave a comment.