New demo uploaded: Wolfenstein 3D - raycasting demo with textures

All aspects of programming on the Commander X16.
Ed Minchau
Posts: 503
Joined: Sat Jul 11, 2020 3:30 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by Ed Minchau »


I wanted to illustrate what this shortcut does, so I took the starting screen from Jeffrey's demo and marked it up a bit in Paint.  First, there would be four rays cast a using the normal method, marked here in red in the first file below.  A is column 0, B is column 256, C is column 288, and D is column 304.  Note that the display is only columns 0 to 303 so 304 is not actually displayed, just used for interpolation if possible.

The second image shows where the interpolation happens.  Ray E is column 128.  First, we check the high byte of the distance value array corresponding to this column; these will all be set to FF at the start of a screen and only changed if a ray is calculated.  So in this case column E has not already been calculated.  We look to the left and right, rays A and B, and see if they point to the same wall.  They do not, so we cast the ray for E and move on to the next one, ray F in column 64.

Once again we check if this ray is already calculated, nope, and then check to the left and right, A and E.  These two are not on the same wall, so we cast ray F and move on to ray G.  Ray G, in column 192, has not been calculated yet (its distance high byte is still FF) so it checks to the left and right, rays E and B.  These are not pointing to the same wall, so we cast ray G and move on to ray H.

Ray H is in column 32.  We see that it has not been calculated yet, so we check to the left and right, columns A and F.  These two rays are indeed pointing to the same wall, so we can interpolate all the rays in between A and F.  Now if we go further down the list and find ourselves at a column that has already been interpolated, such as column 16, the high byte of its distance will no longer be FF, and that entry in the list is skipped.

These interpolated pixel columns are marked in yellow in the second image.  Eventually ray Y (column 272) will be encountered, and comparing B and C shows that they are on the same wall so columns 257-287 are all interpolated.  And when Z comes up on the list, all columns from 289-303 would be interpolated.

The third image shows all 39 columns that would have to be raycast as red vertical lines, and the 266 interpolated columns are shown in yellow across the bottom - an 87% reduction in the number of rays cast.

Edited to add: this is probably pretty representative of an average.  305/(log(305)/log(2)) ~ 37

startscreensmall2.bmp startscreensmall3.bmp startscreensmall4.bmp

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by ZeroByte »



6 hours ago, Ed Minchau said:




Basically, if you have two rays that hit the same wall, then all the rays between those two are calculated with one multiplication and one addition for the image column choice



My method was based on yours - I just wanted to think of a way that would generate less rays to keep track of. Plus calculating the center of the new range is trivial (min + max) >> 1

Your illustrations and estimated code complexity are quite interesting. It makes a lot of sense when you see it illustrated like that. The ultimate goal is to cast as few rays as possible.

SlithyMatt
Posts: 913
Joined: Tue Apr 28, 2020 2:45 am

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by SlithyMatt »



6 hours ago, Ed Minchau said:




20 fps is 400000 cycles though, and I think you'll be able to hit that easily with this method



And I think that would still exceed the performance of the original Wolf3D. That was more like 15 fps, at best.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by ZeroByte »



6 hours ago, Ed Minchau said:




The fastest you can push the data to VERA for the whole image is about 260000 cycles, so 30fps wouldn't leave any time to calculate anything else.  20 fps is 400000 cycles though, and I think you'll be able to hit that easily with this method, with time left over to calculate bad guys and pew pews and sound effects etc.



Gotta have those pewpews!

And regarding sound - the PCM SFX are going to be "more expensive" for X16 than PC because the Soundblaster used DMA - the Wolf3d source just sets up DMA in the SB and lets it rip - but that does mean there's only ever one digital sound playing at a given time - so when the SS guard laughs "Hoo Haw haw!" - and you start shooting before he finishes laughing, the laugh gets cut off by the gunshot.

Ed Minchau
Posts: 503
Joined: Sat Jul 11, 2020 3:30 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by Ed Minchau »



2 hours ago, ZeroByte said:




I gather that "same wall" is implied to mean "same face of same tile" and not any tile in the same plane as the first one.



Yes.  You'd have to keep track of the map block hit and the side of the block; two rays that hit the same block on different faces can't  be interpolated between. 

BruceMcF
Posts: 1336
Joined: Fri Jul 03, 2020 4:27 am

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by BruceMcF »



