Wolfenstein / DOOM for Oric : has this been done?
Re: Wolfenstein / DOOM for Oric : has this been done?
Excellent effort,
Like you said, with some recoding of the C part into assembly would allow possibly faster rendering and some sort of gameplay thrown in there.
Without knowing how the mapping part works, even a dungeon master style game looks more than feasable.
Like you said, with some recoding of the C part into assembly would allow possibly faster rendering and some sort of gameplay thrown in there.
Without knowing how the mapping part works, even a dungeon master style game looks more than feasable.
Amateurs built the Ark, Professionals built the Titanic.
rax engine + ray casting + glOric
Hi all,
Playing with raycasting and rax engine within a glOric scene.
Only 2 times overclock to record the following screencap:
Sober Mode : Color Mode : Running out of memory ..
Playing with raycasting and rax engine within a glOric scene.
Only 2 times overclock to record the following screencap:
Sober Mode : Color Mode : Running out of memory ..
High Performance Ray Casting On Oric
Hi all,
I'm very glad to release the C source code of a brand new ray casting system dedicated to Oric computers.
I've been working hard over the past few month on how to do ray casting in the most suitable way for Oric.
I started from the equations and try to find the smartest possible way to implement them on the 8 bits processor of the Oric computer.
I came up with a solution which, IMHO, fits nicely the performance of this incredible machine.
In the attached demo, I use Dbug's rendering routine for ultra fast Hires performance.
The source code of this demo is here : I'm currently working on an assembly language version of this ray casting system.
Stay tuned.
I'm very glad to release the C source code of a brand new ray casting system dedicated to Oric computers.
I've been working hard over the past few month on how to do ray casting in the most suitable way for Oric.
I started from the equations and try to find the smartest possible way to implement them on the 8 bits processor of the Oric computer.
I came up with a solution which, IMHO, fits nicely the performance of this incredible machine.
In the attached demo, I use Dbug's rendering routine for ultra fast Hires performance.
The source code of this demo is here : I'm currently working on an assembly language version of this ray casting system.
Stay tuned.
- xahmol
- Flight Lieutenant
- Posts: 437
- Joined: Sun Jun 28, 2020 7:32 pm
- Location: Utrecht, The Netherlands
- Contact:
Re: Wolfenstein / DOOM for Oric : has this been done?
Great work! Looks superb!
What a huge step in looks compared to the post before.
What a huge step in looks compared to the post before.
Last edited by xahmol on Sat Nov 14, 2020 7:53 pm, edited 1 time in total.
- ibisum
- Wing Commander
- Posts: 1655
- Joined: Fri Apr 03, 2009 8:56 am
- Location: Vienna, Austria
- Contact:
Re: Wolfenstein / DOOM for Oric : has this been done?
Astonishing accomplishment, even more binoculars to consider where this will lead to next!
Re: Wolfenstein / DOOM for Oric : has this been done?
I must say this is impressive indeed. Great work!
Re: Wolfenstein / DOOM for Oric : has this been done?
Congrats! (Glop-Glop! )
Re: Wolfenstein / DOOM for Oric : has this been done?
It's moving very well, congratulations
- coco.oric
- Squad Leader
- Posts: 720
- Joined: Tue Aug 11, 2009 9:50 am
- Location: North of France
- Contact:
Re: Wolfenstein / DOOM for Oric : has this been done?
JB, you're incredible.
What you've done is a fantastic performance on our lovely computer. This game rendering machine will give ideas to creators for sure.
Thanks for opening a new world on Oric
What you've done is a fantastic performance on our lovely computer. This game rendering machine will give ideas to creators for sure.
Thanks for opening a new world on Oric
coco.oric as DidierV, CEO Member
Historic owner of Oric, Apple II, Atari ST, Amiga
Historic owner of Oric, Apple II, Atari ST, Amiga
Re: Wolfenstein / DOOM for Oric : has this been done?
Thank you all for your warm and kind comments.
It is very encouraging and honouring.
I'll keep you posted of new developments when they deserve to be shown.
I can already announce that I:
- solved the memory problem and fastened the ray tracing by translating into assembly language some big part of my C code (I got back 8 ko !! ).
- integrated rax engine
I recently had a bugfixes period (following the porting in assembly language) and now I'm going to work on:
- 3D animated scene
- Rendering enhancement
So it should worth staying tuned .. I hope ..
It is very encouraging and honouring.
I'll keep you posted of new developments when they deserve to be shown.
I can already announce that I:
- solved the memory problem and fastened the ray tracing by translating into assembly language some big part of my C code (I got back 8 ko !! ).
- integrated rax engine
I recently had a bugfixes period (following the porting in assembly language) and now I'm going to work on:
- 3D animated scene
- Rendering enhancement
So it should worth staying tuned .. I hope ..
Re: Wolfenstein / DOOM for Oric : has this been done?
I am quite impressed and interested in this project. As I told before I always wanted to experiment with this in the Oric, but never got the time (did not write a single line of code!). So I am going to ask a few questions
For what I understand, raycasting is a matter of tracing rays from the player's point of view. Usually you set an angle of view of 60 degrees and divide it into the visible columns. In the Oric the max would be 240, but I if you use full scans it could get down to 40. The thing is tracing the ray in the map in the correct direction and check when it collides with a wall. Then you have distance and wall information (colour, texture, whatever). I guess you can use distance to decide brightness and use a pattern to draw the column (either pixel-wide or scan-wide or something in the middle), but most importantly to decide its height. There is a correction with the cosine of the angle so walls in front of you look flat. All that *could* be done at a decent speed in the 6502, I imagine: angles are fixed, so all needed values can be stored in tables, and there are some data structures which can be used to optimize the process of casting the ray (beyond drawing it on the map until you hit something).
If I understood correctly, you optimized all this process with a different approach. Could you elaborate a bit more on this? I am curious.
I always thought the worst part was the rendering. I think the demo is drawing full scans to achieve this speed, thus the ragged borders of the walls. They may work anyway if the speed is kept as it is in the demo. I wonder how flexible the current method is as to be used in a game. For instance, is it double buffered? Can other sprites be rendered with the map? Some sprites will be partially covered with walls... How does using scans instead of one-pixel columns behave when the player wants to aim an enemy? Are you mirroring up and down halves of the viewing area? Could elevations be used? (moving up/down a bit while walking would look terrific).
I was thinking about using a completely unrolled list of sta to draw a column and jump to the drawing code at a given address to start at a given height and end at a given position (patching the sda with an rts, for instance), but that might work well when using a single scan value for all the column.
What about patterns? You can have simple patterns or textures and "scale" them with distance (drawing 1 row every n rows when you are far), but that means more code. And, unless the pattern is constant horizontally, you'll need to figure out which column of the graphic is needed. That should not be too difficult as your map may contain not only wall/nowall, but different values for pattern slices. However, this process looks a bit complex (in CPU time) and more difficult to optimize.
As you can see, I find this quite exciting, so I am eager to learn
For what I understand, raycasting is a matter of tracing rays from the player's point of view. Usually you set an angle of view of 60 degrees and divide it into the visible columns. In the Oric the max would be 240, but I if you use full scans it could get down to 40. The thing is tracing the ray in the map in the correct direction and check when it collides with a wall. Then you have distance and wall information (colour, texture, whatever). I guess you can use distance to decide brightness and use a pattern to draw the column (either pixel-wide or scan-wide or something in the middle), but most importantly to decide its height. There is a correction with the cosine of the angle so walls in front of you look flat. All that *could* be done at a decent speed in the 6502, I imagine: angles are fixed, so all needed values can be stored in tables, and there are some data structures which can be used to optimize the process of casting the ray (beyond drawing it on the map until you hit something).
If I understood correctly, you optimized all this process with a different approach. Could you elaborate a bit more on this? I am curious.
I always thought the worst part was the rendering. I think the demo is drawing full scans to achieve this speed, thus the ragged borders of the walls. They may work anyway if the speed is kept as it is in the demo. I wonder how flexible the current method is as to be used in a game. For instance, is it double buffered? Can other sprites be rendered with the map? Some sprites will be partially covered with walls... How does using scans instead of one-pixel columns behave when the player wants to aim an enemy? Are you mirroring up and down halves of the viewing area? Could elevations be used? (moving up/down a bit while walking would look terrific).
I was thinking about using a completely unrolled list of sta to draw a column and jump to the drawing code at a given address to start at a given height and end at a given position (patching the sda with an rts, for instance), but that might work well when using a single scan value for all the column.
What about patterns? You can have simple patterns or textures and "scale" them with distance (drawing 1 row every n rows when you are far), but that means more code. And, unless the pattern is constant horizontally, you'll need to figure out which column of the graphic is needed. That should not be too difficult as your map may contain not only wall/nowall, but different values for pattern slices. However, this process looks a bit complex (in CPU time) and more difficult to optimize.
As you can see, I find this quite exciting, so I am eager to learn
Re: Wolfenstein / DOOM for Oric : has this been done?
Yes but I was targeting the insane speed rather the decent one.
Dbug's ray casting system uses this very smart approach of ray casting which consists in actually shooting a ray until it hits a block.
My first work had been to rework his demo. I speeded it up a bit and start to fix a little bit the stairs effect. I showed my code to Dbug and he didn't feel like making it available on defence-force repository.
I was very impressed by his principle of filling column by using a patched entry point adress in an unrolled columnn filling routine.
I was also seduced by his idea of actually casting the ray and I still think it is the most efficient approach for tight labyrinths made of block.
I considered that the render routine couldn't possibly be improved (on the speed point of view) so I decided to rather look for an optim on how to compute the distance.
Just like you've just done, I told to myself that the calculation *could* be done at a decent speed in the 6502. Rather than casting the ray, it should be possible to find the distance by computation rather than deduction.
But the problem with this approach is that we have to compute the distance for all wall, for all slice of screen. So the calculation really has to be fast to compete with the iterative approach which automatically find the first wall that cross the ray.
- Computing the distance rather than deducing it.
- Find the most optimized way to compute the distance with a good-enough accuracy
On this second point, I think the two key points are:
- Doing all calculation on logarithmic scales because it avoids division and additions while preserving comparison with native processor instruction.
- Avoiding fixed math arithmetic as long as a pure 8 bits calculation is possible.
And I can witness that the second point was difficult because the C compiler use fake 8 bits type of data.
And truncated 16 bits arithmetic is not the same as 8 bits arithmetic in some case.
For example, when dealing with angle rollover .. the overflow flag of the processor is very valuable and the C compiler doesn't give an easy way to work with it. I had to write things like:
Code: Select all
if (abs(lAngle[RayIdXPoint2] - lAngle[RayIdXPoint1]) > 127){
which is pure non sense because lAngle are signed char values .. but which does what I was wanting:
Code: Select all
"ldy _RayIdXPoint1;"
"lda _lAngle,Y;"
"sta reg7;"
"ldy _RayIdXPoint2;"
"lda _lAngle,Y;"
"sec;"
"sbc reg7;"
"bvc VeryWideAngle_03;"
The other very powerful stuff I found (and finally not used) is that:
sin(alpha).cos(beta) - cos(alpha).sin(beta) = sin (alpha - beta)
I was ignorant of this trigonometric relation and re-discoved it as I was looking for a way to do ray casting on non-aligned walls. It turns out that the quantity sin(alpha).cos(beta) - cos(alpha).sin(beta) is very important in this case and the fact that it can be calculated with sin (alpha - beta) can save lots of cycle. There's a function exploiting this trick in the code I provided .. but it is not used because I decided to keep only aligned walls.
NB: this quantity is also very important in texture mapping. I had encountered it when working on texture .. so .. maybe not lost
I have the same questionning .. that's why I'm exploring a text mode rendering in which I could use glOric's z-buffer and frame buffer which are already armed to deal with sprites partially covered with walls and stuffs like that.Chema wrote: ↑Sun Nov 15, 2020 9:46 pm I always thought the worst part was the rendering. I think the demo is drawing full scans to achieve this speed, thus the ragged borders of the walls. They may work anyway if the speed is kept as it is in the demo. I wonder how flexible the current method is as to be used in a game.
At the output of the ray casting procedure, there are two arrays. Each array gives, for each slice of screen:
- the wall number that is crossed on this slice,
- the distance at which it is crossed,
The array with the distance can be used as a one dimension z-buffer to help selecting part of the sprite that are visible. If the distance of the object represented by the sprite is greater than the one in the zbuffer at a given slice index, then the sprite is not visible on this slice.
rendering 3D scene with 1D RayCasting consist in exploiting scene symetry .. so the elevation cannot be used .. but I presume there must be a way to displace things by offsetting addresses either in a kind of post processing step or when the screen buffer is copied to the screen memory.
That's allmost exactly what the Dbug's weapon does.Chema wrote: ↑Sun Nov 15, 2020 9:46 pm I was thinking about using a completely unrolled list of sta to draw a column and jump to the drawing code at a given address to start at a given height and end at a given position (patching the sda with an rts, for instance), but that might work well when using a single scan value for all the column.
He doesn't even have to patch for the rts because he draws the columns by the two sides. he draws one pattern at the top, then one pattern at the botton .. starting from highest and lowest ones and ending with the middle of the screen. So the rts remains at the same place .. its just en entry point adress that is dynamically calculated. It's terribly efficient.
Code: Select all
_DrawColumn
sta $a000+0,x
sta $a000+7960,x
sta $a000+40,x
sta $a000+7920,x
sta $a000+80,x
sta $a000+7880,x
....
rts
I had the idea of using a pattern principle that could allow to:Chema wrote: ↑Sun Nov 15, 2020 9:46 pm What about patterns? You can have simple patterns or textures and "scale" them with distance (drawing 1 row every n rows when you are far), but that means more code. And, unless the pattern is constant horizontally, you'll need to figure out which column of the graphic is needed. That should not be too difficult as your map may contain not only wall/nowall, but different values for pattern slices. However, this process looks a bit complex (in CPU time) and more difficult to optimize.
- create separate texture for different wall
- deal with adaptative darkness depending on the distance
It consists in chaining drawing pattern into cycle based on the number of bit at one.
the chain would be build so that nextPattern[Vn+1] = Vn with nbOfBitSet(Vn) == nbOfBitSet(Vn+1).
the drawing procedure would then look like:
Code: Select all
_DrawColumn
sta $a000+0,x
sta $a000+7960,x
.(:tay: lda _nextPattern,y:.):
sta $a000+40,x
sta $a000+7920,x
.(:tay: lda _nextPattern,y:.):
....
rts
https://github.com/jbperin/rewall/tree/changePattern
But I failed to make it work nicely as you can see in this attached TAP file.
I don't think I can teach you something. I'm just very glad that this project caught your attention and honoured that you find it impressive. You impressed me so much with your games ..
Re: Wolfenstein / DOOM for Oric : has this been done?
It's not MY ray casting system. It's just my (not very efficient or accurate) implementation of something that has been around for a decade.
And so was it for my own version. It never made it to the shared routines folders because it was not good enough.
I only put on the svn repository what is:
- Runs fast enough
- Relatively free of bugs
- Easy to use or integrate with another program
As long as your version stayed at the cool prototype demo the was no point to add it on the global repository because there was still some serious fish eye distortion problems and it was still not easy to integrate any object in the scene.
As I said casting the ray is not my idea, even Wolfenstein 3D (1992) worked that way.jbperin wrote: ↑Mon Nov 16, 2020 12:44 am I was very impressed by his principle of filling column by using a patched entry point adress in an unrolled columnn filling routine.
I was also seduced by his idea of actually casting the ray and I still think it is the most efficient approach for tight labyrinths made of block.
That being said, for the unrolled STA, it has probably done by other people but I came up with this solution myself.
Re: Wolfenstein / DOOM for Oric : has this been done?
I'm starting to put all stuff together : ray casting + glOric + rax engine + mymplayer. It is getting slow but it is not yet optimized. So there remains hope.
https://odysee.com/Oric3dMusic:a
The worrying stuff is that integrating mym player creates unexpected artefact.