Asset - Shaders Retro Palette Swapper

A

Ali-TP

Guest
Thank you! Got it working :) I praise thee.

Here's the code now with the correct layer depth auto assigned:
//------------------ Tiles
var lay_id = layer_get_id("Tiles_1");
if room = rTitle {
var my_pal_sprite = sTitlePalette;
}
if room = rForest1 {
my_pal_sprite = sForest1Palette;
}
var current_pal = global.eth?1:0;
var td = layer_get_depth("Tiles_1");
pal_swap_set(my_pal_sprite,current_pal,false);
pal_swap_set_tiles(my_pal_sprite,current_pal,td-1,td+1,false);
pal_swap_reset();
I just left a review and it doesn't seem to recognise my account name but it's still gone through.
 
Last edited by a moderator:

Edmanbosch

Member
This works really well, but your pallete swap builder doesn't work well with low-res sprites, and when I save or create a new project the save button stops working, and sometimes changes to palletes don't save.
 
Last edited:
but your pallete swap builder doesn't work well with low-res sprites
Okay. So, when you say "low res" what do you mean? I just added a 16x16 sprite and it looks fine....
https://i.gyazo.com/5a6bc530350d12c4f049f57d55be9402.png

Can you show me a screenshot of what you mean?

and when I save or create a new project the save button stops working
Well... yeah. It's just a "save" button, not a "save as" button. So when you don't have changes to save (there will be a * next to the file name in the window header) the save button won't work. I suppose I could add a "save as" button if it's that important to you.

sometimes changes to palletes don't save
Can you maybe figure out the steps to reproduce this? I've never seen this issue before.
 

Edmanbosch

Member
Okay. So, when you say "low res" what do you mean? I just added a 16x16 sprite and it looks fine....
https://i.gyazo.com/5a6bc530350d12c4f049f57d55be9402.png

Can you show me a screenshot of what you mean?


Well... yeah. It's just a "save" button, not a "save as" button. So when you don't have changes to save (there will be a * next to the file name in the window header) the save button won't work. I suppose I could add a "save as" button if it's that important to you.


Can you maybe figure out the steps to reproduce this? I've never seen this issue before.
Don't seem to have a problem with the sprites now, not sure what happened. And I would like to be able to save without any changes made.

And it seems like my issue with changes is only a problem when changing pallete colors using the arrow buttons, here's a GIF of the issue:
 
Ahhhhh. Interesting. Okay, yeah. I'll see if I can find some time to fix those issues and add a "save as" button to the tool. Thanks for the feedback!
 

Edmanbosch

Member
I also noticed that when I click the "save" button and then I click "cancel" it still saves the project anyway with an empty name.
 
@Edmanbosch Alright. I've uploaded a new version of the tool.
https://www.dropbox.com/s/sunqbxlpmgwesuy/PaletteGenerator.exe?dl=0

Saving works a bit different now. When you create a new project, the save button should always be immediately available now. And when you make consecutive saves, it won't prompt you for a file name (Hopefully this didn't break something... I feel like I had it the other way for a specific reason). There is now a Save As button that will allow you to save the current project out to a new file at any time. This new file will then become the "active" document.

So the problem with the sliders was because I was originally using the built in HSV functions to pull the HSV directly from the color itself to populate the sliders. So if either the saturation was at 0, or if the value was at 0 or 255, you didn't really have a "hue" because the color is either gray or black or white. So it would reset back. Fortunately, I was saving the slider positions, just not using that saved data. I was able to hook it up and it seems to be working fine.

Thanks again for the feedback and the testing. Let me know if you find any other issues.
 

TheBroman90

Member
@Pixelated_Pope How well does this work for multiple objects?
I'm making an RTS game and looking for a way to change the color of all units and buildings to their team color.
I'm using "depth = -y" so I have to use the shader in all objects. Will that kill my frame rate?
 
@TheBroman90 Yeah... large number of objects all swapping can be a bit of an impact on your performance. The biggest problem is all of the shader_sets and the shader_resets, those operations are surprisingly slow from my testing.
I'm doing some experimentation now with large number of objects all swapping to different colors to see if there is a way to improve performance. Of course, you are free to download the system and test it out in your project. There's also GamerXP's palette system which may be an improvement over mine performance wise.
https://marketplace.yoyogames.com/assets/2463/palette-based-drawing
 
S

Sardec Xavier

Guest
This is not working for me. I have the latest version of direct x installed but it isn't working or changing my sprite.
Create event of the control object
//Create Systems
pal_swap_init_system( shd_pal_swapper );

Draw event of player character
///Palette Swap
pal_swap_set(spr_player_pal,1,false);
draw_sprite_ext(sprite_index,image_index,x,y,image_xscale,image_yscale,image_angle,image_blend,image_alpha);
pal_swap_reset();
 
