• Ever wanted an RSS feed of all your favorite gaming news sites? Go check out our new Gaming Headlines feed! Read more about it here.

ghibli99

Member
Oct 27, 2017
17,700
Good stuff. Thanks for always putting so much effort into your posts!

I do have fonder memories of Wolf 3D, which was so impressive to me in that even back in the early '90s, a game like that could run on potato PCs, and do so so smoothly. First time I played it was at a local BBS user party. That memory is burned in my brain.
 

Malawhur

Member
Oct 27, 2017
175
Man now I want to dive in to that code and learn as well but being very much time constraint, I know I won't go far. But this was a fantastic read, thanks for sharing!
 

powersurge

Member
Nov 2, 2017
925
Pensacola, FL
Agreed. Just looking at the mods being produced for Doom on the various source ports of the game just shows how good this engine was.

You have people making Sonic fan games, racing games, games in games and so much more in such an old engine. It is truly an amazing engine and John Carmack was a genius for coming up with something like this.

I know its nuts how good some of the mods that are still being made for Doom look. I saw this pop up in my youtube recommends list the other day and it looks awesome:

 

Mars People

Comics Council 2020
Member
Oct 25, 2017
18,181
using things like the screen's refresh rate to tie to logic
It blows me away that to this day there are some games that still do this.
Why would you do this!?

Sorry we can't get Okami running faster than 30fps because the framerate is tied to the game logic. The fuck would you build it that way?!
 

Bjones

Member
Oct 30, 2017
5,622
I've always loved pointers in c . I don't know why all these higher level languages didn't use the same set up. You can easily clone data in c. &pointer gets the address. *pointer gets the value. So simple.
 

Deleted member 17210

User-requested account closure
Banned
Oct 27, 2017
11,569
Doom melted my face in the 90s and this thread melted my face today. Well written, OP.
Yep.

Doom had such an impact on me. Getting a 486 computer at home in 1994, and then playing that game every day for a year was awesome. That combo of technology and game design almost never comes along. I remember being amazed it originated on home computers and not the arcades. Doom also permanently re-wired how my dreams work giving many of them a CG video game quality they didn't have before despite playing many 3d games years earlier.
 

TeenageFBI

One Winged Slayer
Member
Oct 25, 2017
10,225
I've had a few mind-melting gaming moments in my life.. First time seeing F-Zero in motion, first time seeing Mario 64 in motion, first time playing Elite: Dangerous in DK2.. But nothing compares to Doom.

I had a 386 at the time and I wasn't tapped into the zeitgeist or whatever. I read a gaming magazine or two but I didn't know anything about Doom. I knew id from Wolfenstin, however. So when I logged in to a local BBS and saw a shareware demo for id's next game, I knew I should try it. There were no screenshots or anything resembling a synopsis.

Jesus Christ. How in the name of fuck was I seeing these things on my screen? Surely my semi-shitty 386 was possessed! And not only did it look amazing, it played just as well!

Doom was also the first time I tried online gaming.

Been into FPS games ever since.

Thanks for the lovely thread.
 

RedSwirl

Member
Oct 25, 2017
10,050
Now compare it to Ultima Underworld 1, which came out a few months before Doom, was actually 3D, and the demonstration of which at least partially inspired Carmack to do Wolf3D.
 

Deleted member 17210

User-requested account closure
Banned
Oct 27, 2017
11,569
Underworld is also an incredible game and engine. And it's arguably the first immersive sim depending on your definition.
 

TeenageFBI

One Winged Slayer
Member
Oct 25, 2017
10,225
Now compare it to Ultima Underworld 1, which came out a few months before Doom, was actually 3D, and the demonstration of which at least partially inspired Carmack to do Wolf3D.
I remember seeing screenshots in a magazine ad that looked very impressive but the game was never mentioned so I assumed it looked too good to be true (misleading screenshots were very common in my experience).

I really liked it when I played it WAYYYYY later.
 

capitalCORN

Banned
Oct 26, 2017
10,436
Now compare it to Ultima Underworld 1, which came out a few months before Doom, was actually 3D, and the demonstration of which at least partially inspired Carmack to do Wolf3D.
Doom's forte is that it's best in class. It is speedy as fuck while supporting large areas chocking with actors, dynamic lighting and even offers perspective correct textures.
 

Fanto

Is this tag ok?
Member
Oct 25, 2017
11,863
I just wanted to echo others who are saying thanks OP for making this thread and your many other ones like this, they are always amazingly insightful and get me excited about programming.
 

Skunk

Member
Oct 28, 2017
3,065
Doom's game design IS great, I really miss that kind of very speedy, fast, arena FPS that doom created and Quake 3 perfected. But sadly, that sort of game design has gone out of favor. I wish it would come back, personally. In contrast, the design of Doom's engine remains foundational. Game engines are still built in the mold of Id Tech 1. You can trace pretty much everything every modern game engine does back to Doom.

