Creating a Doom-style 3D engine in C

Creating a Doom-style 3D engine in C


In this tool-assisted education video I walk through the creation of a Duke Nukem 3D style (or Doom-style) software-rendering pseudo-3D engine from scratch. It supports non-Euclidean geometry. Topics such as vector rotation and portal rendering are at the core. SUBTITLES ARE AVAILABLE.

Twitter:
Patreon: (alternatives at
Twitch:
Homepage:

Contribute subtitles: or:

This homebrew software-rendering pseudo-3D engine bears many similarities to Duke Nukem 3D. The geometry can be tweaked at run time without performance penalties, to create things like ceiling crushers or rotating doors.
For rendering, it only supports single-color floors, walls and ceilings, with optional depth shading. Unlike Duke3D, it also requires that each sector is convex.
So far this engine does not support objects or sprites. It also does not support sloped surfaces or parallax ceilings.

DOWNLOAD MATERIAL:

SUPPORT / INSTRUCTIONS:

The C program must be compiled with a C compiler supporting the C99 standard. If you attempt to compile it as C++, errors will be produced. If you attempt to compile it on a C89 compiler, errors will be produced. You must compile it as C using C99 standard or newer (on GCC, use the commandline option: -std=c99 or -std=c11).

You also need libSDL 1.2. SDL 2.0 will not work. Add the options printed by pkg-config sdl –libs –cflags into your compiler commandline.

The BASIC program is ideally run in QBASIC or QuickBASIC 4.5. It will not work in QB64 without modifications, because QB64 does not support DEF FN. It will not work in GW-BASIC, because of the structural programming statements.

Music credits in order of appearance:
– Lunar: Silver Star Story – Lunar Traffic theme (Noriyuki Iwadare)
– Axelay – SPIDERS (Taro Kudou)
– Tales of Phantasia – Final Act (Motoi Sakuraba and Shinji Tamura)
– Tales of Phantasia – Ridge Racer (Shinji Hosoe)
All these video game songs have been transformed into OPL3 songs with homebrew tools and played through ADLMIDI.

Sorry about the fluctuating narration volume. I recorded pretty much every sentence separately over many days, and my microphone was positioned differently at different times, and sometimes it was day, sometimes night, sometimes I had morning voice, etc. I tried to compensate with both manual volume adjustment as well as running a compression filter over it all, but it was only after publication when I noticed how uneven it still is.

My typical workflow for recording the narration involves the following:
1. Watching some of the video
2. Writing into a text file what I would like to say (this file will also form the basis of closed-captioning later). Much of the text comes from the directing script that I wrote before I even began any video recording.
3. Speaking that dialog and recording using Audacity. I honestly try to speak as naturally as possible. If I stutter or mispronounce some part, as happens many _many_ MANY times with English (that whole language is a frigging tongue twister to me), I simply repeat the sentence or part of a sentence as many times as necessary until I get it right. Then I listen to it, and delete the flubbed parts until I have the best takes for that text. Typically this involves about two minutes of recording for every 40 seconds of narration. Sometimes I leave a particularly difficult part in out of spite even if it doesn’t sound fluent. Unfortunately having to do the recording in this manner tends to kill natural prosody. I do not use voice synthesizers for reference.
4. If the dialog is shorter or longer than the section of video I was planning this to be narration over, adjust something. From here the editing may branch anywhere, including things like changing the text, or adjusting the playback speed/length/order for clips, or even changing the source code (which requires a new round of video recording).
5. Go ahead in the video with step 1

For the record, my native language is Finnish. It has a small set of phonemes similar to Spanish or ancient Greek, and a similar rhythm of vowels/consonants as Japanese. This background is quite a disadvantage for speaking English, considering that a person’s ability to distinguish and to reproduce a language’s defining traits, such as phonemes, rhythm, accent and intonation, is mostly determined by the languages they are exposed to as a toddler.
So, if my bad accent disturbs your harmony, I urge you to disable the sound and use the closed captions instead.

100 Comments on "Creating a Doom-style 3D engine in C"


  1. For other humbled programmers that just watched this: "I designed and tested this program very carefully for days before I began recording the video, in order to avoid consuming video-time in debugging and in other uninteresting activities. Within the video, I just retrace the steps of creating the program in a natural and a structural manner, with mistakes mostly removed." – From a FAQ on one of his other videos. I'm still impressed, but I feel a lot less terrible about my own coding speed now. 😉

    Reply

  2. the map you designed hurts my brain because it could not exist in a real three dimensional physical space

    Reply

  3. Interesting, thanks for uploading!
    You're very hard to understand, though. Tip: if you turn down the volume so much you cannot hear the music anymore, you should still be able to hear the voiceover somewhat clearly.

    Reply

  4. One question: Which method are you following to draw the pixels in the screen? I mean, in the C code. Thanks!

    Reply

  5. Really cool, I've never ever attempted to build my own engine, instead relying on stuff already made like unity or löve but watching do this so apparently seamlessly and easily made me wanna try my hand at it, granted, as people in the comments pointed out you didn't just do this on your first go, instead going through the necessary steps and practicing before doing the final video but despite knowing I will fail miserably on the first couple of tries I wanna try doing this and seeing how it goes

    Reply

  6. Dude. I just found a new favorite Youtuber.

    I wrote a ray tracing engine like this back in highschool about 20 years ago. This was like a trip down memory lane. Not to mention you just helped me solve a 20 year old problem that I hadn't gotten past in my youth (the bit about the problems when wall segments go outside of the view frustrum).

    So thanks to you video, I'm going to revisit this project and finish it. Love the accent by the way.

    Anyways, you have a new subscriber for life. Cheers.

    Reply

  7. I understand the C syntax and keywords; I do not understand the math. I think I need to brush up.

    Reply

  8. Question. In your code, I notice that when you draw the walls, you are taking a ratio of a number and tz to figure out how tall to draw the sides of the wall and how wide the draw the top and bottom of the wall. I get why you are using 50 against tz for the y coordinates, but where did you derive 16 from for the x coordinates?

    Reply

  9. Vector cross product isn't black magic; basically what it does is give you a new vector that is perpendicular to the two input vectors…

    Reply

  10. "Im not sure how this works but it works, which is what matters" all the code I have written to this day

    Reply

  11. You are writing in real time, without any speedup? If this is the case, I am about to quit programming D:

    Reply

  12. This is my favorite video of yours. I always come back to this video to improve my own programming skills.

    Reply

  13. Hello Bisqwit. Your video is great!
    We're currently working on a Duke like engine for a school project and so far we've achieved to print the walls which are totally in front of the player. But concerning the partially visible ones, we find some difficulties to fully understand the clipping part. How do you define nearz, farz, nearside and farside? Since it is an approximation, are you sure that the result will always be exact?
    We also found 2 major bugs in your engine:
    _You can go through the walls if you run into their angles.
    _Sometimes random walls appear on the screen for a certain POV. Do you think it is due to the approximate clipping of partially visible walls?
    Thank you so much 🙂

    Reply

  14. Doom is actually just a 2D game that looks 3D. you have a 2D map and you display it a certain way for the 3D illusion. In Duke Nukem they took it a step further with the stairs which was another illusion. you just got "beamed" to another place on the 2D map without noticing it. also the rendering of the textures where rather simple in Doom since you cannot tilt your head the walls were easy since you just scaled the height for each column of the texture and many more… its great what they achieved back then. the perfect 3D illusion.

    Reply

  15. I wrote my first code when I was 6. It was in Sinclair Basic. I tried BBC Basic after that. This is what made me scared of being a programmer for many years, presuming I couldn't do it. Now I have been coding for 20 years, I know 10 different languages including scripting and cheekily adding HTML as a markup, because it follows the same principles of what I believe is coding. BUT….
    I see basic code, and I still run a mile. That is some horrific code to remember. The logic is so progressively linear that it's either genius to your mind, or makes no real sense. Thank the lord for modern languages.

    Reply

  16. It's just me or you finally didn't say why Doom needs this long BSP build (when Duke does not) and how it makes stairs not allowing for multi stair buildings?

    Reply

  17. "Creating a Doom Styled Game in C" goes on to reference or use duke nukem as an example

    Reply

  18. "if you are confused about whats happening please watch that part again" ummm….i dont think watching it again will help

    Reply

  19. This is the cool stuff that made me want to be a programmer. Then I found out most programmers outside of silicon valley just work on outdated boring business platforms all day and I lost interest.

    Reply

  20. Bisqwit: makes 3D Game Engine in 15 minutes

    Me: finds out how to make cube move after 3 hours

    Reply

  21. For an uneducated mind like myself all of this looks like black magic. Now i understand why some people believe the earth is plane

    Reply

  22. Can we hire you please for 7 minutes 23 seconds to implement in Zandronum all refeatures, which Doom community ever needed?:)

    Reply

  23. @Bisqwit please lower down the music when you edit your videos before upload. It is really hard to hear your voice over the blip-bloppig 8-bit chip tunes.

    Reply

  24. I am very interested in your education background, where did you acquire all this programing knowledge ?

    Reply

  25. You're not the dull one, Bisqwit. It's been very long since I've come across someone with such clear and concise thought. Thank you for this, and all other demonstrations you so religiously upload.

    Reply

  26. in basic you can draw directly to the screen like that without any library like opengl? The hardest thing about graphics is the pain in the butt of opengl and directx making you write 10 pages of shader crap to draw a simple rectangle

    Reply

  27. Amazing video, too bad I suck dick at math. Hahaha! I'm a terrible programmer, but I get a cookie for effort.

    Reply

  28. I know everyone here knows this but he is using sdl, which will use open gl if it can.

    Reply

  29. I made a BUILD clone in Flash years ago, but in my version I ended up rendering polygons with textures.

    Reply

  30. I keep finding that whenever I walk into a corner where two sectors meet you just pass through the wall.

    Reply

  31. A similar rendeing technique to the one demonstrated in this video was used in the Marathon games.

    Reply

  32. Perhaps that additional code for "clipping" addresses the vanishing point for the perspective view. I seems the vanishing point was rendering and then the wall continued past it. The clipping probably just removed anything after the vanishing point.

    Reply

  33. Hey, Bisqwit!
    Really nice coding video. Very inspiring. But I'm having a hard time trying to understand some parts of your code.
    For example:
    float nearz = 1e-4f,
    farz = 5,
    nearside = 1e-5f,
    farside = 20.f;
    Why 5 for farz and 20 for farside?

    Reply

  34. Bisqwit remember me a character from Hunter x Hunter, in Greed island, the videogame, 😛

    Reply

  35. Hey, man, I love your video!!

    Maybe you could give me a hand with a problem I'm having. I'm developing something very similar to your video. Most of the time it works pretty well.

    But, when the camera is on top of the line that divides two sectors, sometimes the camera aligns perfectly with the wall or window, and in that case, the window is either unperceptible or smaller that it should be because it gets clipped against the camera. So I don't have the "window" where to render the next sector.

    I've been trying some patches with different results, but I wanted to ask if it is a known problem, or am I doing something wrong.

    Thanks in advance.

    Reply

  36. Absolutly awesome content, but pipe down the music, we have a hard time understanding the content!

    Reply

  37. I'm confused by the values used in this video for hfov, vfoc, nearz etc. for examle what value is 1e-4f ? Don't get it =/

    Reply

  38. “How is life, family circumstances, and everything that is nice”. I didn’t after coming back a year later I finally understand what he said in the into.

    Reply

  39. Trying to mess around with qbasic to get a basic sense of the math before I try to implement anything advanced. When I run a program that has only the line
    VIEW(4,40)-(103,149),0,1
    interpreter fails with error:
    Syntax error at 1:6: Token(4)
    [13536] istatement: 'VIEW' . 'PRINT', 0, token=VIEW, prev=13490
    What gives? I assumed VIEW is a built-in? I also could not find much information on basic. Is there a spec/api anywhere?

    Reply

  40. i want to make this in visual c++ will be risky to "migrate" right? … did you make another "engine" in a modern languaje? .. PS: Don't apologize for how you speak english, for sure you speake more languages than many youtubers..

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *