Genny and 3D

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Post Reply
Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Sun May 20, 2007 10:34 am

Yeah, sorry if I messed a bit the topic too...
Anyway, there is a lot of reasons to keep cool :)
Rendering the 3D characters to layer B is possibly the only time consuming thing. You may have to mask the character against the background, but a pseudo z-buffer could easily be created with each screen. And, depending on the scene, it could be a simple mask/don't mask bit per pixel.
Why not using sprites for characters then? And leave planeA & B for background&foreground?
Using sprites would allow more tricks like this : upload top of character if top is moving, upload bottom of character if bottom is moving..
Also, sprite can have palette tricks while backgrounds are more limited...
Another advantage is that sprites can be placed at any X/Y in real time, even if the drawing rate don't fallow...
In other words :
Even if the drawing rate of each sprite (average) is 4fps, the player can feel something quite smooth :)


Off topic :
In a case of a starwing game, nobody took a look at shadow/stellar-assault 32x and the way the programmers rendered the earth/sun atmosphere? This method seems quite simple, use few colors, and it is very immersive and impressive... (if you havent reached the last level, nevermind... i'm just asking in the case someone saw the last sun level).

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sun May 20, 2007 12:25 pm

Fonzie wrote:Yeah, sorry if I messed a bit the topic too...
Anyway, there is a lot of reasons to keep cool :)
Super cool. 8)
Fonzie wrote:Why not using sprites for characters then? And leave planeA & B for background&foreground?
It's ingenious. Welcome to the next level. :wink:
Fonzie wrote:Off topic :
In a case of a starwing game, nobody took a look at shadow/stellar-assault 32x and the way the programmers rendered the earth/sun atmosphere? This method seems quite simple, use few colors, and it is very immersive and impressive... (if you havent reached the last level, nevermind... i'm just asking in the case someone saw the last sun level).
For Shadow Squadron (in Fusion): 1029CA:E005 (enable the code, then hard reset)

Shiru
Very interested
Posts: 786
Joined: Sat Apr 07, 2007 3:11 am
Location: Russia, Moscow
Contact:

Post by Shiru » Sun May 20, 2007 9:54 pm

TascoDLX wrote:*WE* were speaking of an RE-like game, not a game that requires such a method. Don't quote me unless you mean it.
OK, sorry, I lost in thread a little.

About 'RAM means nothing'. I don't state what we need 640KB to implement RE-like game on SMD, of course - you right about difference between cartridge-based (all data directly available in CPU address space) and other (data can't be addressed directly by CPU) type of systems. However, in case with limited RAM size we need to do tricks to reduce RAM usage - as you said, we can't make fullscreen raster buffers for all planes (they just don't fit into VRAM/RAM), so we need to work around somehow. This workaround means more complicated renderer. So, more RAM means simpler and faster rendering, and it's no 'nothing', although I'm agree that it less important than CPU speed in case of SMD.

Generally you right, with your idea it's possible to fit in available VRAM/RAM and avoid of BG updates, to make something RE-like. Anyway, for now I don't believe that it's possible to make something similiar even to AiTD on SMD because of rendering speed in games and tests which already exists for SMD.
TascoDLX wrote:Honestly, I don't see why this should be different than any other game. The only difference is that the characters/objects need to be rendered. Otherwise, they are sprites and don't need to overwrite the background (or foreground).
There is difference that BG in RE-like games is not a tile-based, and size of 'sprites' (buffers for rendered objects in case of your idea) is not pre-determined - more VRAM needed, or additional calculations to manage available VRAM on fly.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Mon May 21, 2007 12:25 am

Shiru wrote:
TascoDLX wrote:*WE* were speaking of an RE-like game, not a game that requires such a method. Don't quote me unless you mean it.
OK, sorry, I lost in thread a little.
No problem. This thread is bouncing in all directions.
Shiru wrote:About 'RAM means nothing'.
Perhaps that was a bit glib. I just meant that PC mem specs are for the most part incomparible to console mem specs, at least when speaking of base memory. I agree that RAM management is always important.

For the record, AITD requires 560KB out of 640KB memory free, not that it's a significant difference.