So while it's a great game, and I 100% don't disagree, the engine itself has had the more enduring legacy. The engine changed the entire video game industry forever.

I would comment that the Doom remake (and soon, Doom Eternal) has been pretty damn successful, and IMO while it has some modern shooter set dressing (like setpiece moments, glory kills, a codex, etc) to make it feel current, it's moment to moment gameplay is firmly, firmly rooted in the days of arena shooters with its frenetic pace, movement agility, lack of weapon reloads, weapon design, weapon variety as opposed to carrying two, enemy behavior design, and level design (though level design does have *some* compromise between modern and old school, and possibly a nod to Gears' "combat bowls"). I definitely feel think it feels like a game out of time, one that continues where Quake 2/3 left off and largely ignores the ~15 years of Halo/CoD influence permeating most modern FPSs. Wolfenstein TNO/II does too, but if Wolfenstein has a foot back in the games of old, Doom reboot is waist deep.

Edit: Also, this thread is just as wonderful as your other ones, thanks so much for sharing your insight with this community.

Edit 2: I wanted to also say that I understand Doom reboot's multiplayer was a bit less well-received (I only played SP) and in the context of "arena shooters" being predominantly multiplayer, it's maybe less of a successor to those than how my original comment could be inferred from. But I would clarify I still feel Doom 2016 borrowed more from Q3s movement and pace than anything before or since Q3. Forget Doom 3 or RAGE or anything else, Doom 2016 *feels* like the game id would have made after Q3, only 20 years later and with shinier graphics.
 
Last edited:

Nali

Member
Oct 25, 2017
3,649
I could listen to John Carmack talk about anything forever, and I could listen to people talk about John Carmack forever.

Wolf 3D gets credited for being the grandfather of the genre, but even that game is id's third take on the formula, after the glorified prototypes that were Hovertank 3D and Catacomb 3D. And those were just a couple of the half-dozen or so games they cranked out for Softdisk in 1991, on top of the second Keen trilogy for Apogee. The speed at which id was iterating on both design and technology at the time was insane, and DOOM's polish and sophistication is as much a testament to how they finally slowed down and took a year and a half to make it as it is to the improved hardware of the day.
 

scitek

Member
Oct 27, 2017
10,054
Cool read, OP. Thanks.

I remember seeing it for the first time on my friends PC and I had only experienced consoles at that point. I just couldn't believe it. It seemed so far beyond any tech I'd experienced I felt like I was time traveling.

Yep, my friend got a PC with a Pentium inside, and it had a digital LED on the front that said 90 for all 90 MHz that bad boy was clocked at. It ran Doom like a dream, and my crappy 286 couldn't. :(
 

balgajo

Self-requested ban
Banned
Oct 27, 2017
1,251
I'm sure a lot of people are like, "yeah, of course, all FPS games after took inspiration from it" but that's underselling what Id Tech 1 did. The things the doom engine did go well beyond FPS games or even rendering graphics period. Doom laid the foundation that virtually all game engines today descend from.

Several years back, Dreamcast scenester and general amazing dude ChillyWilly had ported Doom to the DC, but his old code no longer builds because of various changes to the KOS library that powers the port. Because of this, earlier this year, I took my first stab at porting doom to a platform:

D9BpcGIWkAAHIiR


I began with ChillyWilly's port as a base, then worked backwards. I have worked with modern engines over the years - Source, Unreal Engine 4, Unity - but never really dove deep into how Doom worked. That's not to say I was unfamiliar with Doom, I had been making Doom WADs for years, so I generally knew of things like BSP and lumps, but not really how any of it worked. Around the same time I began porting doom, I also picked up Fabien Sanglard's Doom Engine black book. This was not the first blackbook I'd read. I had read the Wolfenstein black book prior, and years earlier, when learning graphics programming, I read Michael Abrash's Graphics Programming black book (which is, really, the Quake black book). Most draw a linear path between these 3 games: Wolfenstein -> Doom -> Quake. But that really undersells how it all progressed. Things I had thought Quake had come up with, actually came from doom. Further, I learned that Doom and Quake share much more in common than Wolfenstein and Doom share in common. One thing dawned on me: To study Doom, is to study how modern video games work. Doom is, IMO, the very best place for anybody to start if they want to know how modern video games function and operate on a conceptual level. So much of what Doom does directly applies to modern engines.

With interest in Id Tech 1 growing, and a project in hand, I started where most doom ports begin: converting the 4 main files that are platform dependent. Doom's engine is genius, honest to god genius. It was built with cross platform compatibility in mind. The platform most people play doom on, IBM PC, was NOT the platform Doom was written on. It was written on the NeXT platform, and id knew most people did not have access to NeXT computers. Doom, thusly, is a prime example of how to write a cross platform game, one of the best models. Doom spares no detail in creating everything from the ground up, including fundamental data structures.

