26 comments

[ 239 ms ] story [ 2729 ms ] thread
I have been waiting for this book to get released, so I'm very excited that its getting released this month. Wolfenstein 3D is why I learned C.
I built a 2.5D engine back in about 2006 with SDL and C on OSX. It worked (eventually) and taught me a lot. It wasn't particularly clever but had collision detection and textures, the latter stolen from Wolf 3D of course. It's a valuable experience as a programmer.

What I never managed to understand was how they managed to get the performance they did out of the hardware. Mine crawled at a miserable 8fps at 640x480 on a 2GHz Core 2 Duo iMac.

Performance is where the magic in this really is! Can't wait for the book.

They didn’t use SDL for a start ;)

SDL is great but it’s not in the same league as the hand-rolled & optimized code they used.

Different goals.

Great job tho! That’s not an easy project!

With VGA you write directly to video memory don't you?

The only extra indirection SDL adds is that you write directly to system memory instead, and then SDL copies that to video memory for you when you swap buffers.

Like the person you're replying to, I've also never seen how copying 640x480 bytes from system memory to video memory can introduce such a bottleneck. What's the bandwidth between the two? 10 Gbps or something?

There must be more to it than SDL overheads.

Indeed, perhaps SDL graphics primitives other than surfaces were used. These are notoriously slow implementations. Or the code was not in C/C++ and messed up the garbage collector or had huge overhead memory allocating.
I can't remember how exactly I did it but the entire thing was written to a surface in a massive for loop per-pixel (C was used) and then flipped.
It depends on how you use the SDL as well. In ca. 2000, I've written a game using DirectDraw (which I think the high-level functions in SDL 1.x also used?), and it worked quite well on ~400 MHz PCs.

Then graphics drivers stopped hardware-accelerating 2D graphics(?), and the same game turned into a CPU hog that performed much worse even on much more recent hardware.

This thread is vaguely about the same issue: https://www.reddit.com/r/gamedev/comments/1rpwig/sdl_blit_is...

In this case I suspect it was inefficient algorithms by me. To be fair it went like lightning (400fps) until I added textures as it was just drawing vertical lines before then.
SDL used as normal in this conext just gets you a window and then gets out of your way.
Instead of SDL on a protected windowing OS, hand-optimized assembly with direct hw access.
sdl doesn't impart any per frame penalty i don't think, and the os not much. 640x480 is also way more pixels than 320x200
Does anyone know why does 2.5D ray-casting perspective in Wolfenstein 3D look so much better than a typical 3D perspective (usual matrix)? When you turn around staying on a single spot, walls aren't changing their size in Wolfenstein 3D, whereas they do in any 3D FPS...
3D games use a rectangular perspective projection - they project the scene to a 2D rectangle. Problem is that the FOV (field of view, zoom) is not correct unless you put your head very close to the monitor. This leads to distortion. For example, if the FOV is 90 degrees, you need to put your eye (will only be correct for one, of course) centered in front of the display at a distance that's exactly half the width of the screen (draw the triangle). Obviously that's extremely uncomfortable so we pull back and deal with the distortion.

Working around that with a fisheye projection has other issues, like straight lines in 3D ending up curved on the screen, and is a bit more computationally expensive, though not too bad these days. It's free in Wolfenstein-style 2.5D though (although Doom chose not to do it).

A great explanation of FOV, thanks!
As far as I am aware, Wolf 3D had an approximation of such perspective constructed from multiple rectangular projections. This trick also allows you to reuse part of the perspective transform while moving forward. Wouldn't look to nice in high res as long as number of projections isn't increased. Seams would get noticeable.
One of the thing that amazed me about wolf3d engine in retrospect is that it uses mipmapping. I dont know if the mipmap level of a vertical segment was computed based on the u-coordinate derivative but my guess is that it could do that quite easily thanks to the raycasting algorithm.
I don't think there was any mipmapping in Wolf3D. That wasn't introduced until Quake.
See, this is unbelievable. There is mipmapping in wolf3d.
Oops epic fail. There doesnt seems to be any.
This looks very interesting!

A. It's terrific to see people really dig into some of these early technical achievements while they're still fresh in our collective memory - limitations tend to inspire creativity, and I think we all like reading about those creative solutions.

B. Modern embedded systems like Cortex-M processors can probably take some design hints from these projects which were developed on/for machines with very limited resources. I was thinking of looking into writing a simple emulator on one, maybe for the [S]NES or an early Gameboy (if anyone knows a good resource...?). It'll be super cool to get an in-depth window into how "3D" was managed without niceties like a programmable shader pipeline. The best that ARM-M chips seem to get is a dedicated memory controller for LCD interfacing, some SIMD operations, 2MB of 'bitband' memory that is rapidly addressable on a bitwise basis, and sometimes a display accelerator for single-cycle pixel operations in higher-end models.

I've been reading the Michael Abrash's Black Book, and it was quite eye opening, especially when working around serious limitations of the old hardware.
We've buried this thread ("announcement of an announcement") so that we won't have to mark a later discussion as a duplicate when this is actually released.
That seems like a self-inflicted problem. Why would you have to mark the future thread as a duplicate?