How to do flashing for sprites?

What would be the most efficient way to do flashing for sprites similar to how Mario flashes when he gets a star in Super Mario Bros.? Is this possible to do with a shader? I've included two examples of the effect I need. Thank you.

why not just use a sprite sheet and animate through it like the sprite sheet is setup?

Click to expand...

If the effect is simple, as with Mario and Mega Man, that would be an inefficient use of memory. It would be easy to deal with, though, so it's a more efficient use of time, if you have the memory to spare.

I need to be able to set the colors with code because they change depending on many different factors.

Click to expand...

I need more information on that. Are there set color palettes, as above, or are there going to be wildly lerping values?

Also, are you able to use a quad for each pixel, or is that too much of a pain? As far as I can imagine, that would be the most efficient route, but if you don't have a workflow for it, it doesn't matter.

Also, are you able to use a quad for each pixel, or is that too much of a pain? As far as I can imagine, that would be the most efficient route, but if you don't have a workflow for it, it doesn't matter.

Click to expand...

I use one quad for each sprite, so it probably wouldn't work to use one for each pixel. I'm open to trying different things though. I haven't really started making the game yet so my workflow is not fully set yet.

Here's what I recommend. If you take this approach, I'd like to hear your workflow, because I think I was a bit slow at it, using lots of eyedropper, magic wand with low tolerance/discontiguous, and one pixel marqueeing.

You'll make two textures. One of them (the one that looks like the character) is Alpha 8, to be memory efficient. You find out how many colored areas you need (11 for Mega Man, by my calculations. 10 actual colored areas, plus one for the cutout), and select the next higher power of two up. Divide 256 by that, and you'll know how far apart to space the greyscale values in the key textures (16 bits apart for mega man). I used white as the color to discard, but the shader can be modified to deal with whatever. White or black should yield the fastest results.

You'll then need to populate a texture with actual color values. This can be set up in row or columns, but I used rows. Take a look at these screenshots, and check out the package. You might get what's going on by doing that, but ask any questions otherwise. If you're using Windows, you'll have to force OpenGL; we can work on that if necessary. I recommend manipulating the "Key Y" slider, for fun and illustration, after opening the scene.

How does this approach compare to what you did in Flash?

P.S. I added the border because Unity actually expands all textures to powers of two, distorting pixel art. You'd probably want to set up the border differently.

Wow, that is crazy Jessy. Thank you for going above and beyond with all your hard work. Since I know nothing about shaders and am pretty new to Unity, I have tons of questions.

First, let me show you how I was doing it in Flash. Here is Mega Man's 16-bit sprite sheet.

And I have a separate file for each character that takes care of all the color replacing and flashing. This is what it looks like for 16-bit Mega Man:

I'm not gonna explain exactly how it works, but the main point is that the left column is the colors on the sheet. It gets those colors, then replaces them with the colors to the right depending on what's going on. In Flash, I just replaced the colors directly on the sprite sheet (equivalent to Unity's Texture2d.SetPixels method).

The thing I noticed about your proposal is that there is no row with the original colors, so I don't understand how it knows which color to replace each shade of gray with. Also, does it need to be gray, or is it possible to use it the way I have it set up on the sprite sheet. A lot of my sprite sheets are made by fans, and it's just easier to work with if I don't have to modify the colors on the sheet.

Is this shader fast enough to use on everything even when it's not flashing? Because I change colors of stuff depending on what level it is, but it doesn't change again until the level is over. I was gonna use Texture2d.SetPixels for that, but I was just wondering if it's possible to use this or if that will cause the game to run too slow.

The thing I noticed about your proposal is that there is no row with the original colors, so I don't understand how it knows which color to replace each shade of gray with.

Click to expand...

The shades of gray are stored as 0-1 values. Black maps to the left pixel of the color values sheet, and goes up in increments of 16 bits (.0625 of the way across the sheet). It would probably be best to have the second color be at 1/32 + 1/16, instead of just 1/16, so that the color is sampled right in the center of the texel, but I forgot to do that. It still worked out. Like I said, I didn't do a fast job of it. Also, the order of greyscale values and colors is totally arbitrary. I kind of worked from the outline, to lighter areas, ending with the face.

Also, does it need to be gray, or is it possible to use it the way I have it set up on the sprite sheet.

Click to expand...

I don't know how'd you do it with your sheets, in a shader. I googled it, and came up with Farfarer doing something very similar to what I posted here! ;-) If it's fast enough to script texture changes, do that. If you need to offload work to the GPU, you could try scripting a conversion to what I did, in the Editor. It looks like you could get away with rows/columns of 128 pixels.

Is this shader fast enough to use on everything even when it's not flashing?

Click to expand...

It's not very heavy, nor is most any shader used for 2D stuff. I might switch to a standard unlit cutout/blend shader, when possible, if you're concerned about battery, though. But the blending or "alpha testing", which are unavoidable if you don't "model" the pixel art with denser meshes, would be the potential bottleneck.

I don't know how'd you do it with your sheets, in a shader. I googled it, and came up with Farfarer doing something very similar to what I posted here! ;-) If it's fast enough to script texture changes, do that. If you need to offload work to the GPU, you could try scripting a conversion to what I did, in the Editor. It looks like you could get away with rows/columns of 128 pixels.

Click to expand...

I bet I could convert the sheets to the gray version when the game is started so that I could still use my current sheets. I already saw that other post, but I didn't understand it. But it does look like it's a similar technique. I noticed in that post that he decided to use the red and green channels to get more than 256 colors. I'll have to look into that.

I was really just trying to see what my options were for the color changing, so thanks for enlightening me a bit. If I decide to go this route I'll probably have more questions. This technique would be faster than using set pixels and swapping textures continuously right? Also why would my rows and columns be limited to 128 pixels? My current palette sheet for Mega Man is 264 x 801 pixels because it holds colors for all of his skins.

Edit: Actually, I don't think I'd ever need more than 256 colors on the source sheet.

This technique would be faster than using set pixels and swapping textures continuously right?

Click to expand...

That's my prediction, but it depends on how much is changing per-frame. It doesn't matter how efficient your algorithm for changing pixels is, if you need to send a lot of texture data to the GPU all the time. If you can keep textures cached near the hardware that works with it, the speed of light won't be as much of an antagonist to you. Also, I don't know any way that a CPU could keep up with the GPU lookup approach I offered, but whether that amounts to a time difference that matters to a human, I don't know. You'd have to profile your own game, which involves much more than just the actions this thread is about. If you've already got some textures and code that works, try it out and see if there's any reason to try to improve performance.

Also why would my rows and columns be limited to 128 pixels? My current palette sheet for Mega Man is 264 x 801 pixels because it holds colors for all of his skins.

Click to expand...

I was basing 128 on what I see in your color replacement sheet. I see blocks of 24x6 (144), but as far as I can tell, there are 7x6 blocks that aren't doing anything, which gets you below 128. There may be other unnecessary areas, or I may be totally off-base on this, due to my incomplete understanding of it.

I don't have any code written yet, that's why I was trying to figure out which approach would be faster. I don't have Unity Pro either so I can't profile it, and I don't have any Apple devices to test mobile performance. I don't really understand which parts the CPU does and the GPU does.

The only way to learn about it is to try it though. Thanks for your help.

Digital ApeModerator

An easier method may be to have a shader which simply swaps around the RGB values, giving you:

RGB
RBG
GRB
GBR
BRG
BGR

etc.. that's a fair few flashy colour cycling combinations and should look sufficiently retro? it is also pretty easy to do in a shader? As for overall brightening (flashes etc) you can just multiply them up.

Just a thought!

Although I am mega impressed by Jessy's idea above and would use that.

I don't have Unity Pro either so I can't profile it, and I don't have any Apple devices to test mobile performance.

Click to expand...