As for the CPU speed (which is also generally incomparible), the game reportedly uses keyframe interpolation to animate its characters. It would be interesting to know what tricks the game uses to render its characters and whether or not you can get decent speed using a different approach to the animation.
Shiru wrote:
TascoDLX wrote:Honestly, I don't see why this should be different than any other game. The only difference is that the characters/objects need to be rendered. Otherwise, they are sprites and don't need to overwrite the background (or foreground).
There is difference that BG in RE-like games is not a tile-based, and size of 'sprites' (buffers for rendered objects in case of your idea) is not pre-determined - more VRAM needed, or additional calculations to manage available VRAM on fly.
Yes, VRAM would probably need to be allocated dynamically. I can't imagine having enough VRAM for a swarm of zombies but a game like AITD, where there are very few characters on the screen, seems more feasible.

cdoty
Very interested
Posts: 117
Joined: Wed Nov 29, 2006 2:54 pm
Location: Houston, TX
Contact:

Post by cdoty » Mon May 21, 2007 3:40 pm

Shiru wrote: I know how this type of games work, and I also like Resident Evil-like games and played many of them.
I think you've completely missed this point.

Just because the PSX or N64 versions did something a certain way doesn't mean the GBA version has to do the same thing. There was also a WIP GBC version, do you think they did 3D on that one also?

They simplified the concept down to the hardware; making trade offs where they had to. One obvious trade off is using 2D environments.

Maybe it would be better to switch the discussion to Final Fantasy 7 which 'definitely' used 2D environments with 3D characters. See http://en.wikipedia.org/wiki/Final_Fantasy which says:
Final Fantasy VII, Final Fantasy VIII, and Final Fantasy IX used pre-rendered and pre-painted backgrounds over which 3D models were overlaid.