For example, doom shows you how to elegantly sanitize malloc -- malloc is a C function that interfaces with kernels in your operating system to request and reserve a block of memory. But how kernels operate on memory varies not only from OS to OS, but even revision of OS to OS. Malloc, thusly, is malliable, over time, as C has evolved, malloc too has changed. It's not wise to rely on malloc to handle memory in C. People who don't do low level programming but operate in higher programming languages like Java might hear things about how C is a "nightmare" because you have to "manually manage memory." A lot of that "nightmare" comes from how much malloc changes over the years. Doom shows you how to manually manage your memory. It uses malloc in the most broad sense, only using it to request a single large pool of memory, which it then handles and breaks into smaller chunks itself. It, in essence, creates it's own micro OS within that chunk of memory. It is doom, not your OS or its kernel, that fiddles with the memory. To do this, it builds every data type it uses from the ground up. That let carmack and crew design custom, portable data structures in low level memory, bit by bit, byte by byte. That might seem rote to anyone who has done engine programming these days, but that's the point. Doom set that standard. Everybody follows doom's model.

Going further, Doom impliments OOP in C. Programmers might have heard that C is classically "not an OOP language." That's not quite true. C is a very low level language, exposing memory directly to the programmer. As such, it doesn't provide any OOP abstraction, but you're absolutely free to write your own yourself. When Doom was created, OOP wasn't really a common thing. None the less, Doom implements it's own OOP concepts through pointers, function callbacks, etc. The OLD style of OOP. But Doom's methods are elegant, it's a great OOP implementation. With liberal use of void* pointers and explicit casting, Doom manages to perform a pattern that wouldn't become popularized till really 5 or so years later!

Back to porting doom: Doom is written to be portable. By writing so much of the engine in custom, operating-system-independent wrappers, it was built so that the core function of the engine was self contained. There are only really 4 files that are platform dependent, those files control the lowest level functions of the engine. Things like calling out to the video card, requesting memory, polling hardware. These 4 files are the core of doom's engine. They are written not to actually do larger functions, but rather to provide a framework of commands that the rest of the engine can call to do complex things. Like, a function to draw pixels on the screen. When you port doom, you write those functions for the hardware, which is how it becomes so portable. If you can write a low level function that places pixels on the screen, matching the interface doom defines, the rest of the engine can use it and thusly do everything it needs to do regarding graphics. That is one of the secrets to why Doom is so widely ported. This concept of portability was not necessarily created by Doom itself -- I've seen Amiga/Genesis/SNES games that work the same way with company-specific libraries that worked the same way which could be placed inside larger assembler code -- but Doom does it very well. More than that, while some other games did this, most did not. It was more common in 1993 for ports of games to essentially be entire rewrites than have modular code like this. And in the Amiga/Genesis/SNES examples I cite, the entire games usually weren't written to be modular, only pieces. Things like the graphics system might work in a modular fashion, but then the memory management might be entirely different among the games. They were often half-ports, half-bespoke-remakes. Doom is truly portable.

I rewrote those core functions in a few days and got Doom running on the Dreamcast. Really cool, very good lesson. But that isn't going far enough. Doom has way, way more lessons to teach if you dive in. Writing those core functions will teach you how to make a nice modern interface, get you thinking about portability, but the Doom Engine itself will teach you many more concepts the deeper you dive in. For example, Doom teaches you the concept of decoupling the game's internal logic from internal hardware. Old games used to have this problem where how well the game performed was dependent on the hardware it ran on. The logic was usually very closely tied to the hardware, using things like the screen's refresh rate to tie to logic. Doom doesn't do that. Doom implements what is called Fixed Timestep, which uses real-world time as a metric. For example, movement. In many old games, movement is handled in number of spaces jumped per frame. On frame 1, you are at position X, on frame 2, you are on position X+A, on frame 3, you are on position X+A+A, and so forth. Your position depends on that A variable and also which frame you are looking at, A is essentially your speed. This means your motion is not constant if the frames are not constant. If it takes 1 microsecond between frames 1 and 2, but 10 microseconds between frames 2 and 3, your velocity will not be linear, it'll be logarithmic. Doom doesn't work like this. Doom calculates delta between frames. One frame 1, your position is X, on frame 2, your position is X + Delta(frame1), on frame 3, your position is X + Delta(frame2). The delta is how much time passed between the current frame and last frame, calculated using a constant velocity. If you are moving at 1 space per unit of time, and between frame 1 and frame 2, 1 unit of time passes, then the delta is 1 space. But if 10 units of time pass between frames 2 and frames 3, then the delta is 10 spaces, meaning you move at a linear 1 space per unit of time. This decouples the refresh rate of the hardware from the game speed. Game speed is dependent on external, real time, not the load of the computer. Again, this sort of thing is rote today, but largely because Doom showed everyone how it was done.