You can get some good info from the framerate, if you leave Application.targetFrameRate at -1. Here's one counter. All devices will have their quirks, but for the most part, you'll get the same performance differences on all devices, just multiplied based on processing power. e.g. If the technique I offered here were to make your game go from 800 FPS to 850 FPS – a useless increase on a desktop – it might possibly mean an actual noticeable difference from 30 to 60 FPS on some mobile device. You'll have to find out where you care; getting this into the App Store might be possible, based on all the bootleg Nintendo franchise stuff there, but doing so might just be inviting legal trouble. You'd probably know better than I would, based on your experience to this point.

Pretty much everything that you do in a script will be performed on the CPU. The GPU stores some data locally, gets other data per-frame from the CPU (like transformation matrices and anything you modified in the mesh or displayed textures), and renders everything using shader instructions and vendor-specific tricks that you have no control over. The CPU is faster than the GPU, but only when you're not doing massively parallel operations, like texture lookups per-pixel, on a transformed polygon, which is why GPUs were invented, and continue to be used. Their architecture involves hundreds or thousands of cores, each generally performing small programs on the same data, instead of a handful of cores, working on all kinds of different data, with many instructions. The CPU is almost universally easier to work with.

I think that the code for your palette switching could be really fast, but because rendering needs to happen on the GPU, it's not CPU speed you need to worry about; it's the communication between the two. Try to minimize the data (textures) that gets modified and uploaded to the GPU. This may involves using fewer sprite sheets, but a balance needs to be struck – there's some acceptable window for all of the possibilities for creating the the graphics and code. The window becomes larger as hardware progresses; I'm thinking that it's going to be pretty difficult for you to get a bad framerate out of anything you do with this project. My opinion is that your experience with Flash has made you paranoid about performance; I'm hoping, and believing, Unity will treat you better.

There may be something you could do with render textures, but without Unity Pro, that's not possible. I don't have experience with my theories of how you'd do that, either.

You'll have to find out where you care; getting this into the App Store might be possible, based on all the bootleg Nintendo franchise stuff there, but doing so might just be inviting legal trouble. You'd probably know better than I would, based on your experience to this point.

Click to expand...

I'm not putting SMBC on the app store, but I'm building a 2D platformer engine that I can use for other games. That's why I want it to be designed really well.

I think that the code for your palette switching could be really fast, but because rendering needs to happen on the GPU, it's not CPU speed you need to worry about; it's the communication between the two. Try to minimize the data (textures) that gets modified and uploaded to the GPU.

Click to expand...

You're talking about the texture swapping technique right? I got scared when I read the docs for the Texture2D.Apply method. It says "This is a potentially expensive operation, so you'll want to change as many pixels as possible between Apply calls." That made me think I couldn't use it for flashing. So you are saying it might be ok if I keep the textures small? My idea was to still use the same sprite sheets, but whenever something flashes, I'll temporarily copy the bigger texture into a smaller texture that is only the size of the current sprite, so it'd probably be like 32 x 32 at the most, and I could change the pixels on that. I was worried it would be too slow, but it sounds like you're saying maybe I should try it. That's how I did it in Flash, but "modifying a texture and uploading it to the GPU" sounds like it's really expensive. Flash didn't have textures, only bitmaps.

My opinion is that your experience with Flash has made you paranoid about performance; I'm hoping, and believing, Unity will treat you better.

Click to expand...

Yes that's true. The reason I get worried about performance is because the music in the game is emulated. I am hoping Unity will be faster at emulating the music. When I play Super Nintendo music, the game has to emulate the sound card of a Super Nintendo, and that can be an expensive operation. I'm hoping the C# version of the emulator will be faster than the C++ version I ran through Flash. I wish I could run C++ plugins in the browser, then it'd be super fast. I couldn't find any way to do it though.

Yes. Or if you don't modify many textures. Even if you only modify a small amount of pixels on a texture, the GPU will need the whole thing resent. Not having to worry about compression or mipmaps will help.

