I'm really curious how they were able to pull of the 3d graphics in f-1 race on the NES. It's rather impressive how they did the turns on the road. How did they do it?
Pole Position works by drawing the road as a triangle toward a vanishing point on the horizon, then scrolling each individual scanline of the road to warp that triangle. The road in F-1 Race is drawn the same way, as is the floor in Street Fighter II and NBA Jam. Rad Racer additionally vertically squashes and stretches parts of the triangle to simulate hills.
This page is a good reference on the technique.
Here's some info on Rad Racer I posted a few years ago:
https://forums.nesdev.com/viewtopic.php?f=2&t=8588
Wait, with CHR-RAM couldn't you render 3d polygons? (With crappy frame rate)
DementedPurple wrote:
Wait, with CHR-RAM couldn't you render 3d polygons?
Yes.
Quote:
(With crappy frame rate)
Which's why nobody did it.
Isn't that how they did FaceBall 2000 on the GameBoy?
And how Elite for PAL NES works.
But Game Boy also has a fairly long horizontal blanking period when VRAM can be written.
I don't know, but the Game Boy is better at dynamic patterns than the NES. The patterns are not in a separate bus, for one, and since the screen is smaller, less patterns are needed to cover the same percentage of screen space. The small resolution also means that there's more time every frame to manipulate patterns. Even with all these advantages, FaceBall is still annoyingly slow.
The NES just wasn't built for real-time 3D polygons, and most developers stuck with using the regular features of the system. The NES did see some attempts at real-time polygon graphics, like in Elite, but IIRC that was PAL only, only drew wireframes, and was still fairly slow.
I understand road drawing algorithm for F-1 Race, but how exactly did Elite work?
Elite is actually doing 3D projection, line drawing, and hidden line removal.
lidnariq wrote:
Elite is actually doing 3D projection, line drawing, and hidden line removal.
How does it render the lines?
zeroone wrote:
lidnariq wrote:
Elite is actually doing 3D projection, line drawing, and hidden line removal.
How does it render the lines?
Writes them into CHR-RAM and maps them into the nametables somehow.. I still think that game is impressive as hell. I don't know how well it runs on a PAL NES, but I remember playing it on NESticle long ago and I thought the performance was just fine (though I was probably speeding up the emulated CPU or something).
One of the authors of the Elite made an NES demo with similar graphics, and he also released the source code.
http://www.iancgbell.clara.net/nestank/I remember looking at it when I was first learning to program, and I couldn't make any sense out of it at all. Maybe I'd do a little better now but I'm still horrible at math.
Memblers wrote:
Writes them into CHR-RAM and maps them into the nametables somehow.. I still think that game is impressive as hell.
Here's my guess (without doing any research; so, it might be completely wrong):
They created a frame buffer in RAM with a bit depth of 1; i.e. each byte represents 8 pixels. To display the frame buffer, they created 256 tiles, such that each row of every tile are colored per the binary representation of that tile index; meaning, the tiles look like colored vertical lines since the same colored row is repeated 8 times. Finally, during horizontal blanking (PPU dots > 255), the nametables are updated for each successive row.
zeroone wrote:
Here's my guess (without doing any research; so, it might be completely wrong): ...
It is.
I believe Elite draws the lines in CHR-RAM, allocates the tiles dynamically (i.e., only the tiles that have non-empty CHR data will have non-zero nametable entries), and uses palette switching to get double buffering.
thefox wrote:
allocates the tiles dynamically (i.e., only the tiles that have non-empty CHR data will have non-zero nametable entries), and uses palette switching to get double buffering.
I don't understand. :/
Palette switching means that in even frames, bitplane 0 (consisting of bytes $00-$07 of each tile) gets displayed while bitplane 1 (consisting of bytes $08-$0F of each tile) gets filled, and vice versa in odd frames. To display only bitplane 0, set the palette to black, white, black, white, so that bitplane 1 is ignored. To display only bitplane 1, set the palette to black, black, white, white, so that bitplane 0 is ignored.
Dynamic allocation means it stores a partial nametable in main RAM, filled with solid black tiles. When trying to draw pixels into a tile whose current tile number is the solid black tile, it allocates a new tile number for that tile. When trying to draw pixels into a tile that is not the solid black tile, it uses the same tile number that was already there.