Another great example of how Doom establishes the model of modern game design is with its rendering system. People will say things like "Doom isn't 3D" but that's completely wrong. Doom IS 3D, it's the map layouts that are 2D. But Doom's rendering system is pretty much the basis of all modern rendering systems today. The main difference between the way Doom renders and wolfenstein renders is owed to how they process the polygons that make up the world. Wolfenstein uses a raymarcher, basically a system where the game shoots rays out from the players perspective, and paints the screen line by line. It is rendering lines. The world is made up of a bunch of tiny lines that make up walls. Doom does not work like that. Doom renders the world per object. This is a massive difference because, to accomplish this, it needed a way to very speedily traverse the world. Enter Binary Space Partitioning. Binary Space Partioning, at the time of Doom's release, was something really only used in the academic world. It was stuff that, like, the military used for simulations, or NASA used for the space shuttle. It was the most cutting edge 3D traversal system around. BSP works by subdividing the world into many partitions to create nodes (called lumps in doom) that contain single objects. BSP helps order the world into lumps so that, when you render the world around you, you don't have to render everything.

Kotaku once ran an infamous article where they talked about Fustrum Culling as though it was a new technique Horizon Zero Dawn used to speed things up:

tumblr_inline_oqh1hamavB1tm46jo_500.gifv


Many people laughed and pointed out that it wasn't unique to that game, it was an old technique, which is correct. Many games used it before Horizon Zero Dawn. BUT NO 3D GAME USED IT BEFORE DOOM. Doom is the genesis of this technique, the magic behind how this technique works is BSP. Even today, modern 3D engines use BSP to speed things up. Without BSP, even modern graphics cards would be too slow to render. BSP is the "magic" that makes rendering large worlds possible. BSP is an ordering technique that sets everything up in a way that graphics technologies can speedily figure out what is or isn't in a fustrum. Without this ability to order objects, if everything was out of order in memory, it would simply be to slow.

More to the point about doom being actual 3D -- while the map is an arrangement of objects on a flat plane, the objects themselves are NOT 2D. They are fully 3D, with both an X and Z component, plus a height component that is functionally a Y component. That's the trick to how Doom works so fast, it's a bunch of 3D objects, laid out on a 2D plane so that the early BSP traversal implementation didn't have to work so hard. Once CPUs became faster, it became possible to have BSP traversal in 3 dimensions (meaning operating on more data) and the process pretty seamlessly transitioned into 3D maps in Quake. But the core concept was there in Doom, just operating on less data to accomplish the same feat.

Another example of how Doom teaches great concepts: Event handling. In games prior, things like joystick polling were done at intervals, in simplistic ways. Every bit of the game would have it's own routine to check input. Like, mario. The title screen has a part where it checks input, then determines if start is pressed to proceed. Then, once the game begins, an entirely separate piece of code in the game loop checks input, and figures out what to do if you press right, or A, or B, or whatever. Each screen, each game mode, had it's own input checking stuff. Doom doesn't work like this. There is one centeral, modular piece of technology (one of the core functions I mentioned above) that polls for input, independently of the rest of the game. To let this piece of technology talk to the rest of the game, it implements what is known as an Event Handler, which is a global queue of events that get passed from mode to mode. Events are queued using hardware interrupts, a way for the processor in your computer to receive a message outside of your program, directly from the joystick, which makes it say "oh shit, let's stop running the main code for a bit, and jump to this routine immediately, then when it's done, let's go back to exactly where we were in the main code." In Doom's instance, the IRQ code that is run when the joystick (or keyboard, or mouse) flags input, is a piece of code that takes the information polled, configures it into a package, then places it into the event queue. Then, individual game modes themselves have event handlers. They don't poll the input, they just handle the input if any exists. This means, for example, the menu in Doom does not need to check for input. Nor does the gameloop. Instead, they just have routines that, if input exists at all, will get executed. If no input exists, they don't get executed. This concept of events is a major change to how games work. All game engines today operate off of events, it's the main concept behind blueprints in things like UE4:

EventHitEX.jpg


Again, this might seem rote today, but that's because DOOM popularized it. It's rote, because everyone is copying doom.

I could keep going on and on about how this kind of stuff is laid out. Doom standardized game networking, for example, teaching synchronization methods. Doom popularized the concept of releasing editors and tools. Doom did a ton of things that all games today crib off of. Doom is, hands down, the most important and groundbreaking and trendsetting game of the last 30 years. Hell, I might say ever. Probably the most important game ever released.

Pay your respects to Doom. It's legacy endures, the entire game industry owes it a huge technical debt.