Does the example project work? If it does the code is fine so it's likely a palette/art issue. If it doesn't, it is likely a video card/driver issue.
 
S

Sardec Xavier

Guest
The weird thing is that the example one works fine, however, I cannot figure out how to implement it into my game, even though I made sure to use your lovely software to make the pallet sheet so it would work
 
S

Sardec Xavier

Guest
Ok man! it has been sent
 
Last edited by a moderator:
For the record, his issue was not properly copying the shader asset in. He had a "pal_swap_shader" asset, but it was just the default vertex and fragment passthrough shader. So, everyone, if it doesn't work for you, bu the example project does. Double check your shader code versus the example project's shader code.
 
ya would you also allow palette swap functions to take a palette image OR a array of colors?
I like to keep my data outside of sprites if I can

something like..
Code:
palette
[
    0xffffff,
    0xffff00
]
that would be three colors including 0 or alpha
alpha could be an optional by adding another two hex digits on the end (for colorsets that are not 0)
 
ya would you also allow palette swap functions to take a palette image OR a array of colors?
That would be a pretty fundamental change to how my shader works, so no, probably won't be implementing that.

But here's the script you requested:

Code:
///pal_swap_generate_pal_sprite(sprite,image index <-1 for all>,<return list instead of surface?>);
//returns a surface with a pixel for each unique color found in the given sprite drawn vertically.
//   or a ds_list with each unique color.
var _sprite =  argument[0];
var _frame  = argument[1];
var _return_list = false;
if(argument_count > 2)
  _return_list = argument[2];

//Need to break out all sprites into their own sprites.
var _all_colors_list=ds_list_create();
var _new_color_count=0; 
var _sprite_width,_sprite_height;

_sprite_width=sprite_get_width(_sprite);
_sprite_height=sprite_get_height(_sprite);

var _surf=surface_create(_sprite_width,_sprite_height);
var _start = 0;
var _end = sprite_get_number(_sprite);
if(_frame != -1)
{
  _start =_frame;
  _end = _frame+1;
}
for(var _i = _start; _i < _end; _i++)
{ //Loop through, draw each sprite to a surface of a standard size.
  //Then create a new sprite for each surface.
  //Pull all unique colors out of the sprite.
  surface_set_target(_surf);
  {
    draw_clear_alpha(0,0);
    draw_sprite(_sprite,_i,0,0);
  }
  surface_reset_target();
 
  //Find all unique colors
  var _buff = buffer_create(_sprite_width*_sprite_height*4, buffer_fixed, 4); 
  buffer_get_surface(_buff, _surf, 0, 0, 0);
  for(var _x=0; _x<_sprite_width; _x++)
  {
    for(var _y=0; _y<_sprite_height; _y++)
    {
      var _col = buffer_read(_buff, buffer_u32); 
      var _a = (_col >> 24) & 255;
      var _r = (_col >> 16) & 255;
      var _g = (_col >> 8) & 255;
      var _b = _col & 255; 
      var _col=make_colour_rgb(_r, _g, _b);
      if(_a == 0)
        continue;

      if(ds_list_find_index(_all_colors_list,_col) == -1)
      { //First time encountering this color.
        ds_list_add(_all_colors_list,_col);
      }
    }
  }
  buffer_delete(_buff);
}
surface_free(_surf);

var _color_count = ds_list_size(_all_colors_list);
if(_color_count >= 255)
  show_debug_message("That's a looooot of colors... can't promise this will work well.");

if(_return_list)
  return _all_colors_list; 
else
{
  //Create pal surface
  _surf = surface_create(1,_color_count);
  surface_set_target(_surf);
  for(var _i=0; _i<_color_count; _i++)
  {
    var _col = _all_colors_list[| _i];
    draw_point_colour(0,_i,_col);
  }
  surface_reset_target(); 
   
  ds_list_destroy(_all_colors_list);
  return _surf;
}
 

cidwel

Member
Hi @Pixelated_Pope

First of all, thanks for giving this to us!

I have a issue regarding the builder. It seems when I zoom the preview pane, the color selector or the hue values are not being rendered in the preview pane. Please see this gif.

Not sure what could be, maybe the method for rendering things in that pane :/



It turns back to normal when I go back to 1x

Here's attached the sprite pallete I'm using as testing so you can debug it.

Thanks for all your effort in the community!

ps: I'm using as a workaround clZoom that seems to really help with this issue. It just creates a separate window and zooms a designed region.


Aaaand... This is what I could manage easily following your guide and using your scripts. Seriously this is great!



many thanks for all!
 

Attachments

Last edited:
@cidwel Oh wow. Thank you. What a silly bug. Somehow "interpolate colors between pixels" got checked, which blurs the image when you zoom in making color detection and replacement with the shader inaccurate or straight up broken. I've uploaded a new version of both the source and the EXE that should fix the problem. Thanks for finding it and letting me know!
 

