Gradual color change

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Gradual color change

Post by DRW »

In my next game, there are several sections that might use different colors, but where you can still move from one section to the other without a hard cut.

For this, I'd like to do a color change like in "Link's Awakening DX":
www.youtube.com/watch?v=YzEU19PUVuE&t=13m19s

Do you know of any automatic algorithm with which I can do the color change for an NES palette?

I'm not talking about how to put this into PPU. I'm talking about a good way to transform one color into another one.

Let's say I have color $05 in one screen and color $2A in the next. And I want to change one color into the other one with two steps in between. But I don't want to build a manual lookup array of every single color tranforming into every other color.

Is there some automatism I can apply here?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Gradual color change

Post by tokumaru »

Grays excluded, the NES palette is circular, like a color wheel, so you can generally, "slide" left or right (whichever way is shorter) to morph one hue into another. The brightness can also be animated like this, as we usually do when fading.

If you want a fixed number of steps between 2 states, you'll have to calculate the difference between the source and target values (hue and brightness separately) and then find N intermediary points in those ranges.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

tokumaru wrote:Grays excluded, the NES palette is circular, like a color wheel, so you can generally, "slide" left or right (whichever way is shorter) to morph one hue into another.
Yeah, that might be a way. Thanks for the tip.I never noticed that the palette actually equals a color wheel.
tokumaru wrote:The brightness can also be animated like this, as we usually do when fading.
When I want to fade into black, I would do the following:
Subtract each color value with 16. If the upper four bits are 0, then the next step will be that the color becomes black.
Is this how you would do it as well?
tokumaru wrote:If you want a fixed number of steps between 2 states, you'll have to calculate the difference between the source and target values (hue and brightness separately) and then find N intermediary points in those ranges.
Could be a bit difficult with 48 usable colors. I guess it's not really necessary that every color has the same number of steps.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Gradual color change

Post by pubby »

It would be easiest to precompute the palettes needed rather than computing them on the fly. Do what Tokumaru said, just don't try doing it in assembly.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

pubby wrote:It would be easiest to precompute the palettes needed rather than computing them on the fly.
That's exactly what I want to avoid: Manually designing each color change for each section combination.
pubby wrote:just don't try doing it in assembly.
What does the programming language have to do with it?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Gradual color change

Post by Bregalad »

You should separate the palette entry between the "hue" (low nybble) and "luminousity" (high nybble) components, and slide those separatedly. Luminosity is the easier, since you just add or substract one, until you get to the number you want.

Hue is a bit more complicated, but doable. The "lazy" way is to simply add one until you get the number you want, if you attain the $0d column reset to the $01 column. But this can take a long time as you might rotate through the entiere palette doing this. So in order to be quicker, you'd want to compute the "distance" between the hues, and go either left (+$01) or right (-$01) through the palette columns, taking the shorter path. In the worst case where the hue difference is 6, the distance is the same in either direction. In the case either the start or target column is $00 it's a special case because you have to jump in our out of this column at some point. Similarly, the colour black $0f is a special case.

The effect as a whole can have a duration up to 6 steps, but you'll have to find a way to stay at the target hue and/or saturation once you reach them, just like you can stay to black when fading the palette out.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

Yeah, the description that you gave is what I would have done anyway after the above hints:
Distinction between horizontal and vertical values.
And finding the shortest path.

I just don't know yet how I should decide which way to take when the other color is six steps away.
And what to do if a color has to move into white, gray or black.

Also, I'm not sure whether I should update each color whenever possible (so that a color that goes through six steps actually shows all six steps) or whether I should declare some fixed points in the transition where all colors are updated (so that the six steps are only done in memory, but only three of them are shown on the screen).
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Gradual color change

Post by Bregalad »