Nice thread OP. I have a some(limited) knowledge of engine architecture but I didn't know that event was handled this way. Even when I was writing simple engines I used some stuff like allegro or sdl for event handling. Did the interruption handler need to be executed in kernel space?
 

Nooblet

Member
Oct 25, 2017
13,622
Top quality OP !
It really shows the genius of Carmack and Romero as they came up with these ideas by themselves at a time when no one was doing any of it.
 

Deleted member 8257

Oct 26, 2017
24,586
John Carmack is a fucking legend for a reason.
 

rayngiraffe

Member
Dec 11, 2018
1,454
Thanks for laying it out TC, but didn't Wolfenstein set the benchmarks for the engine first? Also I'm curious cause weren't there other developers which came up with the same concepts for game design too?
 

sugarmonkey

Banned
Oct 27, 2017
515
Awesome post. Thank you for taking the time to share this with me. Also a breath of fresh air from all the self indulgent console warrior nonsense on this forum as of late. This is imo the kind of enthusiast posting we need more of.
 
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
Great post. I want to add a couple of corrections and/or trivia about the BSP part, tho.



It's not well known but the first game using BSP is actually Wolfenstein, or to be more precise, its SNES port.
Carmack used the SNES port of Wolfenstein as a test bed for the technique, and a sort of proof of concept that it would have worked on a bigger scale in DOOM.
In the end, DOOM was shipped a couple months before Wolfenstein's SNES port, so it's still the first commercial title to use it. :p

One major difference - Wolfenstein's maps are axis align bound, which means they are not technically BSP, they are R-trees, which are bound by axis. Doom, by contrast, are true BSP, because it is not axis align bound. The mathematics to compute BSP is more complex than R-Trees.
 

danmaku

Member
Nov 5, 2017
3,232
Wait, are you telling me that old 3d games like Ultima Underworld didn't use culling? They just rendered the whole dungeon all the time?

Also, now I get what that "memory allocation demon" was. As a kid I thought it was awesome having a demon in my pc, managing the memory.
 

Deleted member 29195

User requested account closure
Banned
Nov 1, 2017
402
It blows me away that to this day there are some games that still do this.
Why would you do this!?

Sorry we can't get Okami running faster than 30fps because the framerate is tied to the game logic. The fuck would you build it that way?!
During the PS2 era, what "frame rate" meant was really, really complicated. Do you mean the amount of frames generated per second by the game's GPU? Or the images shown on your television? Because in the PS2 era we had CRTs, which don't display a grid of pixels, and interlaced video, which is even more complicated. A lot of games didn't even realize they were tying things to frame rate.
 

xinoart

Member
Oct 27, 2017
506
I remember doom (and wolf) mostly for their Shareware. I wish we could go back to those days. It always felt kind of criminal for some reason even though trading disks at the time was intended. I guess the closest thing to that nowadays is something like free chapter 1 games, but has anyone done it besides Telltale? I can't even remember the last time they did it.

I do agree that doom is really the godfather of the current videogame landscape though. They made games become more than just "Nintendo" at the time. Hearing adults talk about games as anything more than just as a toy was pretty cool back then. Of course that also led to poeple boycotting grocery stores and gas stations because they had Mortal Kombat in them, but that's another tale from an OG gamer.
 
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
Wait, are you telling me that old 3d games like Ultima Underworld didn't use culling? They just rendered the whole dungeon all the time?

I actually ported many of the ultima games as my very first learning projects with my mentor back in the day. When I was first learning SDL and OpenGL, my mentor in the field, a NASA engineer who would tutor me on saturdays at a PC Users club called Hal-PC in a custom graphics SIG, was an Ultima nut. We went over how these games worked in their rendering process.

First thing to clarify, there is a difference between rendering and object processing. Someone else mentioned that Quake did not use BSP to render -- neither did Doom. They used BSP to process objects. The idea behind BSP is to minimize the number of objects to check whether or not they are in a frustrum, if an object is found to be in the frustrum, they render, if they are not, they are not rendered. This is the first pass of a culling process. Once all the objects are binned (placed into a queue to indicate they are within the frustrum), they are passed to the renderer, which draws the objects (in doom's case, it draws them with a raymarching routine, in quake's case, it draws them using fixed function OpenGL rendering calls to the hardware, or software routine equivalents that plot pixels at a projection).

The way BSP works is that objects in the world are considered as hyperplanes that bisect the world into smaller cubes, over and over again, until you arrive at a series of nodes -- a node representing a section of the world containing exactly 1 polygon -- and the nodes are arranged in a logical pattern from front to back. That is, the list that represents the queue of polygons to draw, are ordered using this function called BSP so that you can start at element 1 of the queue and iterate to the final element of the queue, and every successive element will be further away than the previous element. They are ordered, in other words, from front to back. BSP functions are math intensive, and thus can only be done on static (non-moving) elements of a map. A BSP tree -- the order of polygons in a world from front to back -- must be pre-calculated for a level before the level is run. The Doom engine uses a tool to do this when you build levels. Because of the way BSP uses hyperplanes, the polygons in the world do not have to be aligned to any kind of grid, they can be of any arbitrary dimension or orientation, and the BSP function will smartly divide the scene into nodes using intelligent algorithms.

