Jump to content


Photo

Fading/gradients with Jaguar's palette


8 replies to this topic

#1 ggn

ggn

    "Can I hear you say YEAH?"

  • Members
  • Pip
  • 170 posts

Posted 18 January 2013 - 09:42 PM

Hi,

I'm working on a "small" tool for the jaguar that's just about ready, apart from the following: I want to be able to create 16-colour gradients in paletted mode (5-6-5 RGB), from one palette entry (grad1) to another (grad2). Because I wanted an easy way for the user to pick colours, I used the Windows built-in col selector which is 32-bit, to select grad1 and grad2. I keep grad1 and grad2 32bit internally and when it's time to generate the gradients, I convert them down to 16bit. Here's the (ugly) code that does both the conversion and gradient creation (with some redundant crap removed):

CODE
          r1 = grad1 And $ff : r4 = grad4 And $ff
          g1 = Shr%(grad1, 8) And $ff : g4 = Shr%(grad4, 8) And $ff
          b1 = Shr%(grad1, 16) And $ff : b4 = Shr%(grad4, 16) And $ff
        
          col = (Shl&(r1, 8) And $f800) + (Shl&(b1, 3) And $7c0) + (Shr&(g1, 2))         'write beginning gradient (1)          
          stepr = (r4 - r1) / 15 : stepg = (g4 - g1) / 15 : stepb = (b4 - b1) / 15        'calculate steps
          
          For l = 1 To 14
            col = (Shl&(Round(r1 + stepr * l  / 8) And 255, 8 + 3) And $f800) + (Shl&(Round(b1 + stepb * l / 8) And 255, 3 + 3) And $7c0) + (Round(g1 + stepg * l / 4)  And $3f)
      
            'write gradients 2-14
          Next l
          
          
          col = (Shl&(r4, 8) And $f800) + (Shl&(b4, 3) And $7c0) + (Shr&(g4, 2))         'write final gradient (15)


(so the code calculates the steps for r,g,b from the 8bit coefficients of grad1,grad4 and then creates the gradients by adding the step values to grad1's values, and then shifts them into place and masks them).

This nearly works, but there are some errors that are really visible on pure grey gradients; the green component seems to not keep in sync with the red and green, so some ugly stuff are being shown instead of shades of gray. From some reference palettes I have, I seem to be either spot-on or +/-1 when creating my palettes.

Anyone had any experiences with this? The only thing I wanted to try was to calculate the gradients using 16bit mode (5R,6G,5B) but I don't think that would change things much. Any input is appreciated!

#2 GroovyBee

GroovyBee
  • Members
  • 31 posts
  • Gender:Male
  • Location:North, England

Posted 21 January 2013 - 12:56 PM

What I'd do is work on 8 bit values for R, G and B (24BPP) until you absolutely need to convert them to 16BPP mode then weight them accordingly (in a final pass). Are stepr, stepg, stepb floating point variables in your code?

#3 Orion_

Orion_

    Rick dangerous

  • Level1
  • PipPipPip
  • 1,067 posts
  • Gender:Male
  • Interests:OldSchool Coding =)

Posted 21 January 2013 - 03:16 PM

maybe it's because Green is 0-63 where as Red/Blue are 0-31.
For my palettes I personally keep 24bits colors and convert them on Jaguar in 16bits using a little 68k routine
my Website with all my homebrew projects !

"C'est la ou tu vois la supériorité de la vitamine C sur les dragibus !" - Fadest, RGC 2008

#4 sh3-rg

sh3-rg

    Super sprint

  • Members
  • PipPip
  • 348 posts
  • Gender:Male
  • Location:bolton, england
  • Interests:/|\<br />ynwa

Posted 21 January 2013 - 04:36 PM

QUOTE (Orion_ @ 21 Jan 2013, 14:16) <{POST_SNAPBACK}>
maybe it's because Green is 0-63 where as Red/Blue are 0-31.

I suggested this but maybe he'll listen if it's coming from someone like you rather than me tongue.gif

poulpe.gif
Would you Push The Button?
"Do not trust people who offer incense" - zerosquare offering some important advice via google translate

#5 Orion_

Orion_

    Rick dangerous

  • Level1
  • PipPipPip
  • 1,067 posts
  • Gender:Male
  • Interests:OldSchool Coding =)

Posted 21 January 2013 - 07:33 PM

Well, I used to write code-that-does-everything-in-one-line like " col = (Shl&(Round(r1 + stepr * l / 8) And 255, 8 + 3) And $f800) + (Shl&(Round(b1 + stepb * l / 8) And 255, 3 + 3) And $7c0) + (Round(g1 + stepg * l / 4) And $3f)"
but I find out that sometimes it led to strange behavior (missing parenthesis or compiler wrong interpretation)
Now I write a step each line, and then I can track the value after each computation and verify that I did everything right
just a suggestion %)

my Website with all my homebrew projects !

"C'est la ou tu vois la supériorité de la vitamine C sur les dragibus !" - Fadest, RGC 2008

#6 ggn

ggn

    "Can I hear you say YEAH?"

  • Members
  • Pip
  • 170 posts

Posted 22 January 2013 - 10:26 PM

Oops, people replied blush.gif. I'm sorry but I've been busy with other parts of the tool so I didn't notice...

Now then...

QUOTE (GroovyBee @ 21 Jan 2013, 13:56) <{POST_SNAPBACK}>
What I'd do is work on 8 bit values for R, G and B (24BPP) until you absolutely need to convert them to 16BPP mode then weight them accordingly (in a final pass). Are stepr, stepg, stepb floating point variables in your code?


Yup that's what I do.

