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?
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.
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.
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.
To white and to black, if needed. If not, then just to black.
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?
I attempted to make more than 4 steps initially, but it didn't looked good, so I'm interested too.
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).
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...
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.
Quote:
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.
Quote:
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.
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.
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.
Quote:
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?
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
Quote:
Quote:
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.
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.
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.
thefox wrote:
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.
I could show a demo of mine but it's like a $10 step fade (but you can set brightness to any value any time 0 black 8 white)
I tried smoothing out fades using the emphasis bits before, but wasn't very pleased with the results. The animation was very "flickery" and not smooth at all.
A trick that works wonders on systems with RGB palettes is to fade out the individual color components one after the other (i.e. first red, then green, then blue). A lot of Master System games and nearly all Genesis/MD ones do this, it looks incredibly smooth. Unfortunately this can't be done on the NES, since the palette is not RGB. Maybe if we could rearrange the colors to simulate an RGB palette we could use this trick, and in the end get the actual color value from a table before writing it to VRAM.
thefox wrote:
Anybody tried using the tint bits to add a little bit of smoothness?
Not if you want your game to work on a PlayChoice or a Famicom Titler.
Shiru wrote:
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.
It should add one extra step, if setting all of the tint bits at once, or 3 steps if setting them one at a time. The idea was to set the tint bits as the very first thing in the fade, then after that just fade out normally.
If you aren't doing anything during the fades, you can use timed $2001 writes to get tint on half the scanlines, which is like adding a half step.
thefox wrote:
The idea was to set the tint bits as the very first thing in the fade, then after that just fade out normally.
What I tried (and didn't look good) was repeating these 2 steps:
1. Set all emphasis bits;
2. Clear emphasis bits and reduce the brightness of all colors by 1;
We should keep in mind that the emphasis bits are problematic on the RGB PPUs.
I threw together a little demo to try out the RGB fade:
http://thefox.aspekt.fi/palette-fade.nes
Press A to do the usual "subtract $10 fade". Press B to do an RGB-fade. Hold down START while pressing either button to add the 3 additional tint steps in the beginning.
As to which one looks better, it's largely subjective, although using the tint bits definitely adds a lot of smoothness. I doubt an Average Joe would notice any difference...
It is definitely smooth, and additonal steps from the emphasis bits add extra smoothness. I would prefer 'subtract $10' version, though, because the RGB fade distorts colors, adds some greenish shade to them, albeit it looks smoother.
This is a demo of my system showing various palette effects from Megaman 2.
Up/Down to change brightness, SELECT to change "stage"
http://www.mediafire.com/?2hbtbebc83h66s7