Okay, I'm really wondering how games like 3D World Runner do their 3D tricks. Does anybody know? Is there some sort of 2D to 3D formula that they use? It really doesn't make much sense to me how they do it, and I was just curious, because I'd like to know so in the far far away future, maybe I can use it somehow.
I'm not planning on making any 3Dish games yet, but maybe I'd like to make a small tech demo. Is this way too complicated even for someone who has been doing nesdev for a long time?
It's a raster effect, and it's easiest to understand Pole Position first. I wrote much of
Wikipedia's article on parallax effects.
Speaking as a non-developer, I don't know much about the math. I would like to clarify that "3D-type" parallax scrolling on the NES uses timed code to decide the scroll position(?) for each scanline; a mapper-based IRQ (if present) is used only to define the start or end of the effect. (I'm just trying to explain why the thread's title is inaccurate; feel free to correct me on this oversimplification.)
EDIT: Okay, I think I get the concept of layers. But still, how does stuff come towards the screen? How do they create that effect? Do they do anything with the CHR data? Or is it just warping whats already on screen?
Sprites for different Z-levels coupled with 3d-to-2d coordinate conversion and sprite selection.
I think that the effect in 3D World Runner is much simpler than the one in Cosmic Epsilon. That one actually has different patterns on the ground, instead of a simple checkerboard. I still don't understand how that one is done.
3D world runner is UNROM, not MMC3, so your title is wrong. (note that the original verison was on FDS). There is also it's japaneese-only sequel, but it is the exact same game engine with better graphics and different levels (there is the same ending, tough).
It use some tricky horizontal scrolling change to make the chessboard look 3D. I don't even think the vertical scroll is changed mid-frame in 3D-world runner.
Sprites are level of farity (does it say that way ?) so a sigle sprites is present smaller and bigger in the pattern table to look far and near respectively.
The ground just move forwards, I'm unsure how this is done, but it is nothing complex. For pits, the BG rendering is disabled, but not sprites. That's it all.
Rad Racer is exactly the same but a bit more complex. There is no chessboard, but a pre-rendered flat 3D road, and its moving is done by palette cycling. Then, road curves are done by changing horizontal and vertical scrolling. It looks much more impressive. As above the objects have level of detail, where each car/three/whatever comes in many size to look 3D.
Rad Racer II uses MMC3, but it is basically the same, but in more advanced. It use 4-screen mirroring to memorise a lot of different pre-rendered 3D road tiles, and doesn't use palette swapping any longer. I think the MMC3 helped with CHRROM switching, allowing the game to use more tiles. It's IRQ counter may also help the life of squaresoft programmers.
Bregalad wrote:
Sprites are level of farity (does it say that way ?)
I don't think this is a word.. =) I assume you meant that there are sprites avaliable for various possible distances.
Quote:
The ground just move forwards, I'm unsure how this is done, but it is nothing complex.
It could be a palette change, but I don't think it is. There is a game that alternated between two CHR banks, one with the colors inverted when compared to the other. But since UNROM has no bankswitching, it's probably not that either. I guess it can "slide" the scroll a full square to the left or to the right whenever it has to alternate the rows on the floor.
For
Cosmic Epsilon, no matter how much I watch the pattern tables and the name tables I can't figure out how that effect is done. It has bitmaps on the floor! That's texture mapping! And it uses more than 2 colors! That's pretty amazing for me.
Cosmic Epsilon zips at 3:1, so it's probably really repetitive.
It seems to use Yoshi's Island style texture mapping, where each possible texture row is pre-rendered into a triangle shape and then bankswitched on each scanline.
Oh! I kind of get it! They just do a pallete change for all of the tiles on 3D world runner? That's not complicated really. And for sprites, don't they just have all sprite sizes in the pattern tables? But yeah, I don't get how Cosmic Epsilon's levels work. I am trying to think of methods for making more detailed floors.
We should try and figure out Cosmic Epsilon's flooring here. So what we can see:
There appears to be nothing in the Name Tables besides the city background.
Nothing that is on screen appears to be in the Pattern Tables.
There is only one attribute used for the whole ground (That's not anything special, but oh well.)
I still can't see how you can do pallete changes to color things that small without having anything in the pattern tables. I actually don't see how you can have anything without at least something in the pattern tables...
Celius wrote:
They just do a pallete change for all of the tiles on 3D world runner? That's not complicated really.
I don't know what exactly you mean by "all of the tiles", but although changing the palette is one of the options, I don't this is what
World Runner does. Changing the palette is not so simple because you have to mess with 2006/2007, meaning you'd have to set 2005/2006 to point to the correct place for the next scanline. What I mean is that changing the palette is not that easy, and I don't think this is what this game does.
Quote:
And for sprites, don't they just have all sprite sizes in the pattern tables?
Yeah, this is for sure.
Quote:
There appears to be nothing in the Name Tables besides the city background.
There is. FCEUXD's Name Table Viewer has a "Display on scanline" field, wich you can set to 200 (or any other value that falls in the part of the screen where the special floor is). Then you'll see that the bottom part of the name table keeps changing through some predefined patterns.
It's probably like tepples said, the game has a bunch of pre-rendered floors, that are switched in as the different rows of squares need to be displayed. By timing the switches you can simulate the movement of going forward or backward.
Quote:
Nothing that is on screen appears to be in the Pattern Tables.
Set the emulator to display scanline 200 here too and you'll see the fisrt half of the left pattern table swiching patterns that make up a section of the ground.
Quote:
I still can't see how you can do pallete changes to color things that small without having anything in the pattern tables.
If you mean from one square to the other horizontally, then you really can't. You'll get distorted lines.
Quote:
I actually don't see how you can have anything without at least something in the pattern tables...
Well, it is possible. Recently a demo that displays all the color of the NES was posted, and it didn't use any tiles, it was all done by manipulating the palette and the color emphasis at the right times. It would be very hard to use this concept for 3D floors, though.
OK, I thing i get how the effect in Cosmic Epsilon works exactly.
The bottom half of the screen has a few stripes that come from far away until the bottom of the screen (pretty much like you see in the name tables of 3D World Runner). Now, the tiles used to draw those stripes are drawn in a way that each stripe uses it's own tiles.
So, by loading different tile sets, you can blank out specific stripes, set them to different colors, etc, wich results in different horizontal patterns. The name table is only set up once, and never changed again. The patterns for the bottom part of the screen, on the other hand, change a few times per frame, to create vertical patterns and movement.
It's not that hard, actually. It can waste a lot of CHR space, depending on how many different patterns you wish to be able to display. You you want to show true bitmaps on the floor you'll need tiles sets for all the combinations. With 8 stripes and 2 colors, there would be 256 combinations, and that'd be a lot of CHR space.
I think you'd better do it like Epsilon, keeping a few specific combinations, and you can even do more detailed things (such as the road you see on Cosmic Epsilon).
The idea is very creative...
Hmm, that's interesting. I think a level engine combining pallete changes and pattern table changes would be pretty cool. Is that what they do here? I mean, that's a little vague, sorry. Like, how they put the road with the white road strip (not strips like you were talking about, like an actual road strip) and just turn off the white part of the pallete for the individual dashes. Or is that not what they do? I have to look at it more, I guess.
Is it possible to take a fixed square tile (not strechted or anything), and stretch it towards the screen? I mean, is this possible at all? Because if I could figure out some way to do that, then that'd be really really cool. That'd be really tricky though. I think pretty much alot of things in NESdev are possible, just alot of them are rediculously tricky, like doing something like this. I'll think about it for a while. It's just an idea, though.
Celius wrote:
Like, how they put the road with the white road strip (not strips like you were talking about, like an actual road strip) and just turn off the white part of the pallete for the individual dashes.
Easy. The game bankswitches between a bank containing a white strip and a bank not containing a white strip.
Quote:
Is it possible to take a fixed square tile (not strechted or anything), and stretch it towards the screen? I mean, is this possible at all?
Vertical stretching of an entire row of tiles is possible, and this is how games such as
Rad Racer make hills. Horizontal stretching, on the other hand, generally isn't doable on the NES unless you have an ASIC generating CHR data.
Celius wrote:
I think a level engine combining pallete changes and pattern table changes would be pretty cool. Is that what they do here?
No, no palette changes here. It's just as tepples said, there is a bank where the space reserved for that stripe is white, and another where it's gray. Alternate between those 2 and you get a dashed stripe. You can see that if you use FCEUXD's name table viewer and set the scanline to 200, as I said before.
I can't think of one single game that changes the palette midframe. I mean, we know it is possible, but HBlank time is really tight, and having to fix the address in 2005/2006 for the next scanline does not make anything easier. You'd probably have to sacrifice some pixels that would otherwise be rendered, and that would introduce glitches. Not acceptable for most games.
Quote:
Is it possible to take a fixed square tile (not strechted or anything), and stretch it towards the screen? I mean, is this possible at all? Because if I could figure out some way to do that, then that'd be really really cool. That'd be really tricky though.
Yes, it's the same as the "normal" scrolling effect that these games already use. They time the changes so that the squares seem to get bigger as they come closer, but if you change that timing you can get stretching effects quite easily.
tokumaru wrote:
I can't think of one single game that changes the palette midframe.
Crystalis?
tepples wrote:
Crystalis?
I didn't know it did. And I don't know how exactly it's done in Crystalis, but I'm sure there are a few games that change the palette from one "section" to the other (something like text boxes or status bars), but I really don't know about actually messing with the palette in the middle of the game/action screen. I can't think of one of those.
Where does Crystalis do it?
Condider midframe palette changine impossible. It actually isn't, but it is always best to consider it to be in a NESdev point. 4 BG palette is enough in 99% of case, regardless of what effects you're doing.
3D world runner does everything with horizontal scrolling.
It uses horizontal mirroring, and already have a pre-rendered sharped ground in the pattern table. You can slope it as you wish, making it possible to do this chessboard effect by changing the horizontal scroll regulary. It is changed every scanline with tricky self-modified code, I think. This is tricky, but not that complicated.
Vertical streaching can be possible if you mess with $2005/$2006 every scanline. Admiting you have a programm or a mapper that does the horizontal streaching for you, and you get mode 7 on the NES. But it is easier to say than to do, and that would consume a lot of CPU time.
Super Off Road and Fantastic Adventures of Dizzy change the palette mid-frame.
Turn off the screen to update the palette and get a multicolor line of glitch as palette[cur_VRAM_pointer & 0x1F] is rendered on the screen. It generally has to be done in hblank if at all, but the monochrome bit may be able to cover up most of the glitch.
Well... that'd result of an image with a flickering white scanline or something similar, and that wouldn't look too good.
So that's why I say consider it to be impossible in a NESdev viewpoint is better. I tried to do a programm that change just one color during HBlank inside a text box that could be used in RPGs, but the result wasn't brillant (especially that I didn't see it work on the real hardware, but Memblers did). Also, the time of one single scanline is very very short, and I think I just had time to get the next color to write, and effectivly write it during HBlank, then calculate the next scroll line. They were not cycles left, and since a PAL scanline is shorter than a NTSC from the CPU clock (3.2 ration instead of 3), it would be impossible to do in PAL.
In a NESemdev viewpoint, it would be totally different.
Well I can see how Cosmic Epsilon makes their stuff by using timed CHR bankswitches, but my question is this: How do they time it? Is there some sort of special equation that describes the rate at which something increases in size?
Celius wrote:
How do they time it? Is there some sort of special equation that describes the rate at which something increases in size?
Yes, and it's called similar triangles. All the Mode 7 games on the Super NES use the same technique, especially
Hyperzone.
tokumaru wrote:
I can't think of one single game that changes the palette midframe.
Wizards and Warriors I. In an emulator written under the assumption the palette could not change midframe:
here
I was looking around, and I saw that some people are interested in raycasting on the NES. How the heck are you supposed to do that? During Hblank? Isn't that like less than 1 cycle for each scanline? Since it's for every verticle line on the screen, am I wrong?
HBlank is about 21 CPU cycles long.
Raycasting has nothing to do with HBlank... There is no need to change the palette. Except if you wanted to change the color of the sky to the color of the ground by the middle of the screen, but even that isn't really necessary.
Raycasts are computed from side to side, horizontally, So I don't think HBlanks have anything to do with them, as they (HBlanks) can be used for vertical effects. My conception of a NES raycaster computes all the columns at once (while the previous frame stays on for a few NES frames) and when ready everything is drawn at once. There is enought time for the copy because there are many unused scanlines at the bottom of the screen wich are used to "extend" VBlank.
The illusion of more colors is created with dithering (since the "3D" resolution is so low, dithering looks very nice), so I don't think there is a need to change the pallete mid-frame. In fact, I can't see any benefit from it (aside from the sky-to-ground thing), as the walls will be displayed with different heights and that would make any palette change awkward.
Okay, I thought that raycasts were computed every vertical line of pixels. And this is very difficult to do on the NES, because you have very limited math. There really is no division that won't result as a whole number. So really complicated math is hard, because you have to round and whatnot. And you have to calculate the distance between you and a wall so many times (I've only read a little about raycasting). So yeah, I have to think for a while.
Celius wrote:
Okay, I thought that raycasts were computed every vertical line of pixels.
It should be every column of pixels, not rows. A screen is rendered from left to right, not top to bottom. It makes sense, since a column can only display one wall, while a row of pixels would span across many walls at diferent distances.
Quote:
And this is very difficult to do on the NES, because you have very limited math. There really is no division that won't result as a whole number. So really complicated math is hard, because you have to round and whatnot.
I spent a lot of time refining the basic raycasting algorithm, until I found a solution that uses no division (only multiplication, bit shifting and one binary search) and produces an 100% glitch-free image. I timed everything and this algorithm can run at around 12 frames per second, wich is enough for such a thing. The hardest part is the texture mapping (stretching a texture to fill the whole column). I have a bresenham algorithm ready, but althout it is very fast, it may drop the fps a little. I'm still looking for an optimal solution here.
Quote:
And you have to calculate the distance between you and a wall so many times (I've only read a little about raycasting). So yeah, I have to think for a while.
I reduced my resolution to 28 columns (each one is 1 tile wide). It's a very low resolution, but considering the machine we're working on, it looks OK.
For each column I have to load from a table the distances to the next vertical wall and the next horizontal wall, based on the angle. They are both multiplied and shifted, to find the first distances (the player is in the middle of a block so we should use only part of the distances at first). Then I keep looking at the level map and adding the full distances, until a wall is hit. When it's hit, I have the distance ready. This distance is already fish-eye corrected from the table (wich makes the table quite big). with the distance at hand, I do a binary serach for it to find the heigh of the wall (saves me a division). If not using textures, the wall can be drawn already. To use texture, the exact point where the wall was hit must be calculated, wich costs 2 more (low-precision) multiplications, I think. then comes bresenham for scaling the texture to the size of the wall.
It's a lot of calculation, but it's all very optimized. The distances must be handled with quite a lot of precision (I think I'm using 24 bits), but many operations (multiplications, mostly) done to them can be of low precision (6 or 8 bits) wich makes everything a lot faster.
Well, enough about that. Hopefully one day I can release this thing and everyone will understand! =)
Hey, sorry to bring this up again, but I've been working on a raycasting engine, and might as well not start another thread for it...
Okay, so I've been thinking of how one might go about raycasting on the NES. I was thinking of a method that only allows 8x8 maps, but it allows for a lot of moving space. Every square on the map has 64 possible locations you can be in. It's like a graphics tile. Your position can be any pixel in that tile. I'd have a table that would define every ray slope for every 2 degrees (My resolution is 32x240, and my FOV is 64 degrees). And when you cast a ray, it follows the slope pattern within the 64 possible positions. So, instead of being high precision like this:
It's low precision like this:
It may not seem like there's much of a difference, but it really does effect the resolution. If there were a ray cast in the high precision mode, it may hit the middle of a square, and you do the pythagorean theorem, and it's whatever length it is, and you plug that number into the raycasting equation. But then you cast another ray, and it hits a little right of the previous ray, but it still hits the same square. Do the pythagorean theorem, and the number will be slightly different than the last. Plug it in to the raycasting equation, and you'll draw a wall slice that's slightly lower than the previous one. It looks very nice that way. It looks a lot more resolute. But in the low precision method, every time that square is crossed with a ray, it will be the same distance, because it only checks if the square was hit, not where it was hit. Do you understand?
Sorry, got a little sidetracked there explaining that. But as I was saying... Say I cast a ray. It hits a wall. Now I have to find the distance. I was thinking of have the square roots predefined in a table, because it'd be alot faster. The table would be 4 kilobytes. 4096 bytes. That's a BIG ASS table. I don't think I'd even have the square roots predefined, I'd just have the wall height predefined. So say the nearest wall was 3x away, and 4y away. I could look in my table for the ray length like this:
.db $x $x $x $x $x $x..... ;Square roots predefined. Go 4 rows down.
...
.db $x $x $5 $x $x $x .... ;And 3 to the right. There's the ray length.
Or I could just have the wall height defined there. Because if I had a ray length of 5, the wall would be X high. It would always be that same height.
So yeah, maybe I'll do that.
Or I could do LONG ASS Division, and LONG ASS square root finding routines, which would take SO MANY CYCLES, you don't even want to think about it. I know of a way to find unwhole square roots, but to transfer that to 6502, it'd take a Binary to Decimal routine, and a Decimal To Binary routine, because it involves long division. And I don't have that. I think I'll just go with the table. I really don't want to make it though... I think I'll just make a NES program that will make the table for me, and I'll have to come up with a Decimal to Binary routine.
Do you need the square root at all? In many cases all you need is the ability to find which of two distances is greater, in which case you can work in distance squared just the same as plain distance.
Hi Celius.
I've been messing with raycasts for quite some time now. And I learned a lot about it. I managed to come with ways to handle EVERY possible glitch you see in bad coded raycasters. Let me share with you some things I learned.
Most documents about raycasters tell you to cast 2 rays, one looking for vertical walls and another one looking for horizontal walls. After that, you pick the closest distance and consider that your hit. The problem is that this method will result in glitchy corners (sometimes, even if only for one column, the program may detect that the wrong wall is closer, 'cause they are so closer to each other), no matter how high is the resolution you use. A while ago I coded a
raycaster for windows (right-click to download, change extension to "zip") wich suffered from this bug. I managed to avoid it, but not fix it back then.
The trick to NEVER missdetect walls is to trace both rays at once, as seen in
this guy's tutorials. These are much cleaner than the more well known tutorial found
here. The tutorials on the first link are very good, but the guy uses many mathematically complex things that should be overlooked when working on a NES version. Anyway, the part of his code that traces the rays is pure gold.
I managed to get rid of all divisions, and only kept a few (low precision) multiplications. My current design uses a table a bit smaller than yours. But my table is a table of distances. It holds the distance from one grid to the next, for all angles (half, actually, as the other half uses the same values). So instead of calculating the distance to the next grid, I just pick it from a table, and keep adding it to the total distance as the rays go. That way, when I get a hit, I already have the distance to the wall, with no further calculation (slow suare roots and all).
Another problem you usually find is that "fisheye lens" effect. To correct it, you have to multiply the distance by the cosine of the reletive angle (center of the screen is 0º). To get rid of that multiplication, I pre-fixed all values in the table, for the 14 possible relative angles. That's what makes the table so big. But this is another big gain: not only after I hit the wall may ray is ready, but it's also fisheye corrected!
The only catch with this table, is that you have to decimate the first distance, as the player will often be in between grids. For that I'll take the distance from the table, multiply by a low resolution (8-bit) version of the player's position withing the grid and then divide that by 256 (throw away the last byte). That is pretty quick.
With the distance in hands, you'd usually have to perform a division of a constant by that distance, to find the height of the wall. But since there are only a few possible heights (in my case, 128 for each half of the wall), I made a table containing the distance values that represent changing points in the height. A quick binary search in this table would give me the height of the wall. A division with the required precision would need something around 48 subtractions (shift-and-subtract division), but the binary search will take at most 7 subtractions. Much quicker.
The tough part, in my opinion, would be the texturing of walls. I made a very quick implementation of a bresenham scaling algorithm, but all the bit shifting would still make it a bit too slow on the NES. I'm still thinking of ways to improve that. Without the textures I'm sure the raycaster would be REALLY fast (more limited by the small ammount of stuff you can write to VRAM than by the speed of the raycasting algorithm itself).
Anyway, I have designed all sorts of tricks to make NES raycasting possible, but I haven't had the time to work on it. I don't even know why I wrote that huge ass post now... I guess it's because I never had anyone to talk about raycasters with.
These are all prototypes of NES raycasters. I don't have a prototype for my current design, as I haven't had time for that at all lately... If you want to take a look at my work on raycasters (again, rename to "zip"):
http://www.nesstuff.kit.net/nesray02.jpg
http://www.nesstuff.kit.net/nesray04.jpg
http://www.nesstuff.kit.net/nesray10.jpg
http://www.nesstuff.kit.net/nesray14.jpg
In spite of beeing made on a PC, these use the same logic and structure that would be used on the NES, as far as I can remember.
Anyway, I wish you good luck on the project, but i'll let you know it's not easy. If you want to talk about it, I'm here.
blargg wrote:
Do you need the square root at all?
Yes, if you use the pythagorean theorem. The raycasting equation is:
H = B/X * P
H - Height of wall slice
B - Block size (Like my blocks are 8x8x8)
X - Distance to block
P - Distance to the projection plane
And in order to find the distance, I find out the X distance, and the Y distance, and use the pythagorean theorem to find the average distance. But if you think about saving time, the square root actually IS NOT neccissary. Most raycasters just find the distance, and calculate the height of the wall with the equation. But this is unneccissary for a raycaster running on such a resolution, because you can just look up what the height of the wall would be if it was a certain distance away, since there aren't a billion distances. There are about 4096, though, and that is low considering that's every single distance on the map.
And if I was making a raycaster in something like C, or C++, I could probably save the space and use the equation, and probably make it look alot nicer. Besides, the resolution wouldn't be so bad because we wouldn't be dealing with tiles.
Sorry, if that doesn't answer your question, I'm not really sure what you meant...
blargg wrote:
Do you need the square root at all? In many cases all you need is the ability to find which of two distances is greater
After finding the smaller distance, the hipotenuse, you'd need to find the other sides of the triangle, to know what column of texture to use on that wall slice you hit, for example. If you don't use textures, the square root is not needed, I guess.
Celius wrote:
since there aren't a billion distances. There are about 4096, though
I use 3 bytes for the distance! That's 16777216 distances. If you go much lower than that you'll get jagged walls, I'm pretty sure. I don't think 4096 values is enough to produce clean walls.
Well, yes, actually, the walls are going to look much like the "Stuck in castle Nessenstein" demo on that one site (By the way, if you want to download it, you have to change the url to "whateverthesiteis/sicn.nes", because the link they have to the download is shot.). The game is actually going to resemble SICN alot. If you play the tech demo, the walls don't change shape as you turn. They just shift whats on the screen, and update a column. I was planning to just do that, and build detail off of that. Do you know what I mean? Like, I don't really mind having a not-so-hot looking raycaster, I will build off of it. I have to have the raycaster before I can add detail.
Oh, and by the way. Your raycasters were pretty cool. You could have really fooled me with that first one. I would've never guessed it wasn't real 3D. The maze one, that is. Oh, yeah, that was quite the maze actually. And your other ones, those should look pretty nice when they are on the NES...
The way I did it in SICN was to save the result of the casting into a buffer in RAM (the tiles that should be drawn). Once I had finished updating the buffer I would signal that by changing a variable and during the next vblank I write the buffer contents to the PPU.
It's been a while since I've talked about raycasting on the NES with anyone. But I have been thinking. Now that I have math routines for multiplying and dividing, this is SOOOO much easier.
Tokumaru, didn't you say yours was 12 FPS? That gives you 5 frames to do stuff. That is plenty of time. I'd say that's a decent looking frame rate as well. Frick man, I've made cartoons running at about 7 FPS, and you can hardly notice.
But, I've been thinking that I would use mirroring to my advantage. I'd calculate several columns, and put the tile values into RAM. I'd take a few frames to completely put the values on screen. If you store parts of the next frame on a name table that's off screen, then it will not be noticable. When you've finished putting the values down on the name table, set the scroll to that name table, and just put the values on the previous name table for the next frame.
When you write data to a name table that's off screen, will it still glitch during rendering?
Celius wrote:
But, I've been thinking that I would use mirroring to my advantage. I'd calculate several columns, and put the tile values into RAM. I'd take a few frames to completely put the values on screen. If you store parts of the next frame on a name table that's off screen, then it will not be noticable. When you've finished putting the values down on the name table, set the scroll to that name table, and just put the values on the previous name table for the next frame.
When you write data to a name table that's off screen, will it still glitch during rendering?
Writing to off-screen areas of the nametable is exactly how
Super Mario Bros. does its glitch-free scrolling. But you still have to write the data while PPU rendering is turned off. For a 3D game, I think you can turn rendering off a few lines early with sprite 0, and nobody will care.
Celius wrote:
Tokumaru, didn't you say yours was 12 FPS?
I calculated that based on the number of columns I had to draw and the ammount of calculations for each one. I don't remember if this takes into account the texture mapping though... it's been a while! I didn't code much of the raycaster, I think it went as far as calculating the distance to one column, but no rendering was ever done.
Quote:
That gives you 5 frames to do stuff. That is plenty of time.
I had 28 columns in my engine, and I think I could get about 7 of them ready in a frame. But those were perfect, no fisheye effect, no misdetected corners, or weird stuff like that.
Quote:
I'd say that's a decent looking frame rate as well. Frick man, I've made cartoons running at about 7 FPS, and you can hardly notice.
Yeah, for a 3D view on the NES, 12fps is good.
Quote:
But, I've been thinking that I would use mirroring to my advantage. I'd calculate several columns, and put the tile values into RAM. I'd take a few frames to completely put the values on screen. If you store parts of the next frame on a name table that's off screen, then it will not be noticable. When you've finished putting the values down on the name table, set the scroll to that name table, and just put the values on the previous name table for the next frame.
I had that in mind for my engine too. The frames alternated between the 2 name tables.
Quote:
When you write data to a name table that's off screen, will it still glitch during rendering?
Yes. That means that the only real advantage of alternating the name tables is that you don't see the screen being rendered from left to right, you see it all at once.
tokumaru wrote:
Celius wrote:
I'd say that's a decent looking frame rate as well. Frick man, I've made cartoons running at about 7 FPS, and you can hardly notice.
Yeah, for a 3D view on the NES, 12fps is good.
What objects will you be placing in the 3D view, other than walls?
tepples wrote:
What objects will you be placing in the 3D view, other than walls?
Me? None, for a long while, 'cause I'm not working on this until my current project is finished (or close to). I'm tired of switching from project to project and never finishing anything.
But objects were the main reason I put my raycaster aside. For the walls I was able to come up with formulas and tables that made everything much faster. No division at all was performed for the walls. The texturing would be done with an algorithm similar to Bresenham's line algorithm, with a few shortcuts for my particular case.
However, I wasn't so lucky with the enemies/objects. They'd each require at least 2 very long divisions, plus they'd have to be clipped by walls, and I couldn't think of any type of look-up table that would make these tasks faster.
I know raycasters aren't actually 3D, but they look and feel like 3D. I think 12 fps is a good framerate when I think of raycasters such as the one used in the Jurassic Park game for the SNES, which is quite slow. Of course that the one for the NES would be much less detailed.
Anyway, even if it isn't possible to add other objects, there are a few types of gameplay that can take place in a 3D maze that do not require any other objects to be present. Doors are pretty easy to make, as they are just a special case of walls.
Yeah, I was thinking of just making a maze for starters. The raycasting engine is what I care about right now. I can make a first person dungeon crawl, or a first person shooter if I want to. But that requires an engine. I think looking at the cool graphics is the best part.
I've been thinking about doing a wire frame game using the same concepts of raycasting. I keep track of points. These points are intersections for wires in the wireframe model. You take the X, Y, and Z variables, and use them to put the points where they should appear on screen. If you can get these points on screen, you can just connect the dots to make a wire frame model. That would be the hardest part about it. I know how to get the points on screen. It's just like a unit of texture on a wall. I created a Qbasic program that shows a couple points on screen that have X, Y, and Z coordinates, and I use the LINE function to connect the dots. It looks quite nice, and I'm quite confident that it's not just close-enough-to-3D. But that's a whole different story, I suppose.
Just something, I really don't think 12 FPS would be good. It may be okay for a movie, but NOT for any vido game (at least not an action oriented one). The slowest you would want would be 25 FPS for a responsive video game. Anything below would have the player smach his screen with his controller out of frustration of the game's unresponsivity.
And, what will look the worst between something with utterly skipped frames, and something with utterly skipped frame where you can see the refresh scrolling lines ? That won't make a very high difference. Unless you can render a 3D image with a fixeed tileset (or a large set of different fixed tilesets) I don't see much interest in it.
Bregalad wrote:
Just something, I really don't think 12 FPS would be good. It may be okay for a movie, but NOT for any vido game (at least not an action oriented one).
I think it is in this case because this is a game that feels like a movie (sorta). Only nowadays people are used to 3D shooters running at 120fps, but this is a game genre that allows decent gameplay at lower framerates.
Quote:
The slowest you would want would be 25 FPS for a responsive video game. Anything below would have the player smach his screen with his controller out of frustration of the game's unresponsivity.
Yeah, I agree with you, if we're talking about a platformer, for example. Play with some console raycasters, such as both "Zero Tolerance" games for the Mega Drive, or "Battle Frenzy"/"Bloodshot", also for the Mega Drive. They play a bit slow (don't know the exact frame rate), but they are playable. "Duke Nukem", also for the Mega Drive plays a bit faster. Try "Wolfenstein" and "Doom" for the SNES. Or "Jurasic Park", that becomes a 3D fighting game once you get inside the building.
No console raycaster is very fluid, but they're all playable. The NES would be no exception. I believe it could run at a decent frame rate, not the best 3D experience in the world, of course, but a nice thing to see the NES doing.
Quote:
And, what will look the worst between something with utterly skipped frames, and something with utterly skipped frame where you can see the refresh scrolling lines ? That won't make a very high difference.
The second option is worse, IMO.
Quote:
Unless you can render a 3D image with a fixeed tileset (or a large set of different fixed tilesets) I don't see much interest in it.
My raycaster uses a fixed tileset, so that only the name and attribute tables have to be updated, while the pattern table, which is very expensive to update, is left untouched. This results in walls that are not very detailed, but are good enough so that one can recognize the shape of the maze.
Rendering pixels to the pattern tables would be an interesting way to go for a raycaster on the NES, each frame could use a different side of the table, so that we can't see it being drawn. This would allow for a more detailed image and more colors could be achieved through dithering, but the 3D view would have to be smaller, specially considering that you have to display other things, such as the status bar. A mapper that allows switching between CHR-ROM and CHR-RAM would be great for this. Any cart with more than 8KB of CHR-RAM would be good, actually. I think the speed would be much worse if rendering pixels, though.
tokumaru wrote:
Play with some console raycasters, such as both "Zero Tolerance" games for the Mega Drive, or "Battle Frenzy"/"Bloodshot", also for the Mega Drive. They play a bit slow (don't know the exact frame rate), but they are playable. "Duke Nukem", also for the Mega Drive plays a bit faster. Try "Wolfenstein" and "Doom" for the SNES.
Wolf3D and
Super Noah's Ark are pixel doubled, but the engine is still effective.
Doom uses a coprocessor at 21 MHz.
Quote:
Rendering pixels to the pattern tables would be an interesting way to go for a raycaster on the NES
At least it's what
Faceball 2000 for Game Boy and Super NES appears to use.
Quote:
but the 3D view would have to be smaller, specially considering that you have to display other things, such as the status bar.
You can display the status bar with sprites.
Quote:
A mapper that allows switching between CHR-ROM and CHR-RAM would be great for this.
TQROM (the
Pinbot board) would be the best for this.
Quote:
=Any cart with more than 8KB of CHR-RAM would be good, actually.
That would be either CPROM (the
Videomation board) or Squeedo, or perhaps the NES Power Pak.
tepples wrote:
Wolf3D and Super Noah's Ark are pixel doubled, but the engine is still effective.
Yeah. My conception of the NES raycaster uses "pixels" that are 8x2 actual pixels. Not a very good resolution, but rendering much more than 28 columns would be too slow (each column represents a ray that is traced through the map, and that means a couple of multiplications, tons of additions and subtractions - depending on the distance from the wall slice). More than that would also make it impossible to use a fixed tileset, which would make it even slower.
Quote:
Doom uses a coprocessor at 21 MHz.
And still slow....
Quote:
At least it's what Faceball 2000 for Game Boy and Super NES appears to use.
Walls are not textured, which makes it so much easier. If the walls are not textured, you only need to render the edges of the walls with the different angles the walls can be seen at. But I think all console raycasters generate tiles on the fly... not sure.
Quote:
You can display the status bar with sprites.
Yeah, if they are not used to place enemies and objects in the level. Other consoles (Genesis & SNES) seem to use the background for that, but they have many more colors in their backgrounds. And making the objects with the background on the NES would also make it impossible to use that fixed tileset.
The pre-calculated tiles I use to make the background use almost all the tileset, there are only 14 free tiles, I think. And that is after I decided not to use a random effect on the floor, which would have used all 256. If the screen could be split after the 3D window, the lower part of the screen could use the other half of the pattern table for the status bar. But sharing that with the actual sprites would be hard, as they have different zoom levels that really increase the tile count.
CHR switching would be the way to go to have a detailed status bar/interface without giving up on sprites or any feature of the 3D view (such as the number of wall colors).
Getting all tiles redrawn would be awesome, but then you'd get a framerate as horrible as Final Fantasy 2's 3D world map (press B+Select after having gotten the ring).
You could use longer VBlank and stack-indexed $2007 writes à la Battletoads to get tricky and win refresh time (however I'd leave less time for the frame calculation itself).
Other than this, I have trouble seeing how you could render any ray-caster only with a CHRROM pattern table.
Oh, and I'd get for untextured walls and a higher framrate any time. It'd be a lot better if you ask me. (as long as they have a solid color, because if by "untextured" you mean wireframe, then ignore my previous senstence, because noting look as worse as wireframe does).
You could also have CHRRAM, but have a fixed tileset in the BG pattern table, and use sprites that are automatically streatched in the SPR pattern table. I think that could look good (but that would be almost impossible to do I guess). Else goes the Rad Racer way, with pre-streched sprites in the pattern table.
And something like this could definitely put the TQROM board to good use, (unlike, hem hem, Pinbot...)
EDIT :
[Tepples mode on]
Quote:
No console raycaster is very fluid, but they're all playable.
My [ Instert Playstation 2 game here ] copy seems to be very fluid.
[Tepples mode off]
I'm surprised he missed this one.
Bregalad wrote:
You could use longer VBlank and stack-indexed $2007 writes à la Battletoads to get tricky and win refresh time (however I'd leave less time for the frame calculation itself).
It should be possible to eat a lot of time from the rendered frame, since a raycasting view is usually much wider than taller, and a status bar shouldn't use much space either, so big chunks of the screen would be avaliable at the top and at the bottom.
However, what good would it be to have a lot of time to copy pattern table data, if that time comes from the time that would be used to calculate that data?
Quote:
Other than this, I have trouble seeing how you could render any ray-caster only with a CHRROM pattern table.
You have seen these, right? The resolution is far from perfect, but you can understand what's going on. These are mockups, made from the windows version of the raycaster, but everything can be drawn with this tileset (now that I look at it again, there sem to be 16 free tiles, at the end):
The limitations are that each slice can have only two shades of the same color, using a 1bpp texture. Also, no more than 3 different wall colors can be shown in the same frame, but this is dynamic and the engine will define the 3 colors as it renders the view. The levels have to be designed in a way that no more than 3 colors would be seen at once, or else something would look wrong.
Bregalad wrote:
[Tepples mode on]
Quote:
No console raycaster is very fluid, but they're all playable.
My [ Instert Playstation 2 game here ] copy seems to be very fluid.
[Tepples mode off]
I thought he'd say that too, so I had an answer ready: They are not
raycasters. =)
I even rephrased that part, as I was going to say "3D shooters", and that would have included the PS2 games.
That's really impressive. I guess 3 colors aren't so many however, but the textures are impressing.
Quote:
I thought he'd say that too, so I had an answer ready: They are not raycasters. =)
That's probably why he didn't say this (or at least I hope for him).
But then, what are they ? Ray-tracers ? I trought this would be impossible unless we got 300 GHz GPUs ?
Bregalad wrote:
That's really impressive. I guess 3 colors aren't so many however, but the textures are impressing.
It would be possible to use more colors with MMC5, where the colors of a column would have zero impact in the colors of it's neighbour. But with regular attributes, each pair of columns must use the same palette, and the palettes must include all possible combinations of the currently seen colors.
I don't think it looks bad, specially since the floor and the sky/ceiling can have one extra color. The thing is that 2 colors are fixed in all palettes: the color for the ceiling and the floor, and the color used for shading (usually black). The other two are modified to accommodate the different walls found during rendering.
I use 3 palettes for the 3D view, the 4th one is used for the interface around it. That means I have 3 pairs of colors to use per frame. Although that would be 6 colors, I have to worry about different colors that meet inside the same attribute block, so the only way to make sure the view can be correctly rendered is limiting it to 3 wall colors, so that pairs AB, BC and AC can handle every possible encounter of colors.
And this is the reason why every pattern in the pattern table comes in two colors (red and blue in the image I posted), 'cause you may need to draw it using the first slot of the pair of colors or the second.
Quote:
But then, what are they ? Ray-tracers ?
Raycasting is a way to fake 3D. As far as I know, newer 3D graphic cards (such as those used in newer consoles) work with actual 3D points and polygons, with mathematically correct formulas. I don't think that's raytracing.
EDIT: Here are two other mockups I have:
I'd really like to see that running on a NES, but I just can't think of a good game that doesn't include enemies. "Escape from the maze" is not cool at all... I think I have figured a way to include enemies/objects that don't move (I have to check my notes), and are always in the center of a block. This is already more interesting that no enemy/object at all! =)
I trought the 3 colors were for using BG color for shading and the 3 other colors for the 3 objects colors. Doing it AB, AC and BC as you said would allow two constant shading colors, instead of just one.
Or it is reserved for sky/ceiling ?
EDIT : For sprites I'd say go with enemies, and make them available at wide set of various distances. If done right, you'd need something like 6 different distances, and 2 different directions (up-left, and down-left, because up-right and down-right would just use horizontal flipping). That'd left room for a handfull of diferent enemies at a time.
Bregalad wrote:
I trought the 3 colors were for using BG color for shading and the 3 other colors for the 3 objects colors. Doing it AB, AC and BC as you said would allow two constant shading colors, instead of just one.
Or it is reserved for sky/ceiling ?
I'm not sure I understood what you said... but I have set up the palettes (3 of them) like this:
color 0: sky/ceiling/floor
color 1: wall color 0
color 2: wall color 1
color 3: shading
Colors 0 and 3 are fixed for the entire level (unless you want to modify color 0 halfway through the frame to have different ceiling and floor colors - most likely only possible using a mapper with scanline IRQ's).
The other 2 are filled in depending on the colors of walls that meet within attribute blocks. This is done as the pairs of columns are rendered. The only way to be sure the view can be rendered is to only allow 3 colors of walls at a time. If there were 4, for example, there'd be 6 possible pairs of colors meeting, but I only have 3 palettes for these encounters.
Code:
4 colors:
A B C D
A x x x
B x x
C x
D
AB, AC, AD, BC, BD and CD.
3 colors:
A B C
A x x
B x
C
AB, AC and BC.
And I can't even use the color of the ceiling/floor in the walls, because the tileset has room for all variations of 2 types of walls only, one that uses color 1 shaded with color 3, and one that uses color 2, also shaded with color 3.
With MMC5 and it's extended graphics mode, using the same 3 palettes and the same tileset it would be possible to use 6 colors for walls, since the attributes for each column are independent from other columns.
Quote:
EDIT : For sprites I'd say go with enemies, and make them available at wide set of various distances. If done right, you'd need something like 6 different distances, and 2 different directions (up-left, and down-left, because up-right and down-right would just use horizontal flipping). That'd left room for a handfull of diferent enemies at a time.
I believe that in such a limited environment as the NES, enemies could be done like in some versions of Wolf3D, where they were always facing you. A lot of tiles are already wasted because of scaling, and having the sprites face different directions would make it impossible to have more than 1 in the tileset, if that. Notice that in most raycasters, things are usually facing you, no matter the angle you look at them. Enemies are the main exception, usually, but this would be too heavy for the NES. No sneaking behind guards, I guess. =)
I'm starting to sound like I'm coding this thing now... O_o I have to focus on my platform engine, and then I'll code this! =)
If you limit yourself to four enemies per screen, you can use MMC3 CHR banking to switch sprite banks every time you switch sprite cels.
tepples wrote:
If you limit yourself to four enemies per screen, you can use MMC3 CHR banking to switch sprite banks every time you switch sprite cels.
Yeah, I though of doing this at some point... I was avoiding this 'cause I wanted to make a NROM demo of the engine first. But I guess that CHR switching and scanline IRQ's can really help a game like this.
It would be nice to see this on the NES. Of course the framerate may not be all that good, but that doesn't mean you can't do it just for the hell of it.
I had problems drawing more than 28 columns (I don't remember where the rows maxed out). But that didn't really have anything to do with the actual raycasting - I just ran out of vblank cycles to use for writing to the nametable.
mic_ wrote:
It would be nice to see this on the NES. Of course the framerate may not be all that good, but that doesn't mean you can't do it just for the hell of it.
I agree.
Quote:
I just ran out of vblank cycles to use for writing to the nametable.
Well, the columns take a few frames to be completely calculated, so there is no problem in writing them little by little (every vblank), to the name table that's not currently visible, and when everything is done, switching to it.