gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > generating a smooth looping palette [solved]

#175449 - zelbo - Wed Nov 24, 2010 12:39 pm

Running into a problem getting a looping palette set up, for something like a plasma, say.
This image shows what is happening. What i am getting is on the left, what i want is on the right.
The first three are from Lode's tutorials. The fourth one is from Relminator's plasma, i don't know what it should actually look like, was just looking for a different take on the problem. (i'm guessing it should look better than it does here)

Some potential suspects:
I'm using ant512's WhoopsiGfx library for drawing lines, maybe that is handling colors strangely? i kinda doubt it, but don't know.
Using a few functions stolen from Lode's quickcg library, maybe these don't work the same on the DS for some reason?
Testing with emulator (no$gba, desmume), my ability to test on hardware is currently impared. Most likely problem?
Using MODE_5_2D. Is this limited to 256 colors?
Maybe some math errors in these algorithms? I know there are some int/u16 type mismatches, but i don't think that's causing it.

Setting up the hardware:
Code:
   videoSetMode( MODE_5_2D | DISPLAY_BG3_ACTIVE );
   vramSetBankA( VRAM_A_MAIN_BG );
   bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 0, 0);


Generate the palettes:
Code:
   u16 palette_0[256];
   u16 palette_1[256];
   u16 palette_2[256];
   u16 palette_3[256];

   ColorRGB colorRGB;
   for(int x = 0; x < 256; x++)
   {
      // lode 1 http://www.student.kuleuven.be/~m0216922/CG/plasma.html#Plasmas_with_Palette_Looping_
      colorRGB = HSVtoRGB(ColorHSV(x, 255, 255));
      palette_0[x] = RGB15(colorRGB.r, colorRGB.g, colorRGB.b);
      
      // lode 2
      colorRGB.r = int(128.0 + 128 * sinLerp(3.1415 * x / 32.0));
      colorRGB.g = int(128.0 + 128 * sinLerp(3.1415 * x / 64.0));
      colorRGB.b = int(128.0 + 128 * sinLerp(3.1415 * x / 128.0));
      palette_1[x] = RGB15(colorRGB.r, colorRGB.g, colorRGB.b);
      
      // lode 3
      colorRGB.r = int(128.0 + 128 * sinLerp(3.1415 * x / 16.0));
      colorRGB.g = int(128.0 + 128 * sinLerp(3.1415 * x / 128.0));
      colorRGB.b = 0;
      palette_2[x] = RGB15(colorRGB.r, colorRGB.g, colorRGB.b);
      
      // Relminator's translucent plasma sample http://rel.betterwebber.com
      u8 r = (u8)(abs(int(16 - 15 * sinLerp(x * M_PI / 16.0f))));
      u8 g = (u8)(abs(int(16 - 15 * sinLerp(x * M_PI / 12.0f))));
      u8 b = (u8)(abs(int(16 - 15 * sinLerp(x * M_PI / 18.0f))));
      palette_3[x] = RGB15(r,g,b);
   }

Using a third party library here, maybe part of the problem?:
Code:
   WoopsiGfx::FrameBuffer topScreen((u16*)BG_BMP_RAM(0), 256, 192);
   WoopsiGfx::Graphics* topGfx = topScreen.newGraphics();

Drawing lines (if WoopsiGfx does somehow turn out to be the problem, i reckon i could build my own line drawing functions, hoping to save some time while using functions written by someone that most likely knows their stuff better than yours truly:
Code:
      for(int x = 0; x < 256; x++)
      {
         topGfx->drawLine(x, 0, x, 5, palette_0[x]);
         topGfx->drawLine(x, 6, x, 11, palette_1[x]);
         topGfx->drawLine(x, 12, x, 17, palette_2[x]);
         topGfx->drawLine(x, 18, x, 23, palette_3[x]);
      }

I'm know this is something i should be able to figure out if i knew what i was doing, but if you've read any of my previous posts, you would know that's not the case as of yet. I've googled everything i can think of regarding ds framebuffer mode, seem to be hitting a wall here. Anyone point me in the right direction?


Last edited by zelbo on Wed Nov 24, 2010 8:53 pm; edited 1 time in total

#175450 - sverx - Wed Nov 24, 2010 4:14 pm

RGB15() doesn't do what you expect. Try RGB8() instead :)

Then you need to turn on the MSB, to say that the pixel has to be nontransparent, so add 0x8000 to that RGB8() result.

#175452 - Exophase - Wed Nov 24, 2010 8:50 pm

Wow, RGB15 and RGB5 are the same thing. Kind of misleading. Seems like it'd be more clear with names like RGB_555, RGB_888, etc.

#175453 - zelbo - Wed Nov 24, 2010 8:51 pm

Cool, that pretty much fixed it. I was certain RGB15 was what i wanted. palette_1 and palette_2 still look pretty clunky (palette_1 has a big black chunk in the middle), but this definitely gives me a working palette. Thank you very much.

#175454 - kusma - Wed Nov 24, 2010 9:11 pm

zelbo wrote:
Cool, that pretty much fixed it. I was certain RGB15 was what i wanted. palette_1 and palette_2 still look pretty clunky (palette_1 has a big black chunk in the middle), but this definitely gives me a working palette. Thank you very much.


128 + 128 = 256, not 255 as the highest unsigned byte is. Try "127.5 + 127.5 * cos(...)" instead.

#175456 - zelbo - Thu Nov 25, 2010 2:19 am

kusma wrote:
128 + 128 = 256, not 255 as the highest unsigned byte is. Try "127.5 + 127.5 * cos(...)" instead.


That makes sense, but still doesn't give me quite what i was hoping for.

Anyone have any good looping palettes? formulas or pre-calculated LUTs?

#175457 - zelbo - Thu Nov 25, 2010 2:23 am

Dur. I think part of the problem is that i'm using floats with fixed-point sinLerp. Might help if i do some actual LUTs.

edit:
you know what just hit me? i've been away from this long enough i need to re-read tonc at this point.

#175472 - relminator - Tue Nov 30, 2010 12:27 am

A little late but this might help:

http://petesqbsite.com/sections/zines/qbcm/issues/4-1/default.html#plasmas

It's a very old tutorial I made for Qbasic on how to generate real-time plasmas.

If you download the example files, there is a routine there to generate a looping palette that can be changed depending on its parameters.
_________________
http://rel.betterwebber.com

#175504 - zelbo - Mon Dec 06, 2010 11:37 pm

Certainly not too late. I'll be sure to play around with this when i get a chance. Thanks, relminator.