QUOTE (Orion_ @ 21 Jan 2013, 16:16) <{POST_SNAPBACK}>
maybe it's because Green is 0-63 where as Red/Blue are 0-31.
For my palettes I personally keep 24bits colors and convert them on Jaguar in 16bits using a little 68k routine


Not an option here I'm afraid, a pre-computed palette is required.

QUOTE (sh3-rg @ 21 Jan 2013, 17:36) <{POST_SNAPBACK}>
QUOTE (Orion_ @ 21 Jan 2013, 14:16) <{POST_SNAPBACK}>
maybe it's because Green is 0-63 where as Red/Blue are 0-31.

I suggested this but maybe he'll listen if it's coming from someone like you rather than me tongue.gif

poulpe.gif


sors.gif

QUOTE (Orion_ @ 21 Jan 2013, 20:33) <{POST_SNAPBACK}>
Well, I used to write code-that-does-everything-in-one-line like " col = (Shl&(Round(r1 + stepr * l / 8) And 255, 8 + 3) And $f800) + (Shl&(Round(b1 + stepb * l / 8) And 255, 3 + 3) And $7c0) + (Round(g1 + stepg * l / 4) And $3f)"
but I find out that sometimes it led to strange behavior (missing parenthesis or compiler wrong interpretation)
Now I write a step each line, and then I can track the value after each computation and verify that I did everything right
just a suggestion %)


Yeah I know, I'm against franken-code like this, at the beginning it was a really simple line, but I kept adding stuff to it to see if it worked (as a proof-of-concept). I'll probably revisit that chunk of code tomorrow and make it less horrible!


Thanks for the tips, all (also on IRC)! Finally, for reference, here's a sample output for the r,g,b values using my routine (left) and the reference palette (right). I'll have another look tomorrow.
CODE
0            39            15            0             39            15
0            36            14            0             37            14
0            34            13            0             33            12
0            32            12            0             31            11
0            30            11            0             29            09
0            28            10            0             27            08
0            26            9             0             25            07
0            24            8             0             23            06
0            22            7             0             21            05
0            19            6             0             19            04
0            17            5             0             17            03
0            15            4             0             15            02
0            13            3             0             13            02
0            11            2             0             11            01
0            9             1             0             9             01


#7 Zerosquare

Zerosquare

    Rick dangerous

  • Administrators
  • PipPipPip
  • 2,122 posts

Posted 23 January 2013 - 12:52 AM

There's something I don't understand with your code...

The gradient list is 15 entries long, but your code seems to generate 16 (1 + 14 + 1) entries :
CODE
'write beginning gradient
...
For l = 1 To 14
...
Next l
...
'write final gradient (15)


If there are indeed 15 entries, then it needs a few patches :
CODE
stepr = (r4 - r1) / 14 : stepg = (g4 - g1) / 14 : stepb = (b4 - b1) / 14
...
For l = 1 To 13

« Mon PC on dirait un Amiga tellement c'est instable » – GT Turbo
« Soit A un niveau d'absurdité, il existe un post N tel que... » – Azrael et al., 2006

#8 Zerosquare

Zerosquare

    Rick dangerous

  • Administrators
  • PipPipPip
  • 2,122 posts

Posted 23 January 2013 - 01:05 AM

Just did a quick test, and here's something that seems to match the original gradient:
CODE
DEFDBL A-Z

R1 = 0: G1 = 39: B1 = 15
R2 = 0: G2 = 9: B2 = 1

FOR I = 0 TO 14
    R = FIX(R1 + (((R2 - R1) * I) / 14))
    G = FIX(G1 + (((G2 - G1) * I) / 14))
    B = FIX(B1 + (((B2 - B1) * I) / 14))
NEXT I


And here are the RGB values it generates:
CODE
0             39            15
0             36            14
0             34            13
0             32            12
0             30            11
0             28            10
0             26            9
0             24            8
0             21            7
0             19            6
0             17            5
0             15            4
0             13            3
0             11            2
0             9             1


I don't have GFA32, so I tested it with gool old QBASIC. Note that FIX(x) always rounds down, not to the nearest integer (I tried adding .5 to round to the nearest integer, but it no longer matches the original gradient, though it's probably more accurate that way).

EDIT: oops, looks like what I thought was the original gradient is actually your version. Back to square one then...

EDIT 2 : If you look at the differences between successive colors, there's something strange in the original palette:
CODE
0    -2    -1
0    -4    -2
0    -2    -1
0    -2    -2
0    -2    -1
0    -2    -1
0    -2    -1
0    -2    -1
0    -2    -1
0    -2    -1
0    -2    -1
0    -2    0
0    -2    -1
0    -2    0
* the green channel uses -4 and -2, but not -3

* the blue channel uses more than two values (-2, -1, 0) and it doesn't look like there's a recurring pattern
IIRC that can't happen if the interpolation is linear, even with rounding. So either they were doing some really strange rounding, or they didn't use a linear interpolation (maybe it's gamma-corrected or picked manually?)

Is it important to match the original palette exactly?
« Mon PC on dirait un Amiga tellement c'est instable » – GT Turbo
« Soit A un niveau d'absurdité, il existe un post N tel que... » – Azrael et al., 2006

#9 ggn

ggn

    "Can I hear you say YEAH?"

  • Members
  • Pip
  • 170 posts

Posted 27 January 2013 - 09:31 PM

Sorry for delaying my reply so much - busy busy busy lately!

Since zerosquare's experiments confirm that the palettes are not exactly linear, I'll change strategies. Thanks to everyone here and on IRC for the suggestions and brainstorming smile.gif.



Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users