Ultima Underworld does not work like any of this. The underlaying mechanism it uses to render the world is a tilemap. Objects aren't placed into a queue from a frustrum, the player in the world is what determines what tiles are being rendered based on distance. To to this, tiles in memory are ordered using what is called a morton code. A morton code is a Z-order filling pattern that places tiles physically in memory according to how close they are to each other. This is opposed to a traditional X by Y tile map, where tiles in memory are arranged by rows and columns. In a traditional tile map, this means that the tile directly below another tile is not next to it in memory, instead every tile in a row adjacent in front of that tile, and every tile adjacent in a row behind the tile below it, precedes the tile below it in memory. The formula to find a tile in memory is ((Y * width) + X), indicating that the entire width (known as a pitch in graphics terms) must be considered when determining X,Y geometric positioning. By using a Z-ordered curve when ordering a tile map, you can arrange things so that tiles in memory match their physical proximity, in a Z pattern. In other words, the tile below another tile in memory, is physically close to that other tile in memory.

The entire goal of these early culling processes is to minimize the number of objects to check. By using a morton code, one can limit the number of world tiles to render by limiting to just a range around the player, as where the player's position resides in space will inform where in memory to look, and all the surrounding tiles are physically close to that area of memory. This works well for something like Ultima Underworld, but has a number of limitations. Being a 2D tile map, it is thus axis aligned, even if the individual tiles do not have to contain elements that are axis aligned. That means the map is made up of a grid of chunks, where the BSP system used in doom is free form. Objects in doom can exist anywhere, independent of any large chunk-based grid. They can be arbitrarily placed, at less memory cost. It's a much freer, less restrictive access pattern, which is why Doom's method of memory sorting won out over competitors like Ultima Underworld. Games like UU represent a technological dead end that other games did not pursue.

Posts pointing to UU are precisely what frustrates me about this board regarding discussions of engines. Most of what the engine does, is not something that can be observed by viewing the end result. At the final step of the rendering process, both UU and Doom use a form of ray marching to draw their primitives, the so-called renderer. But the bits that make those renderers actually viable, which allows the hardware enough breathing room to actually perform the rendering process in a performant way, which influences the way worlds and levels and gameplay mechanics are built, is largely invisible to the end graphics result on the screen. Thus, while UU might look similar to Doom, in the same way that Wolfenstein looks similar to doom, they are vastly different engines. Modern engines descend from Doom, not UU, what UU does is not how modern games work. And that's why you shouldn't judge an engine based on what you see on screen.
 
Last edited:

capitalCORN

Banned
Oct 26, 2017
10,436
UU1 is also the best of its class.
You're acting like I spit on Looking Glass's grave. Doom was a marriage of action and technology that basically crushed all competition to dust. It spent two generations being ported to practically every console at the time. It's the rare game that exceeded the arcade experience at the time.
 
Last edited:
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
It blows me away that to this day there are some games that still do this.
Why would you do this!?

Sorry we can't get Okami running faster than 30fps because the framerate is tied to the game logic. The fuck would you build it that way?!

There is actually a caveat to how doom's fixed timestep works. The games you are complaining about actually work just like doom, it's just that doom's methods have been further iterated to further decouple games. Example, you cannot make the original doom engine run at greater than 75 frames per second. There is a hard limit to how the game works. The fixed timestep that doom uses is a way to decouple the actions of the game, from the speed of the hardware, to tie the actions of the game, to real world time metrics. It does this by subdividing a larger unit of time, like say 1 second, into smaller microseconds, called ticks. Ticks operate on a fixed interval, like say 1/75th of a second, so that 75 ticks happen every second. Those ticks are where the smallest polling operations occur, the ones that compute the delta time. It decouples actions in games in one direction, if the hardware slows down, it can compensate. But if hardware speeds up, it cannot. It can't consider any rate higher than 1/75th seconds.