My idea was to still use the same sprite sheets, but whenever something flashes, I'll temporarily copy the bigger texture into a smaller texture that is only the size of the current sprite, so it'd probably be like 32 x 32 at the most, and I could change the pixels on that. I was worried it would be too slow, but it sounds like you're saying maybe I should try it. That's how I did it in Flash, but "modifying a texture and uploading it to the GPU" sounds like it's really expensive.

Click to expand...

Expensive in terms of time at least – literally due mostly to the distance between physical components, as far as my understanding goes. Your approach sounds pretty reasonable to me, but I've never tried it.

Thanks. I didn't get much help with my other questions so this is the first time I'm seeing how helpful the forums can be.

Click to expand...

Sorry to hear that. I hadn't read your other posts, but unfortunately, I don't have anything useful to respond with to them at this time. I got delete-happy on my RSS feed after Unity's popularity exploded years ago. There are too many threads nowadays that are inane, or have been answered countless times before, for me to get excited about checking the forum like I used to be. I bet there are a lot of potentially helpful people who fall into the same boat, now; I've heard some of them talk about it. Thanks for bringing an interesting topic around, though!

There are too many threads nowadays that are inane, or have been answered countless times before, for me to get excited about checking the forum like I used to be.

Click to expand...

I agree. I think it's because Unity's market includes both professionals and hobbyists. There are a lot of young people posting simple questions that can be answered with a quick search. A lot of threads seem to go unanswered because they get swallowed into the massive pool of random topics. And there's also Unity Answers, which is an entirely different thing, but it basically falls into the same boat. I've actually had more success by PMing people that seemed to know about topics I had questions about.

Anyway, I think I'm going to attempt your method because I want to learn about shaders and it's something new and different. My flashing code in the Flash version is very sloppy so I need to redo it anyway. You seem like you know a lot about Unity and are very friendly, so I may PM you with questions about other topics if that's alright.

Digital ApeModerator

I check the forums whenever I have a nice cuppa or smoke my e-cig usually during breaks. It's fairly fun and I don't mind helping out. There's a lot of annoying people who never read docs like ever, but once in a while you get a well-worded post that begs for an answer like this thread.

Anyway, I think I'm going to attempt your method because I want to learn about shaders and it's something new and different.

Click to expand...

That's cool. I wrote it in GLSL (ES in particular) because that's what I know best, and is what the platforms I care most about right now use, but you'll need Cg code for Windows and Flash. (A surface shader would work, but is overkill, given your lack of dependency on lighting.) Ippokratis, who is an awesome member of the community, wrote this Cg–Unity primer. Maybe you could check it out, and try to translate what I made into Cg? That would help me learn Cg, too, if you have any success, and share it.

You seem like you know a lot about Unity and are very friendly, so I may PM you with questions about other topics if that's alright.

Click to expand...

Ha, thanks! I usually prefer that people post questions publicly, and PM me a link, so that many more people can be helped by any information I can share, and so that other people can help. However, it's fine for people to talk to me privately if they don't want the subject of their questions out in the open, or if the scope of the issue is big enough to warrant contract work.

Ippokratis, who is an awesome member of the community, wrote this Cg–Unity primer. Maybe you could check it out, and try to translate what I made into Cg? That would help me learn Cg, too, if you have any success, and share it.

Exploding Rabbit:
Perhaps the Rage Pixel package could help you build an efficient workflow for creating - using pixel art in Unity.

Jessy :
Thanks a lot for sharing the code, it is much appreciated. The use of palletes + Alpha8 has a big potential in building memory - efficient particle effects too. There is a presentation from Valve where they describe how they used this approach to obtain three different colored "muzzles" from one alpha 8 and three palletes with a higher degree of color control than tint gives. The main drawback that remains ( for me using this technique ) is how to create the assets, i.e the alpha and the pallete, in an efficient way.
Here is an attempt to "translate" the shader code you posted in Cg, I wonder if we could skip the need to use discard ( = clip(-1) ) somehow.