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.
when sprites do it, its just a palette swap/change. An easy way to do something like that in unity is to change the color of the material.
Last edited by kablammyman; 04-20-2012 at 03:55 PM.
The best way to do it depends on the actual effect you want to achieve. I'd do the above two differently. I couldn't give a recommendation without seeing your artwork and a mockup.
That is the artwork I'm using and it's the exact effect I want to achieve. It's for the Unity port of Super Mario Bros. Crossover.
Why not have a full animation for each state and each mode? Then just transistion as required.
Why not have one block of sprites in greyscale. Then adding color should be no biggie.
Ah-hah! That's why I recognized your avatar! Why are you porting? How is that not shut down by now?! :-OThat is the artwork I'm using and it's the exact effect I want to achieve. It's for the Unity port of Super Mario Bros. Crossover.
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.
Last edited by Jessy; 04-20-2012 at 06:47 PM.
All of the color palettes are set ahead of time. Basically I have an array of source colors and an array of colors that need to be set to depending on what's happening.
Last edited by Exploding Rabbit; 04-20-2012 at 10:01 PM.
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.
Last edited by Jessy; 04-20-2012 at 11:01 PM.
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.
Anyway thank you so much for helping me out.
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.
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.
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.
Last edited by Jessy; 04-21-2012 at 12:30 AM.
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 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.
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.
Last edited by Exploding Rabbit; 04-21-2012 at 12:58 AM.
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.
Last edited by Jessy; 04-21-2012 at 09:19 AM.
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.
An easier method may be to have a shader which simply swaps around the RGB values, giving you:
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.