Fade in, fade out

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Wave
Posts: 110
Joined: Mon Nov 16, 2009 5:59 am

Fade in, fade out

Post by Wave » Thu Nov 10, 2011 7:29 am

I have the unmodified palette on RAM and update each frame the modified palette to upload it to the PPU with a "darkness" value.
The darkness value is used to select the actual color from a 4 step "darkness" table (that avoids $0D color), but instead of doing this in the vblank, I have 2 palette buffers.

What do you do to fade palettes?

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Post by Shiru » Thu Nov 10, 2011 8:02 am

A buffer in RAM to be able to use different palettes with the same code, the table of brightness, and an unrolled loop that takes correspoing values from the table and write them into VRAM.

Wave
Posts: 110
Joined: Mon Nov 16, 2009 5:59 am

Post by Wave » Thu Nov 10, 2011 8:04 am

Shiru wrote:A buffer in RAM to be able to use different palettes with the same code, the table of brightness, and an unrolled loop that takes correspoing values from the table and write them into VRAM.
Is that table to white and to black or only to black? I also use an unrolled loop to write the VRAM values.

User avatar
tokumaru
Posts: 11520
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Nov 10, 2011 8:13 am

I have a number of virtual brightness levels ranging from full black to full white, and a table indicating how the colors have to be modified for each of these levels. Since I do more than linearly modify the brightness bits, I have 10 or so steps (instead of the typical 4) in each direction (black or white).

I do the color modifications in real time as I upload the palettes to VRAM, which means that palette updates take considerably more time, and have to "fight" for VBlank slots just like name/attribute/pattern table updates do. the advantage is that I don't waste RAM with the modified palette, or part of the frame's time to modify the palette.

If you're not tight on RAM or CPU time, your way is probably better.

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Post by Shiru » Thu Nov 10, 2011 8:13 am

To white and to black, if needed. If not, then just to black.

Wave
Posts: 110
Joined: Mon Nov 16, 2009 5:59 am

Post by Wave » Thu Nov 10, 2011 8:28 am

tokumaru wrote:I have a number of virtual brightness levels ranging from full black to full white, and a table indicating how the colors have to be modified for each of these levels. Since I do more than linearly modify the brightness bits, I have 10 or so steps (instead of the typical 4) in each direction (black or white).

I do the color modifications in real time as I upload the palettes to VRAM, which means that palette updates take considerably more time, and have to "fight" for VBlank slots just like name/attribute/pattern table updates do. the advantage is that I don't waste RAM with the modified palette, or part of the frame's time to modify the palette.

If you're not tight on RAM or CPU time, your way is probably better.
And how do yo generate the 10 steps table?

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Post by Shiru » Thu Nov 10, 2011 8:43 am

I attempted to make more than 4 steps initially, but it didn't looked good, so I'm interested too.

User avatar
tokumaru
Posts: 11520
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Nov 10, 2011 9:25 am

Heh, at first I tried to alternate hue modifications with brightness modifications (i.e. darker is bluer, lighter is yellower). This looked pretty good, but wasted a lot of space with tables, and was too slow to calculate at update time under certain conditions.