DRW wrote: Also, I'm not sure whether I should update each color whenever possible (so that a color that goes through six steps actually shows all six steps) or whether I should declare some fixed points in the transition where all colors are updated (so that the six steps are only done in memory, but only three of them are shown on the screen).
Unless the effect needs to be faster than 6 frames, I do not see the point of not showing all steps.
I just don't know yet how I should decide which way to take when the other color is six steps away.
It really doesn't matter, you just have to pick one "preferred" direction that applies in those cases.
And what to do if a color has to move into white, gray or black.
The simplest is to avoid using those colours in the palettes that will go through your effect ^^. If you still need those colours with the effect, you'll have to handle the cases individually and code them as special cases.

Another way would be to have your own luminosity that extends the NES luminosity, for example it accepts values 0 to 5, but when display it you convert it to NES palette, for instance $0x always convert to $0f, $1x converts to $0x, and so forth until $4x which converts to $3x, and eventually $5x which converts to $30.

That still doesn't solve the problem of jumping to and from the gray column, but at least it allows easily fading to and from black, as well as to and from white, using the normal algorithm, but you just have to convert your palette colour before displaying it.

Using the same concept you could extend this and have a full HSL palette internally, do a gradual change there and "convert" it to NES palette before displaying, however I do think it's overkill. But if you really need smooth transitions and you need support for all colours including black, whites and grays, this is the most appropriate solution.
Something like this pseudocode to convert from HSL to nearest NES palette colour.

Code: Select all


convert_HSL_to_NES(H, S, L):
   if L == L_MAX :
      return $30

   elseif L == 0 :
      return $0f

   else if S < SAT_MAX :
      return (L*3/L_MAX) << 4

   else :
      hue = 12*H/H_MAX + 1
      lum = 4*l/L_MAX
      return lum << 4 + hue      
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

Bregalad wrote:Unless the effect needs to be faster than 6 frames, I do not see the point of not showing all steps.
Because in this case, the colors will switch at many different times. Not only will there be more or less steps. But colors that are six steps away will be updated at other times from colors that are four steps away.
Bregalad wrote:The simplest is to avoid using those colours in the palettes that will go through your effect ^^.
Unlikely.
Bregalad wrote:If you still need those colours with the effect, you'll have to handle the cases individually and code them as special cases.
Well, yes, but making something up for handling these cases is the interesting part. Actually programming it is not an issue.

I don't think I'll have some kind of internal abstract palette. I'll simply invent something for the grey values.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
Dwedit
Posts: 4922
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Gradual color change

Post by Dwedit »

Image
Why yes, NES palette, I see you clearly in the YIQ color plane. Divide it into twelfths.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Gradual color change

Post by tokumaru »

Since the grayscale columns in the NES palette are all fucked up, I usually give hue 0 special treatment, and I use a look-up table to convert brightness values into the final hardware colors.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

Of course column 0 needs special treatment. The color change algorithm will only work on column 1 to C. This one is pretty obvious.

The question is just: How could we treat transformation from and to the grayscale values?

Brightness is simple: Conversion from one brightness to another is done as if black was actually color $00, white $30 and gray $10 and $20 instead of the constellation that they have in the moment.

But how do I gradually transform black into a specific green? Or gray into orange?
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
nesrocks
Posts: 563
Joined: Thu Aug 13, 2015 4:40 pm
Location: Rio de Janeiro - Brazil
Contact:

Re: Gradual color change

Post by nesrocks »

In my opinion, transitioning from black/grays/white to any color:
1 - jump to the correct hue instantly
2 - add/subtract brightness untill you get the final color
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!
https://www.patreon.com/bitinkstudios <- Support me on Patreon!
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: Gradual color change

Post by DRW »

Sounds like a plan.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Gradual color change

Post by tepples »

DRW wrote:I just don't know yet how I should decide which way to take when the other color is six steps away.
When the colors are five or six hues apart, you're cutting through the middle of the YUV/YIQ plane. This means you can go through the gray of roughly the same brightness. For example, for $22 to $28, use $22, $10, $28.
Post Reply