I was one of the programmers behind Revenant (http://www.mobygames.com/game/windows/revenant), so I do understand the 3D character over a 2D background engine concept.

Shiru
Very interested
Posts: 786
Joined: Sat Apr 07, 2007 3:11 am
Location: Russia, Moscow
Contact:

Post by Shiru » Tue May 22, 2007 5:08 am

cdoty wrote:
Shiru wrote: I know how this type of games work, and I also like Resident Evil-like games and played many of them.
I think you've completely missed this point.
Ok, I say more exaclty: I know, how games-with-prerendered-backgrounds-and-3d-models work, and I also like such type of games, which includes FF7-9, RE1-3, PE1-2, and so on.
cdoty wrote:Just because the PSX or N64 versions did something a certain way doesn't mean the GBA version has to do the same thing.
In video on youtube game looks as original version with reduced resolution and character model details level. So it must work same way as original version.
cdoty wrote:There was also a WIP GBC version, do you think they did 3D on that one also?
GBC has many versions of games of famous series, which only use name of this series, and has completely different engine/gameplay. For example, Driver, GTA, etc.
cdoty wrote:They simplified the concept down to the hardware; making trade offs where they had to. One obvious trade off is using 2D environments.
Resident Evil games used pre-rendered (2D) enviroments from beginning of series, on all platforms, until Code Veronica.
cdoty wrote:Maybe it would be better to switch the discussion to Final Fantasy 7 which 'definitely' used 2D environments with 3D characters.
FF7-9 has slightly more advanced engine than RE, which also allows to use prerendered movies as backgrounds (player can walk on background while movie play).
cdoty wrote:I was one of the programmers behind Revenant (http://www.mobygames.com/game/windows/revenant), so I do understand the 3D character over a 2D background engine concept.
This game seems isometric, in this case we have less problems to integrate 3D models and 2D BG (no need for walkmesh and Z-sort planes, usual isometric rendering algorithm works fine).

cdoty
Very interested
Posts: 117
Joined: Wed Nov 29, 2006 2:54 pm
Location: Houston, TX
Contact:

Post by cdoty » Wed May 30, 2007 3:50 pm

Shiru wrote:
cdoty wrote:I was one of the programmers behind Revenant (http://www.mobygames.com/game/windows/revenant), so I do understand the 3D character over a 2D background engine concept.
This game seems isometric, in this case we have less problems to integrate 3D models and 2D BG (no need for walkmesh and Z-sort planes, usual isometric rendering algorithm works fine).
The tiles have z-buffer and normal values for each pixel. The base zbuffer is adjusted based on the position of the tile in the map.

Inigo Montoya
Newbie
Posts: 2
Joined: Sat Mar 31, 2007 7:05 am

Post by Inigo Montoya » Sun Jun 17, 2007 3:08 am

Shiru wrote:
cdoty wrote:Just because the PSX or N64 versions did something a certain way doesn't mean the GBA version has to do the same thing.
In video on youtube game looks as original version with reduced resolution and character model details level. So it must work same way as original version.
Just because it looks the same doesn't mean it is the same! There are many ways to achieve the same effect; this is true of almost everything.

peekpoke
Interested
Posts: 37
Joined: Fri Feb 01, 2013 1:11 am

Post by peekpoke » Mon Feb 18, 2013 5:48 pm

I tried to port Jeremy A Burns' LCD Raycaster

Just changed sine/cosine, square root calculations to precalc lookup tables. Also created lut for bitmap2tile coords translation.
Changed everything to integer math. Also changed few constants, which used in calulations to pow 2 aligned, so instead of using div/mul, use bitwise shift.
O3 flag for compiling.
And still not playable at all - max fps 3 :lol:

Used old Stef SGDK (GenesisDev04).


Here is result:
raytest.bin

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Mon Feb 18, 2013 6:28 pm

Raycasting is one of those things that HAS to be pure assembly on such a low-end processor. The entire render loop would need to be converted and tuned.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Feb 21, 2013 12:02 am

I was looking at LCDWolf3D peekpoke mentioned toward making a demo for direct color dma on the CD and noticed this:

Code: Select all

void drawSlice( uint8_t screenX, SLICE *slice )
{
        uint8_t offsetY   = ( slice->sliceHeight >  64 ) ? ( 0 ) : ( 32 - ( slice->sliceHeight >> 1 ) );
        uint8_t overflowY = ( slice->sliceHeight <= 64 ) ? ( 0 ) : ( ( slice->sliceHeight - 64 ) >> 1 );
        
        for( uint16_t y = 0 ; y < slice->sliceHeight && y < 64 ; ++y )
        {
            if( GET_WALL_DOT( textures[ slice->textureId ] , slice->textureOffset , ( ( y + overflowY ) << 6 ) / slice->sliceHeight ) )
            { 
                SET_PIXEL( screenX, offsetY + y );
            }
        }
}
Look at the inner part of the for loop for drawing the slice:

Code: Select all

            if( GET_WALL_DOT( textures[ slice->textureId ] , slice->textureOffset , ( ( y + overflowY ) << 6 ) / slice->sliceHeight ) )
Unless you (peekpoke) got rid of that divide, THAT is the main source of slow-down on your MD version. A divide for EVERY SINGLE PIXEL DRAWN?? You're LUCKY to get 3 FPS. :lol:

If you look at column renderers (like W3D or Doom), they turn that divide into a delta increment in fixed point which is added to the offset each loop. If the fixed point shift is the same as the shift for making the Y component for the texture, you only need to AND off the lower bits each loop.

peekpoke
Interested
Posts: 37
Joined: Fri Feb 01, 2013 1:11 am

Post by peekpoke » Thu Feb 21, 2013 6:32 am

Thank you very much!

To be true, i didnt get rid of that divide fully. Im really very noob in programming, just read somewhere that div is much slower (few times maybe?) than mul, so here was the first idea of "optimising" this divide - i just changed it on mul by precalc lut for 4096/sliceHeight :roll:
So, it looks like this:

Code: Select all

temp2 = divlut[slice->sliceHeight]; //divlut[n] - precalc lut for 4096/n;

//bla-bla-bla

GET_WALL_DOT( tex_wood, slice->textureOffset , ( (( y + overflowY ) << 6 ) * temp2 )>>12)
But now, thanks for your tip, ill try to look at those methods you mentioned, and finally remove this mul.

To be true, i also tried to remove this GET_WALL_DOT at all (i.e. render just transforms into plain untextured version) - but it didnt gave any great boost. Yes, average fps became 4-6, and even add smooth in movement, but its not what expected at first.

Ill try to send u my source - but im not sure that ull find it any useful (because everything i try to code is very lame) :D But, maybe at least, u will have some fun from this xD

Btw, Chilly Willy - thank you very much for everything you do for console dev scene! I already tried to use your gcc cross toolchain tutorial for 68k/sh2 - its very useful and helpful. Also, I want to try later write some hello world for saturn. So, thank you for your help to libyaul project - im sure it will be very great to use this open library with current gcc to write something for saturn. And, the very great thing - that u always release source code for all your console projects - its very very helpful to anyone who interested in learning programming! Really, Big Respect for your work and thanks!


Btw N2. I also tried to port Matt Westcott's wolfy. It already used fixed point math, so, i just changed sine/cosine to precalc lut. Same below playable performance - but just let it be here:

raytest3.bin

..little offtopic update. Just tried to port this LCDWolf to saturn, using gcc 4.6.2 toolchain, created using Chilly Willy instructions. I didnt use any existing saturn library - just used vdp initialisation from Charles MacDonald's saturn samples, and Bart Trzynadlowski's linker script and crt0 code. And as result - without any further tweaks this raycaster runs very smooth xD If someone wants to check, here it is (tested on Yabause, just upload it in ram and execute):

raysat.bin

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Feb 21, 2013 7:39 pm

This isn't tested yet, but this is how I changed drawSlice()

Code: Select all

void drawSlice( uint8_t screenX, SLICE *slice )
{
        uint8_t offsetY   = ( slice->sliceHeight >  64 ) ? ( 0 ) : ( 32 - ( slice->sliceHeight >> 1 ) );
        uint8_t overflowY = ( slice->sliceHeight <= 64 ) ? ( 0 ) : ( ( slice->sliceHeight - 64 ) >> 1 );

        register uint8_t heightY   = ( slice->sliceHeight >  64 ) ? ( 64 ) : ( slice->sliceHeight );
        register uint16_t textureInc = ( 1 << 12 ) / slice->sliceHeight;
        register uint16_t textureY =  ( overflowY << 12 ) / slice->sliceHeight;
        register uint16_t *texturePtr = &textures[ slice->textureId ][ slice->textureOffset ];
        register uint16_t *screenPtr = &screenBuffer[ offsetY * 322 + screenX + 8 ];

        while( heightY )
        {
            register uint16_t c = texturePtr[ textureY & ~63 ];
            *screenPtr = c;
            screenPtr += 161;
            *screenPtr = c;
            screenPtr += 161;
            textureY += textureInc;
            heightY--;
        }
}
I'll have to try your Saturn bin... I have the USB dev cart for my Saturn. :)

peekpoke
Interested
Posts: 37
Joined: Fri Feb 01, 2013 1:11 am

Post by peekpoke » Thu Feb 21, 2013 9:08 pm

Thx!

Tried this method right now. Seems that there is some problems with pointers in gcc 3.4.6 (included in GenesisDev04), so - quick copypaste+adaptation (changed my "blit" routine to draw from new screenbuffer to tilebuffer first, also removed double pixel addition for test) didnt worked at first. Seems that it loops forever in this while( heightY ). Im almost sure it have something with pointers in 3.4.6 (its why i changed those textures pointers to ugly and lame switch case routine instead :lol: ).

So, i quickly moved to 4.6.2 version. It didnt hangs anymore in while( heghtY) but draws only few pixels on screen, which updates when u move camera, but still u see only 5-10 pixels randomly on screen. Seems that i need to somehow tune math...
Ok, need to go sleep now, will try to continue tommorow!

Thank you very much again!

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Feb 21, 2013 11:32 pm

Some old versions of gcc had trouble with certain conditional constructs - you might try while( heightY != 0 ). I'm too used to using ( value ) when I mean either ( height != 0 ) or ( height > 0 ) depending on how the variable is used. In this case, the height is decremented until you reach 0. Notice that heightY is either slice->sliceHeight, or 64 if the sliceHeight is > 64. Notice that the last thing in the loop block is decrementing heightY.

Post Reply