KhMaIBQ

Member
Hey @Pixelated_Pope. I just wanted to say thank you again for the Retro Palette Swapper! I finally fully implemented it in my project and it is working flawlessly. It is very easy to integrate and create palettes with the provided tool. :D
 
Hey @Pixelated_Pope. I just wanted to say thank you again for the Retro Palette Swapper! I finally fully implemented it in my project and it is working flawlessly. It is very easy to integrate and create palettes with the provided tool. :D
Awesome! Thank you! It's always nice to get a notification that someone replied to this thread and see that it isn't a "this doesn't work for me" post. :D
 

Tayoyo

Member
@Pixelated_Pope So I managed to get the palette swapper to work properly, but I've run into an issue where the object that I'm using the swapper in (the player object) animates very slowly. I'm not sure why it's happening, as I've tried looking through all the code in the demo and that I imported into my project and I can't find anything related to image_speed. If I comment out all of the Palette Swapper code the animations run fine for the player. (All the other animations for enemies work just fine with the shader on, and the game still runs at 60 fps)
I tried setting the image_speed of the player really high while running with the shader on but the animations still run at the same slow speed.
Any help would be appreciated, and if you need any videos of the problem I'd be happy to make them.
Thanks a lot!
 
Last edited:
So I managed to get the palette swapper to work properly, but I've run into an issue where the object that I'm using the swapper in (the player object) animates very slowly. I'm not sure why it's happening, as I've tried looking through all the code in the demo and that I imported into my project and I can't find anything related to image_speed. If I comment out all of the Palette Swapper code the animations run fine for the player. (All the other animations for enemies work just fine with the shader on, and the game still runs at 60 fps)
I tried setting the image_speed of the player really high while running with the shader on but the animations still run at the same slow speed.
Any help would be appreciated, and if you need any videos of the problem I'd be happy to make them.
Thanks a lot!
That is an incredibly strange issue and I'd be willing to put actual money on it not being related to my shader. That being said if you'd like me to look at your project I could likely find the issue fairly quickly. You could also join my discord server for live help (link in my signature). I am headed off to bed for the night but there is almost always someone helpful online. If you want my help directly you can PM me and I will do what I can.
 

Tayoyo

Member
That is an incredibly strange issue and I'd be willing to put actual money on it not being related to my shader. That being said if you'd like me to look at your project I could likely find the issue fairly quickly. You could also join my discord server for live help (link in my signature). I am headed off to bed for the night but there is almost always someone helpful online. If you want my help directly you can PM me and I will do what I can.
I'm already on the server but I have to go to bed too, so we can try out some things tomorrow. Talk to you then!
 

Tayoyo

Member
@Pixelated_Pope Yay, I managed to find the issue!

So the problem was that in the step event of the beholder there was a line of code that messed with the image speed that I copied over. I found this by adding an image speed and a simple animation to the demo and getting the same issue. Once I removed the last line of code everything worked perfectly fine.
///Palette control
///Change palette with up/down (Basic)

if(keyboard_check_pressed(vk_up))
{
current_pal++;
}
if(keyboard_check_pressed(vk_down))
{
current_pal--;
}

current_pal=wrap(current_pal,0,pal_swap_get_pal_count(spr_player_pal)-1);
image_speed=.1 * delta_time * (60/1000000);
Thanks for being so responsive and thanks for making this so simple and great! Sorry for bothering you with a problem that I could fix myself. Everything else works great and the palette tool is really useful for designing new outfit styles for the main character :D. Have a nice day!
 
Thanks for being so responsive and thanks for making this so simple and great! Sorry for bothering you with a problem that I could fix myself. Everything else works great and the palette tool is really useful for designing new outfit styles for the main character :D. Have a nice day!
No Problem! Glad you got it figured out.
 

cidwel

Member
Hi!

I'm here again to report some bug. I'm trying to fix it by myself anyway. It seems the pallete scripts aren't compatible with yoyocompiler. It throws these errors:


I'll try to post a workaround in the mean time.

Many thanks for your script! I'm using it on diverse ways and it couldnt work better :)

Sorry. I've just figured it out. Somehow missed to add some vital objects from the core project.

I'll just leave this message to thank you again for sharing these scripts :)
 
Last edited:
New Update!
--------------------------------------------
New Feature: Layer based swapping
-Will set everything on a specific layer to draw using the indicated palette. Utilizes the layer script feature of GMS2.


Palette Generator 3 is out now!
New for this version:
Play your sprites while modifying your palette at your desired speed.
Saving a project now saves all the sprites! As well as the scale and position in the viewbox, the background color and the highlight color. No more re-adding your sprites every time you want to modify a palette!
Background color of app can be manipulated, and is persistent between runs of the app.
 

KhMaIBQ

