7 ms·
>The N64 hardware has something called a Z-Buffer, and thanks to that, we were able to design the terrain and visuals however we wanted. This was a huge advant
by dmbaggett 10y ago
>The N64 hardware has something called a Z-Buffer, and thanks to that, we were able to design the terrain and visuals however we wanted.
This was a huge advantage for them. In contrast, for Crash Bandicoot -- which came out for the PS1 at the same time -- we had to use over an hour of pre-computation distributed across a dozen SGI workstations for each level to get a high poly count on hardware lacking a Z-buffer.
A Z-buffer is critical, because sorting polygons is O(n^2), not O(n lg n). This is because cyclic overlap breaks the transitive property required for an N lg N sorting algorithm.
The PS2 got Sony to parity; at that point both Nintendo and Sony had shipped hardware with Z-buffers.
- fuckyeah 10y agoHad the ps1 a dedicated chipset for 3d graphics or was it a pre-written software renderer library kind of thing? Was writting a software renderer (with perspective correct texture mapping and a zbuffer, amongst other things) out of question?
- dmbaggett 10y agoYes, a software renderer would have been far too slow. The PS1 had a 33Mhz MIPS processor.
- zubat 10y agoThe PS1 can be characterized as "half-software" because the geometry transforms are done through a CPU coprocessor, then sent to a mostly-2D GPU capable of filling in the gaps with affine transformations. This unusual pipeline accounts for why the rendering artifacts have a system-defining character to them - information about the geometry is lost after leaving the CPU and the GPU operates at screenspace precision, making the biggest polygons onscreen the most visibly inaccurate.
- JonnieCache 10y agoNice to have a proper explanation of why PS1 games look so weird.
- rangibaby 10y agoIt's called affine swim, and is present in some PC games too. I first noticed it in Half Life when I was messing around with the software renderer.
- damptowel 10y agoMight be wrong but I thought Quake's software renderer does proper perspective texture mapping? (Original Half-Life is based on Quake)
- royjacobs 10y agoQuake perspective corrects only every 16 pixels and does linear interpolation in between. This is because the correction requires an expensive FPU divide. While the FPU is busy doing that, the CPU can do the linear interpolation. Once the CPU is done with the 16 pixels, the FPU has also completed the divide and the CPU can do the next 16 pixels, and so on. Looks pretty decent but is not 100% accurate.
- deleted 10y ago[deleted]
- rangibaby 10y agoIt was so long ago that I honestly don't remember. It might have been something like HL model viewer or Milkshape 3D rendering things using a different software renderer. I did some research and there is also an option to set affine texture mapping in the HL OpenGL renderer. HL works on Macs so I will test that stuff out soon
- digi_owl 10y agoI think by the time HL shipped, the engine had been so hacked to bits that very little was left over from Q1. Heck, i think they even ported over various bits from Q2.
- sthatipamala 10y agoI just read the Making of Crash Bandicoot blog post series. This limitation is why Crash Bandicoot had a camera-on-rails to limit the number of polys on screen, right?
- dmbaggett 10y agoNot to limit the number of polygons on screen, but to make it feasible to precompute the exact order polygons would appear on the screen during each frame at render time. Pre-computation actually increased the effective polygon count because it also meant that the engine didn't need to render occluded polygons (i.e., the rock behind the tree you're looking at) at all.
- wnevets 10y agois that similar to resident evil's prerendered graphics?
- corysama 10y agoResident Evil largely baked their complex scene geometry down to large, flat textures on large, flat polygons in game. Crash kept the complex geometry of the scene in the game. What was baked was the exact set of polygons that needed to be loaded and displayed at any point along the track.
- jimmaswell 10y agoHow did Spyro end up getting past this limitation to have a free roaming camera with a good poly count?
- dmbaggett 10y agoThe Hastings brothers (who were actually down the hall from us when we were writing Crash) are really awesome coders. Even so, however, I don't think Spyro for PS1 actually had anywhere near Crash's effective polygon count. Crash himself was over 750 polygons, which was not bad for an entire frame of a PS 1 game.
- icebraining 10y agoAccording to this great series on the making of Crash Bandicoot¹, Spyro used walls to reduce the number of polygons visible concurrently. ¹ http://all-things-andy-gavin.com/2011/02/02/making-crash-bandicoot-part-1/ http://all-things-andy-gavin.com/2011/02/02/making-crash-ban...
- rangibaby 10y agoQuake 1 did that too
- agumonkey 10y agoMan you should write a book. Or many, I'm sure you could fill them with all the details about your game development over the years. That would be a nice complement to Abrash Black Bible.
- vvanders 10y agoIf you dig this stuff then Real-Time Collision Detection[1] is solid gold. It's basically data structures for 3D along with a practical appreciate of what makes real world algorithms fast(data layout). [1] http://realtimecollisiondetection.net/books/rtcd/ http://realtimecollisiondetection.net/books/rtcd/
- agumonkey 10y agoThat's the second time I see this suggested, time to try. Still doesn't absolve Dev Baggett to bless us with his stories ;)
- jimminy 10y agoAndy Gavin wrote several extended articles on the making of the original Crash Bandicoot. IIRC correctly, Dave contributed to a few of the articles,, or at least his contributions are mentioned pretty heavily. http://all-things-andy-gavin.com/2011/03/12/making-crash-bandicoot-gool-part-9/ http://all-things-andy-gavin.com/2011/03/12/making-crash-ban...
- agumonkey 10y agoI remember these; but I don't remember them including what Dave Baggett just said, hence my delighted surprise and suggestion above.
- epse 10y agoThat is one expensive book! It's discounted on Google Play and still 75 euro
- seanwilson 10y ago> we had to use over an hour of pre-computation distributed across a dozen SGI workstations for each level to get a high poly count on hardware lacking a Z-buffer. Did you consider any other alternatives? Curious if you had any other ideas that you sidelined as being too crazy.
- dmbaggett 10y agoNo, that idea was crazy enough. :) The collision detection system and camera control code were also insane. Mark Cerny helped me make the collision code fast enough. Very clever assembly language tricks there, and we used 2K of "scratchpad" static RAM built in to the PS1 (for some reason) to make it fast enough.
- seanwilson 10y ago> No, that idea was crazy enough. :) The collision detection system and camera control code were also insane. Mark Cerny helped me make the collision code fast enough. Very clever assembly language tricks there, and we used 2K of "scratchpad" static RAM built in to the PS1 (for some reason) to make it fast enough. Can you expand on how the precompute trick works further? So you're precomputing the order of the scenery/level polygons because of their predictable movement but how does that combine with objects with unpredictable movement (Crash, enemies etc.) when you render a frame? Did the limitations of this trick limit the gameplay you wanted?
- dmbaggett 10y agoI've been meaning to write a blog post about this, but here's a brief summary. We wrote a software renderer for the SGI that exactly replicated how the PS1 hardware would render. I wrote an imperfect clone for Crash 1, then Stephen White wrote a pixel-accurate one for Crash 2. (This is why Crash 1 has "crispies", as Andy called them -- little pixel-sized glitches in the background -- and Crash 2 does not.) When computing a level, we'd sample N points along the rail as we moved the camera forward through the level. At each point, we'd render the entire scene using the software renderer, then recover the rendered list of polygons, in sorted order, from the (software) Z buffer. We'd then store this sorted list of polygons for each of the N frames, using delta compression between frames to keep the size manageable. The pre-computation phase would choose N empirically, based on much change happened from frame to frame in any given section of the level; basically it would make N as large as it could be without blowing out the page allocation (which was in turn determined by how fast we could read from the CD). This handled all the polygons in the background, which was completely static. For foreground objects like Crash, enemies, gems, etc, we'd bucket sort them in as we rendered the background. This required manual tuning in some cases, so we had an editor where we could manually adjust the "push-back" (i.e., bucket adjustment) for each object in real time while playing the game. These magic values were then stored with the associated objects as part of the level data. If we couldn't make an object sort in right via bucket adjustment, we'd change the background slightly until it worked. In other words, it was a massive hack. :) In terms of gameplay, we took our inspiration primarily from Donkey Kong Country, which had linear gameplay. So the rail model actually worked really well for the gameplay we were trying to achieve. (DKC is still an awesome SNES game; check it out if you haven't played it recently.)
- xigency 10y agoLearning this is like when I learned that the Sony PSP couldn't clip triangles that were larger than the view frustum when rendering. I was making a hack-and-slash dungeon game for a homebrew contest when I figured that out and had to find software clipping code fast, so that big pieces of the walls and floor wouldn't disappear when you got too close. It ended up slowing my game down, and if I knew about that limitation I would have engineered around it from the start. I ended up breaking up large triangles and keeping everything stored in an octree. After that, I started noticing subtle clipping issues in a few games including Daxter. I would have never guessed that any 3D video game console didn't have a Z-Buffer, including a relic like the PSX.
- gambiting 10y agoSlightly off topic - I used to participate in several PSP homebrew programming contests too, have you by chance participated in QJ.net or NeoFlash competitions in years 2006-2009? I'm asking because it would be cool to find someone else who took part :D My entries were: PSPSnake, Shoot4Fun, Mandelbrot Fractal Generator, and BlowUp! in the final year.
- coldpie 10y agoI did :) I made Dyox in 2006 and won a prize: https://www.neoflash.com/forum/index.php?topic=2876 https://www.neoflash.com/forum/index.php?topic=2876 I no longer have a PSP, but reportedly it still works on modern CFW and you can run it in PPSSPP: http://brightnightgames.com/games.php?game=dyox http://brightnightgames.com/games.php?game=dyox My email's in my profile if you want to chat
- xigency 10y agoYes, I did. I made "Quak Arena" [1] for the 2006 NeoFlash competition and the game I mentioned was Chronicles [2] for the dash hacks competition in 2009. [1] https://www.neoflash.com/forum/index.php/topic,3035.0.html https://www.neoflash.com/forum/index.php/topic,3035.0.html [2] http://forums.dashhacks.com/psp-programming-development/239955-%5Bhombrew-idol-2%5D-chronicles.html http://forums.dashhacks.com/psp-programming-development/2399...
- Retric 10y agoYou can bound polygon sorting by looking at the closest and furthest points from the camera for each polygon. This get's tricky if the polygon is perpendicular to the camera, but avoiding O(n^2) in the general case is huge. Z-Buffer's are still a major advantage.
- dmbaggett 10y agoThat's an excellent point, and something that I've never actually thought of or read. Cool!
- oxide 10y agoyou should go implement this in Crash Bandicoot and make a youtube video of it.
- deleted 10y ago[deleted]
- CamperBob2 10y agoYou can bound polygon sorting by looking at the closest and furthest points from the camera for each polygon That still fails to resolve cycles.
- Apes 10y agoI have heard before that the Z-buffer was not actually usable on the N64 due to a design flaw. I forget the details, but one of the wikipedia pages about the N64 mentions this: "The Z-buffer could not be used because it alone consumed the already constrained texture fill rate." -- https://en.wikipedia.org/wiki/Nintendo_64_programming_characteristics https://en.wikipedia.org/wiki/Nintendo_64_programming_charac... I vaguely remember a technical analysis on the N64 that explained using the Z-Buffer had such a dramatic negative impact on performance, that only a very small handful of games actually used it. The general theme of the technical analysis was that the N64 had a lot of "features" that had a massive performance impact to use, so many of them went unused. If I remember correctly -- most games implemented their own pseudo z-buffer in microcode, which is why a lot of games on the N64 have issues with textures popping through each other incorrectly -- Goldeneye's bullet hole textures stick out in my mind as a good example of this. However, I'm trying to find the analysis, and I'm not having any luck. Maybe I'm just remembering things incorrectly.
- modeless 10y agoThat quote is referring to a game that runs at a 640x480 resolution. According to a quick search, most N64 games including Mario 64 run at 320x240 which reduces the fill rate requirements by a factor of 4. That would leave plenty of room for using the Z-buffer along with texture sampling.
- MBCook 10y ago640x480 was only possible with the memory expansion pack IIRC.
- corysama 10y agoThe N64 only had 4 megs of unified RAM. 640x480x3bytesx2buffers would be 1800k. It was technically possible to run that without the expansion pack. But, losing that 1350k compared to 320x240 really hurt. 4x fillrate cost hurt even more. N64 had a form of antialiasing support https://www.google.com/patents/US6999100 https://www.google.com/patents/US6999100 That was the motivation for the "9-bit RAM". Worked well enough for the time and was cheap enough to use. Much cheaper than running at a higher rez.