The evolution past this, which is what you are calling for, is variable timestep, which is a much more complex process that was born from Quake. It's a descendant of fixed timestep, that lets the decoupling work in both directions. But it is a subset of the original fixed timestep pattern that doom originally created. Variable timestep has it's own set of drawbacks, mind you, which are why some games choose to use fixed timestep instead. But those are too numerous and complex to list, as they mainly come down to things like physics calculations and determinism (as well as implementation and performance, it's much, much easier and more performant to implement fixed timestep).
 
Nov 1, 2017
3,067
Another fantastic thread Krejlooc. If you haven't already, you should save your posts. You could easily make a book out of them at the rate you're going.
 

Sinatar

Member
Oct 25, 2017
5,684
If Doom was impressive then what does that make Ultima Underworld which predates both Doom AND Wolf 3d?

Incredible that's what.
 
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
If Doom was impressive then what does that make Ultima Underworld which predates both Doom AND Wolf 3d?

Incredible that's what.

Ultima Underworld shares more in common in terms of memory sorting with something like Phantasy Star on the Sega Master System than any modern game, where modern games basically follow the same pattern doom trail blazed. UU is really a great game, but it did not have much influence on engine design going forward like people ITT think.

Where games like Phantasy Star and UU differ is in the rendering component, namely the latter's use of raymarching to render primitives, but UU was hardly the first game to use raymarching. All 3D rasterization uses raymarching, lots of games had software rasterizers prior, they just performed poorly. UU is amazing in that the rasterizer was performant, but so were games like Catacomb 3D and Wolf3D. But there was prior use of these raycasting patterns in video games prior to any origin or id game.

By contrast, the BSP Doom uses really is the first use of BSP in all of video games. A true pioneer, that all games following took after.
 
Last edited:
Nov 23, 2017
4,302
I actually ported many of the ultima games as my very first learning projects with my mentor back in the day. When I was first learning SDL and OpenGL, my mentor in the field, a NASA engineer who would tutor me on saturdays at a PC Users club called Hal-PC in a custom graphics SIG, was an Ultima nut. We went over how these games worked in their rendering process.

First thing to clarify, there is a difference between rendering and object processing. Someone else mentioned that Quake did not use BSP to render -- neither did Doom. They used BSP to process objects. The idea behind BSP is to minimize the number of objects to check whether or not they are in a fustrum, if an object is found to be in the fustrum, they render, if they are not, they are not rendered. This is the first pass of a culling process. Once all the objects are binned (placed into a queue to indicate they are within the fustrum), they are passed to the renderer, which draws the objects (in doom's case, it draws them with a raymarching routine, in quake's case, it draws them using fixed function OpenGL rendering calls to the hardware, or software routine equivalents that plot pixels at a projection).

The way BSP works is that objects in the world are considered as hyperplanes that bisect the world into smaller cubes, over and over again, until you arrive at a series of nodes -- a node representing a section of the world containing exactly 1 polygon -- and the nodes are arranged in a logical pattern from front to back. That is, the list that represents the queue of polygons to draw, are ordered using this function called BSP so that you can start at element 1 of the queue and iterate to the final element of the queue, and every successive element will be further away than the previous element. They are ordered, in other words, from front to back. BSP functions are math intensive, and thus can only be done on static (non-moving) elements of a map. A BSP tree -- the order of polygons in a world from front to back -- must be pre-calculated for a level before the level is run. The Doom engine uses a tool to do this when you build levels. Because of the way BSP uses hyperplanes, the polygons in the world do not have to be aligned to any kind of grid, they can be of any arbitrary dimension or orientation, and the BSP function will smartly divide the scene into nodes using intelligent algorithms.

Ultima Underworld does not work like any of this. The underlaying mechanism it uses to render the world is a tilemap. Objects aren't placed into a queue from a fustrum, the player in the world is what determines what tiles are being rendered based on distance. To to this, tiles in memory are ordered using what is called a morton code. A morton code is a Z-order filling pattern that places tiles physically in memory according to how close they are to each other. This is opposed to a traditional X by Y tile map, where tiles in memory are arranged by rows and columns. In a traditional tile map, this means that the tile directly below another tile is not next to it in memory, instead every tile in a row adjacent in front of that tile, and every tile adjacent in a row behind the tile below it, precedes the tile below it in memory. The formula to find a tile in memory is ((Y * width) + X), indicating that the entire width (known as a pitch in graphics terms) must be considered when determining X,Y geometric positioning. By using a Z-ordered curve when ordering a tile map, you can arrange things so that tiles in memory match their physical proximity, in a Z pattern. In other words, the tile below another tile in memory, is physically close to that other tile in memory.

The entire goal of these early culling processes is to minimize the number of objects to check. By using a morton code, one can limit the number of world tiles to render by limiting to just a range around the player, as where the player's position resides in space will inform where in memory to look, and all the surrounding tiles are physically close to that area of memory. This works well for something like Ultima Underworld, but has a number of limitations. Being a 2D tile map, it is thus axis aligned, even if the individual tiles do not have to contain elements that are axis aligned. That means the map is made up of a grid of chunks, where the BSP system used in doom is free form. Objects in doom can exist anywhere, independent of any large chunk-based grid. They can be arbitrarily placed, at less memory cost. It's a much freer, less restrictive access pattern, which is why Doom's method of memory sorting won out over competitors like Ultima Underworld. Games like UU represent a technological dead end that other games did not pursue.

Posts pointing to UU are precisely what frustrates me about this board regarding discussions of engines. Most of what the engine does, is not something that can be observed by viewing the end result. At the final step of the rendering process, both UU and Doom use a form of ray marching to draw their primitives, the so-called renderer. But the bits that make those renderers actually viable, which allows the hardware enough breathing room to actually perform the rendering process in a performant way, which influences the way worlds and levels and gameplay mechanics are built, is largely invisible to the end graphics result on the screen. Thus, while UU might look similar to Doom, in the same way that Wolfenstein looks similar to doom, they are vastly different engines. Modern engines descend from Doom, not UU, what UU does is not how modern games work. And that's why you shouldn't judge an engine based on what you see on screen.
In the case of Doom, by "objects" you mean walls and raised platforms and things like that? Or things like sprites/enemies?
 
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
In the case of Doom, by "objects" you mean walls and raised platforms and things like that? Or things like sprites/enemies?

level geometry, represented as individual single vector polygons on the map. Each polygon has a wall ID that maps to a specific 3D wall shape, which defines Y position (as well as things like window, ceiling height, etc).
 

lazygecko

Member
Oct 25, 2017
3,628
Doom's forte is that it's best in class. It is speedy as fuck while supporting large areas chocking with actors, dynamic lighting and even offers perspective correct textures.

This is kind of the understated component of what made Doom such a revelation. The game actually ran relatively fast and smooth even on consumer grade PCs. It's easy to forget that the whole zeitgeist around 3D graphics (outside of arcades) at the time was that you just sorta took for granted that it would run like a slideshow.
 

Kazooie

Member
Jul 17, 2019
5,011
I'm about to run out for the day to do some work, but someone remind me in the future and I'll break down how Carmacks' "Black Magic" fast inverse square root algorithm works. It's unbelievable. It's an algorithm that shouldn't exist. He didn't create it, but he knew of it, which is mind blowing in and of itself.
Why not? He was working on 3D games with limited hardware, so he probably was in contact with people on the hardware side, to whom the algorithm was folklore. Technical innovation usually is a team effort and a matter of collecting and combining successful ideas. Chances are that most of the thing in Doom are not Carmack's ideas initially, but a good implementation of previous ideas.
 
OP
OP

Deleted member 12790

User requested account closure
Banned
Oct 27, 2017
24,537
This is kind of the understated component of what made Doom such a revelation. The game actually ran relatively fast and smooth even on consumer grade PCs. It's easy to forget that the whole zeitgeist around 3D graphics (outside of arcades) at the time was that you just sorta took for granted that it would run like a slideshow.

The way I put it, is that the Doom Engine is when computer science really entered video game development. Prior to Doom, games were built of a cowboy coder mentality. I don't mean this as a pejorative, because while I'm actually educated in computer science, as a programmer, I cut my teeth in demoscene and hacking and picked up all my habits from that world. It's a very different world from proper computer science. Doom was like a template for everything regarding comp sci in video games. It did everything properly, including a lot of stuff that only existed in academia at the time. It was a very solid example of an academically made game engine. Which is super ironic, because Doom was made by Delta Quit Delta -- a fraternity of college drop outs.

Doom is so performant, so well made, because it uses all the top of the line computer science research available in 1993. People in other fields have honestly used Doom to teach computer science. It really is an amazing educational tool, which ties back into what I mentioned at the end of the OP about it being significant that id released it for free. Doom is not only well written, it is well annotated and commented. Through it's release, it taught an entire generation of young and amateur computer programmers the type of things you'd normally have to complete a comp sci course to learn. More importantly, it trimmed the fat. Computer Science is an enormous field, there are lots of things in comp sci to learn that aren't too applicable to game development. You have to pick and choose what to spend your time learning, and Doom provided a template that showed you everything you needed to learn. The release of the Doom engine straight up made the gamedev world better. It's not at all a stretch to call John Carmack a scientist on the level of, say, Einstein's importance to physics, applied to the video game world. Michael Abrash as well. It's pretty astonishing that these men chose to apply their incredible gifts to video games, and the entire industry benefited greatly.
 

dmix90

Member
Oct 25, 2017
1,885
sqrt.png


It would honestly take super computers of the time years to find this magic number, how carmack knew about it is a mystery. You can actually write an entire book about this algorithm because there is so much awesome shit in it. And yes, the comments on the right, "what the fuck??" etc, are carmack's comments/explanation lol.
5SzsIqq.jpg


XYXvBvU.jpg



Oh, we are indeed DOO.... OH SHIT...!
 

Ada

Member
Nov 28, 2017
3,731
I remember downloading the Q3 source code as a kid and being completely overwhelmed how complex it was. First time I'd ever seen a games code at the lowest level.