16 hours ago, ZeroByte said:




Gotta have those pewpews!



And regarding sound - the PCM SFX are going to be "more expensive" for X16 than PC because the Soundblaster used DMA - the Wolf3d source just sets up DMA in the SB and lets it rip - but that does mean there's only ever one digital sound playing at a given time - so when the SS guard laughs "Hoo Haw haw!" - and you start shooting before he finishes laughing, the laugh gets cut off by the gunshot.



YM2151 pew-pews are a lot cheaper. SS guard laughing would still be PCM, though.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by ZeroByte »



8 hours ago, BruceMcF said:




YM2151 pew-pews are a lot cheaper. SS guard laughing would still be PCM, though.



Wolf3d used a combination of OPL and Digitized SFX. The sound files actually contain all SFX in 3 versions each: PC Speaker / Adlib / Digi and the playback routine chooses from the 3 based on which modes are available. So there's an OPL noise that equates to the SS guard laughing (it's just a kind of alarming ding sound though). Some SFX didn't have digital versions at all, such as the sounds it makes when you collect treasures / ammo / weapons, etc.

Since the OPL has 9 voices, Id reserved voice 0 for Adlib SFX and the music just didn't use that channel. The YM2151 only has 8 voices, which works out great for the music playback, but the Adlib SFX would either have to be multiplexed in by the engine, or else maybe the PC Speaker SFX equivalents could be used exclusively but emulated on the PSG. Gotta admit tho - the digital SFX really make a huge difference in the experience, so I'd still try to include those if I were doing this project. Not sure how much overhead it's going to take just to keep that PCM stream going. Like I said in my earlier post - the SB used DMA to play them back but the X16 doesn't have that luxury so it remains to be seen if enough CPU time is going to be available for PCM SFX at all.

Fortunately, though, which SFX are available in which formats is hard wired in the source code, so a port could pick and choose which SFX to ignore the PCM versions if you wanted to keep that to a minimum - but I think if you include any at all, you may as well include them all because whenever those SFX -do- play, you're going to get slowdown then.... it'd be something to play around with.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by ZeroByte »


okay - I finally hit a milestone with my IMF to YM2151 conversion experiment. After much banging around in registers and tracking down mistakes with bit shifting, etc, I have gotten "first light" - the driver produces sound and the voices are actually closer to the original than I would've guessed. I had to bootstrap it by just pre-loading a single pitch on all voices, so it's not actually playing the tune yet because I haven't implemented translating the frequency from OPL-speak to OPM-speak. (they're VERY different). Hopefully I can have that done tonight and post a video of it doing its thing - then it will be time to start improving the fidelity, using the LFO, etc. I plan to use the VERA PSG to do the percussion channels but that's going to come later.

As someone else said in some other thread here recently - debugging audio sucks! It doesn't work until suddenly it does - lol.

Ed Minchau
Posts: 503
Joined: Sat Jul 11, 2020 3:30 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by Ed Minchau »



On 3/25/2021 at 9:03 PM, Jeffrey said:




FYI: the next couple of days I will be very busy IRL ?



I've been looking through your code; I think I understand it enough to write some tables and subroutines for you.  One thing I noticed in ray.h:


Quote




extern u8 _banked_ram[8096];



That should be 8192, no?

Anyhow, I'll generate the data tables and subroutines needed for the interpolation and will post them here soon.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

New demo uploaded: Wolfenstein 3D - raycasting demo with textures

Post by ZeroByte »


The OPL->YM2151 playback driver is a success!

It has some tweaking to be done, and I ended up cheating and generating a LUT for the YM equivalents of the OPL frequencies because I just couldn't think of a way to do the math in the X16 when I can't use floats or longs. You have to multiply two 16-bit values together and divide by 2^(20-x) - the OUTPUT of this is 16-bit but the process requires up to 32 bits. And concert pitches are almost all floats (226.84Hz, etc). So PHP to the rescue - loop through the entire possible frequencies the OPL can make and have a LUT that returns the YM equivalents. It could be better, as the YM can pitch shift between notes too, so this program is not a 100% OPL emulation, and actually can never be, as the OPL has some strange waveforms.

The Wolf3d tune comes out sounding pretty damned close though - except that the emu still uses 4Mhz for the YM clock so the pitch is wrong.

I'm going to touch a few things up tomorrow and post the results.

Post Reply