Now I change just the brightness, but instead of modifying the whole palette at once, I change only colors of a certain brightness each frame. Based on the assumption that darker colors will reach complete darkness first when fading out, I first change all $0x colors to black. On the next frame I change all $1x colors to $0x. On the next frame, $2x becomes $1x, then $3x becomes $2x. At this point, the whole palette has shifted 1 brightness level down, and you can repeat the process. It takes 10 or 11 frames (can't remember) for the whole palette to become black, and it looks surprisingly smooth.

I also have some special handling for the grays, since the gray scale is not like the others. I also ignore the whole $xD column, not only because $0D is evil, but also because not all PPUs have those colors (the RGB PPUs I think).

Wave
Posts: 110
Joined: Mon Nov 16, 2009 5:59 am

Post by Wave » Thu Nov 10, 2011 9:48 am

So, instead of decreasing the whole palette in a frame you do it in 4, one for each 16 colors. Is this done using tables?

Also I've implemented a byte to activate which palettes you want to modify, so you can dark the background and let the sprites colorful like in MegaMan 2 (or dark only half background, and so on)

Next thing I'm planning to do are Palette "timers" so you can configurate on the fly wich palettes are rotating (to left or to right) or maybe more effects than just rotating like switching the last colors, like also on MegaMan2 Metalman stage background gears.

With this I hope be covering most of palette effects...

User avatar
tokumaru
Posts: 11520
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Nov 10, 2011 11:00 am

Wave wrote:So, instead of decreasing the whole palette in a frame you do it in 4, one for each 16 colors. Is this done using tables?
Yeah, the first "wave" takes 4 frames, but the second one takes 3, since one row is already black. The 3rd takes 2 frames, and the 4th only 1 frame. This is where the 10 step figure comes from: 4 + 3 + 2 + 1 = 10.

I use 2 tables for this. One of them has the output brightness for each of the 4 possible input values. Depending on the desired level of virtual brightness I point to a different part of this table. The second table is used to convert from a temporary format to the actual format used by the NES. The temporary format is used to easily/quickly manage the grays and make colors black and white as they reach the end of the fading sequence.
Also I've implemented a byte to activate which palettes you want to modify, so you can dark the background and let the sprites colorful like in MegaMan 2 (or dark only half background, and so on)
This is an interesting idea. I don't have anything like that, the fading routine I described is global. If I want to have individual palettes fading I have to directly modify the colors in RAM. Some objects might have to do that.
Next thing I'm planning to do are Palette "timers" so you can configurate on the fly wich palettes are rotating (to left or to right) or maybe more effects than just rotating like switching the last colors, like also on MegaMan2 Metalman stage background gears.
I have something like that... but either the level or objects control these animations.

tepples
Posts: 21842
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Thu Nov 10, 2011 11:07 am

I just subtract $10 every frame and apply three special cases: $F0->$02 (dark gray into dark blue), $80-$FF->$0F (colors that have reached black), and $0D->$0F (to protect sync integrity). This also allows a distinction in the palette between $20, which is ordinary white, and $30, which shows up as superbright white during fades.

User avatar
tokumaru
Posts: 11520
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Thu Nov 10, 2011 11:15 am

tepples wrote:I just subtract $10 every frame
What about fading in? You start from black and compare against the target values every frame? Where are the target values stored? I never liked the approach of modifying the RAM copy of the palette because fading in and fading out are very different processes.
This also allows a distinction in the palette between $20, which is ordinary white, and $30, which shows up as superbright white during fades.
Are you saying that we should avoid $30 just like we avoid $0D?

tepples
Posts: 21842
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Thu Nov 10, 2011 11:51 am

tokumaru wrote:
tepples wrote:I just subtract $10 every frame
What about fading in? You start from black and compare against the target values every frame? Where are the target values stored?
If a 32-byte update slot is open:
1. Query the level and all on-screen objects for their palette, storing the result in that update slot
2. Run the fade routine on that update slot with $10, $20, or $30
This also allows a distinction in the palette between $20, which is ordinary white, and $30, which shows up as superbright white during fades.
Are you saying that we should avoid $30 just like we avoid $0D?
No, just use it sparingly for when you need something to be just that bright.

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox » Thu Nov 10, 2011 8:51 pm

Anybody tried using the tint bits to add a little bit of smoothness? Setting all of them (or setting more and more of them gradually) as the first steps of the fade out might work. This of course would only work for global fades.

It would be interesting to see demo ROMs of different fade techniques.

Shiru
Posts: 1161
Joined: Sat Jan 23, 2010 11:41 pm

Post by Shiru » Thu Nov 10, 2011 9:29 pm

I recall tried to use it, but in the emulator I was used for testing it was looking the same as one step lower brightness, so it didn't added any extra steps.

Post Reply