Member
Hey @Pixelated_Pope, someone that played my game ran into an error. Here is the error:
Code:
############################################################################################
FATAL ERROR in Fragment Shader compilation
ShaderName: shd_pal_swapper

C:\Users\xxx\Downloads\memory(130,6): error X3511: unable to unroll loop, loop does not appear to terminate in a timely manner (54 iterations), use the [unroll(n)] attribute to force an exact higher number

at gml_Script_pal_swap_set
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_pal_swap_set (line 0)
gml_Object_obj_VersusScreen_Char_Draw_0
Any idea what caused this issue?
 
@KhMaIBQ So, most likely, that would be because they are running on old hardware. But there are some options.

1. In your game, make sure the shader actually compiled using the built in function before trying to use it. This will mean no pal swapping, but no pal swapping is better than crash.
2. Open up the code for the shader. There's a for loop in there. That loop iterated too many times for that hardware (54 seems to be its limit). There is a way to force a higher limit, though I haven't actually tested this myself as I have never encountered the error personally. But, give this a shot. RIght above that for loop, add this line of code:
Code:
#pragma unroll(256)
I don't know if 256 is the number you want. Definitely need more than 54. Hopefully the player will work with you to try out a few different solutions. I'd be very excited to hear back about the results.

As a side note. Googling for this error (because I remember encountering it a long time ago) lead me to a reddit thread in the AM2R subreddit. Apparently AM2R uses my pal swap shader! This is particularly exciting for me because reading about AM2R's development about 10 years ago is what lead to me purchasing gamemaker. Crazy.
 

KhMaIBQ

Member
@Pixelated_Pope Thank you for the quick reply!

How do I know how many loops I need? I am not familiar with shaders.

Outside of that, I will give those things a try and see if it works. I'll be sure to post the results.

That is an awesome story involving AM2R and your beginnings. :)
 
@KhMaIBQ I honestly don't know either. Again, I've never encountered this, so I've never really been able to test it. Different people who have encountered the error seem to run into it around the 55-60 point. I would start at 64, then maybe 96 if that doesn't work, and maybe 128. I don't know if it's necessary to do it in multiples of 32, but it seems like a safe bet.
 

jujubs

Member
Hi Pope. First of all, thanks for this amazing tool!

So, I've been struggling to find out how to apply a palette to the entire screen. Is it even possible? I've tried disabling the application surface, then drawing it manually and applying the shader to it, but the scripts seem to ask for a sprite specifically. How could I go about this?
 
@jujubs
Yeah, it's absolutely possible. The script is just asking for your palette sprite (or surface), but anything can be drawn with the palswap.

Just set it.
draw it.
reset it.
 

jujubs

Member
Hey @Pixelated_Pope, thanks for the reply. Could you be a little more... specific? I'm not really a code guy, so I'm a little lost. Is there, like, a video tutorial on the topic? Or maybe we could start a separate thread or something.
I managed to make it kinda work using sprite_create_from_surface, but I'm not sure this would work. Also, I don't know how to point out the original palette, so the shader knows which colours to swap :(
I tried reading your example code, but there are lots of "palette_etc" everywhere and I keep getting lost.
 
@jujubs Oh, sorry :D. Okay, so first off, IMO, the best way to get help is to join my discord server! Just follow the (recently updated) link in my signature! Then I, or one of the very smart and friendly members can help you out.

But until then, if your core problem is applying a shader to the entire screen, here's a great youtube video on how to do it:
If your problem is specifically palette swap related, we should probably talk on Discord.
 

derboo

Member
Hi! I'm currently trying out this cool shader and I'm currently puzzled by what seems to be an interference with another shader, and I'm a noob to shaders so I don't know if this is the correct place to ask, but...

I'm trying to use this in combination with Vortex Game Studios' OLD TV Filter (can't link since this is my first post), and in principle, it seems to work fine. However, that shader looks better with interpolation on, but once I activate both shaders AND interpolation, all palette instructions are ignored (the basic palette inherent in the sprite image is used).

In short, either one of the shaders plus interpolation good, both shaders without interpolation good, both shaders together plus interpolation problematic. Any ideas?
 
@derboo

You usually have two options when combining shaders.
1. Literally combine the shaders (not always a great option, especially if you didn't write the shaders in the first place)
2. Draw the content with one shader to a surface, then draw that surface to the screen with another shader.

Option 2 is likely going to work best for you. I'm guessing all you'd need to do is enable texture interpolation before using the CRT shader, and then disable it afterwards. That will keep your pixel graphics sharp (which is required for the pal swapper) while allowing some color interpolation when using your CRT shader.
 

derboo

Member
Ah, that was a lot simpler issue than I feared. Turning on interpolation only for the CRT shader's drawing process and off after like you suggested immediately solves it. Looks like I didn't properly think the sequence of these processes through. Thanks for the advice! :)
 
Top