Tech demo: Real-time sprite scaling
Moderator: Moderators
Tech demo: Real-time sprite scaling
Sprite scaling wasn't a hardware feature of the NES or most other 2D consoles until the Super FX coprocessor and Game Boy Advance PPU. It was on the Neo Geo AES, but that's about it. But that doesn't mean there isn't a reasonably efficient way to shrink sprites in software. I got the idea from a post by psycopathicteen to look up each byte of the tile through a lookup table that shrinks a bit plane. The Sega Master System/Game Gear has to do something similar just to flip sprites; on that platform, sprite scaling would be effectively free.
Up and Down control size; Left and Right step through frames.
Up and Down control size; Left and Right step through frames.
- Attachments
-
- scaling-wip.zip
- (24.59 KiB) Downloaded 1136 times
Re: Tech demo: Real-time sprite scaling
I have no idea how you managed to make it this fast, but it's impressive. Back when I tried to roto-scale an image on the NES it was extremely hard to do and very slow.
Why do you have a fetish for legless people recently ? I find personally this is kinda ugly but this doesn't matter for the demo.
Why do you have a fetish for legless people recently ? I find personally this is kinda ugly but this doesn't matter for the demo.
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: Tech demo: Real-time sprite scaling
Nice work!
I did some simple scaling on the PCE for a title screen (replicating the Lunar SegaCD title screen), but I used packed pixel scaling and then converted to planar in realtime. It was slow, but fast enough for title screen stuffs.
This LUT method works out pretty decent. I ran some numbers of some quick code (more PCE geared) after seeing this, and along with a special WORD element shift table, I was able to drastically cut down the number of cycles compared to my old code.
Anyway, stuff like this would have been nice to see back in the day. Relatively easy to use and would be great for non cpu intensive parts in games; more than just demo scene stuff.
Got any ideas for rotation of planar graphics?
I did some simple scaling on the PCE for a title screen (replicating the Lunar SegaCD title screen), but I used packed pixel scaling and then converted to planar in realtime. It was slow, but fast enough for title screen stuffs.
This LUT method works out pretty decent. I ran some numbers of some quick code (more PCE geared) after seeing this, and along with a special WORD element shift table, I was able to drastically cut down the number of cycles compared to my old code.
Anyway, stuff like this would have been nice to see back in the day. Relatively easy to use and would be great for non cpu intensive parts in games; more than just demo scene stuff.
Got any ideas for rotation of planar graphics?
Last edited by tomaitheous on Mon Dec 01, 2014 5:34 pm, edited 1 time in total.
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
Re: Tech demo: Real-time sprite scaling
That's because you tried rotation at the same time. Rotation is slow, but Neo Geo scaling is fast on NES. I precompute each 8x1 pixel strip scaled down to widths 7, 6, 5, and 4, and then I apply that to each bitplane. It's actually limited more by vblank time than by anything else.Bregalad wrote:I have no idea how you managed to make it this fast, but it's impressive. Back when I tried to roto-scale an image on the NES it was extremely hard to do and very slow.
Did you have a chance to look at my topic about shearing?tomaitheous wrote:Got any ideas for rotation of planar graphics?
Discussion about the appearance of the character in the demo can go here or here.
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: Tech demo: Real-time sprite scaling
I took a second look at this. Ok, so you avoid shifting and ORing the 8 pixel down scaled segments by using sprite positions to compensate for this (horizontally)? I thought it was a more brute force method. Also, why stop at 50% shrink?
The method I was doing required a shift table with 8 positions (split table with LSB/MSB) for ORing the WORD (shifted BYTE) with the data buffer together. The 8pixel planar value (byte) was loaded directly into X and used to access a the shift table (ldy idx ; ldx 8pixel_data,y ; ldy scale,x ; ora shift.lsb,y ; etc),. The shift table is kinda big (4k), with MSB of the table address (both tables) using the offset value from a counter for quick dirty addressing. And a little bit of self modifying code to shave a few cycles. It doesn't save a whole lot of cycles, compared to doing a 4bit (byte expanded) linear scale and then converting planar afterwards (4bit planar). But for NES 2bit planar format, it'd probably be decent enough in savings. Still not as quick as this sprite offset method you have here, but would lend itself to background rendering.
The method I was doing required a shift table with 8 positions (split table with LSB/MSB) for ORing the WORD (shifted BYTE) with the data buffer together. The 8pixel planar value (byte) was loaded directly into X and used to access a the shift table (ldy idx ; ldx 8pixel_data,y ; ldy scale,x ; ora shift.lsb,y ; etc),. The shift table is kinda big (4k), with MSB of the table address (both tables) using the offset value from a counter for quick dirty addressing. And a little bit of self modifying code to shave a few cycles. It doesn't save a whole lot of cycles, compared to doing a 4bit (byte expanded) linear scale and then converting planar afterwards (4bit planar). But for NES 2bit planar format, it'd probably be decent enough in savings. Still not as quick as this sprite offset method you have here, but would lend itself to background rendering.
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
Re: Tech demo: Real-time sprite scaling
For Super NES, you'll need to use a bit more force by shifting the right half of each 16-pixel-wide unit by a power of 2 to the left. The memory-mapped multiplier should work fine for this: store the shift amount ($01, $02, $04, $08, or $10) in $4202 before starting, then store the (scaled) right half of each 16x1 sliver the sprite into $4203, scale the left half, and read the shifted right half out of $4216. For an architecture without a multiplier, you might have to use a self-modifying shiftslide for this part.tomaitheous wrote:Ok, so you avoid shifting and ORing the 8 pixel down scaled segments by using sprite positions to compensate for this (horizontally)? I thought it was a more brute force method.
Because at that point you need to drop down to the next smaller prescaled step in your mipmap so as to avoid excessive overdraw.Also, why stop at 50% shrink?
Know what else would lend itself to background rendering, at least on Super NES? Mode 7.[My own technique was] Still not as quick as this sprite offset method you have here, but would lend itself to background rendering.
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: Tech demo: Real-time sprite scaling
Meh - mode 7. It takes the fun out of everything
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
Re: Tech demo: Real-time sprite scaling
Tepples I understand how you can use lookup tables for this but I see two major drawbacks :
1) This requires a lot of lookup tables, or, it can only shrink to very few scales
2) This does not work for vertical shrinking
3) There is no way you can expand sprites this way
Nevertheless it's still awesomely simple, I can't believe no game ever used this technique when it was so simple. This would also apply on SNES or any other 2d console without sprite scaling capabilities but bitplane based graphics.
This technique could/should also be used to do other effects to sprites, for example mosaic.
1) This requires a lot of lookup tables, or, it can only shrink to very few scales
2) This does not work for vertical shrinking
3) There is no way you can expand sprites this way
Nevertheless it's still awesomely simple, I can't believe no game ever used this technique when it was so simple. This would also apply on SNES or any other 2d console without sprite scaling capabilities but bitplane based graphics.
This technique could/should also be used to do other effects to sprites, for example mosaic.
-
- Posts: 592
- Joined: Thu Aug 28, 2008 1:17 am
- Contact:
Re: Tech demo: Real-time sprite scaling
The SNES could easily make due with a slower routine, and just cache the frames to WRAM (128k is a nice chunk) for whatever level/area.
__________________________
http://pcedev.wordpress.com
http://pcedev.wordpress.com
Re: Tech demo: Real-time sprite scaling
You really just need tables for 8 (identity), 7, 6, 5, and 4, after which you jump down to the next size and use the 8, 7, 6, 5, 4 table on that.Bregalad wrote:I see two major drawbacks :
1) This requires a lot of lookup tables, or, it can only shrink to very few scales
Of course it does. After each row I copy, I add between 0/256 and 255/256 rows to the skip variable, skipping a row when it overflows.2) This does not work for vertical shrinking
Or on a Neo Geo. (And that's three )3) There is no way you can expand sprites this way
Re: Tech demo: Real-time sprite scaling
Can't you drop the 4 as well? (since 4 in the current size would be the same as 8 in the next size)tepples wrote:You really just need tables for 8 (identity), 7, 6, 5, and 4, after which you jump down to the next size and use the 8, 7, 6, 5, 4 table on that.
Re: Tech demo: Real-time sprite scaling
Do you really need a table for identity? It's identity, nothing is changing.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!