I'm sorry, I have to do this:
[SPOILER="This"][video=youtube;AnBvbo2cel8]https://www.youtube.com/watch?v=AnBvbo2cel8[/video][/SPOILER]
... Anyway. So in the course of working on my new project, DyeRite, I have gained an intimate familiarity with the dyeing process in Mabinogi, and I thought I'd share some tidbits.
NOTE: The following does not apply to fixed dyes. Fixed dyes use a totally different system.
[SIZE="4"]Palettes[/SIZE]
When you use a dye ampule, you're really just selecting a predefined color from something called a "palette", which is literally just a collection of colors. As Rydian has said before, the palettes are predefined by devcat, who likes to get... shall we say... creative. These palettes are stored in the client, in RAW format, and can be viewed if you have some technical knowledge.
Here are some examples of palettes:
Cloth (used for most items):
[Image: http://xcelled.rydian.net/colors/cloth/raw.png]
Metal:
[Image: http://xcelled.rydian.net/colors/metal/raw.png]
Bright Pastel:
[Image: http://xcelled.rydian.net/colors/bright_pastel/raw_big.png]
"Starking":
[Image: http://xcelled.rydian.net/colors/starking/raw.png]
So, the colors availible through the dye amps are limited to what's on the palettes. Itemdb.xml defines what palettes each part of the item uses, for those who care to know.
"But wait", you say. "Everyone knows the palettes look all groovy!"
[Image: http://wiki.mabinogiworld.com/images/c/c8/Cloth_Dye_Palette.png]
"Yeah, like that! So how come the ones you posted look so blocky?"
[SIZE="4"]Distortion[/SIZE]
When the game goes to use a palette in the dye window, it first runs it through a distortion function. This, along with some randomness sent from the server, ensures a different distribution of colors every time. It's also responsible for the characteristic "waves" in the colors.
Dye helpers like DyeLite and DoDye essentially screenshot Mabinogi, and then extract the color pool that way. Unfortunately, this method can be quite inaccurate, depending on how your graphics are rendered. DoDye even warns that ATI GPU's "can be 0.5-1.0 color notes off"! In an attempt to avoid this, I decided to make DyeRite mix the palettes itself. By not relying on screen scraping, I could be sure to have a pixel-perfect pool. But this meant I had to reverse engineer the distortion algorithm. A few days ago, I sat down, and with some assistance from my friend Kadalyn, successfully derived the algorithm.
I'll spare you the details of how, but here's what I found out:
- Each palette is fed through the distortion function up to four times.
- The distortion function is based on a precomputed sin^2 transformation, with a period of 256.
- The randomness from the server simply shifts the sin wave.
- Each transformation has a scale associated with it. This number determines the impact of the transformation. For example, transformation 4 has a scale of 0.03, so its effect can be hard to see.
- Most palettes run a horizontal transformation, then a vertical transformation, then a horizontal, and finally another vertical.
For those of you who don't know, a sin^2 wave looks like this:
[Image: http://4.bp.blogspot.com/_iCUnH8P-OYo/S7ZV48nkMiI/AAAAAAAAAOc/-cZqfcPkxuM/s1600/SineSquared.gif]
The final translation formula winds up being this:
[Image: http://quicklatex.com/cache3/33/ql_a18f5f15f97261b329829950ca9dad33_l3.png]
where a is the predefined scaling value, and r is the server-specified randomness. To get the vertical transformation, simply swap x and y.
Here's a step-by-step view of what happens with each transformation. Notice the sine wave is clearly visible.
[Image: http://i.imgur.com/0v1Dcr8.png]
[Image: http://i.imgur.com/xRbdC2U.png]
Next, I injected a simulated server randomness of "64, 0, 0, 0". Notice how the sine wave in the first transformation is now offset:
[Image: http://i.imgur.com/Jxv2b4T.png]
[SIZE="4"]Bonus Section: (Developer Secret)[/SIZE]
When I discovered this, Hanae told me it was called a "Developer's Secret".
If you look at a metal dye palette as rendered in game and compare it to the "metal.raw", you'll notice something... off.
In game:
[Image: http://wiki.mabinogiworld.com/images/8/84/Armorpalette.png]
Raw:
[Image: http://xcelled.rydian.net/colors/metal/raw.png]
Hmm... Seems to be colors missing from the in game version! And colors present in game that aren't in the palette! In fact, it's almost like they use two different palettes!
Guess what, they do. When using a dye amp, "metal", "weapon_edge", and "weapon_handle" redirect to "metal_dye", "weapon_edge_dye", and "weapon_handle_dye". Only those three.
And, if you're wondering, the two are quite different. Metal has 10,621 colors that are not in metal_dye, and metal_dye has 8,743 that aren't in metal. They share 3,139 colors.
Because item generation (monster drops, store, etc) pulls from the un-redirected palette, there are certain colors you can ONLY get by dyeing, and certain colors you can ONLY get by sheer luck.
[SIZE="4"]Additional resources[/SIZE]
Kadalyn created a python implementation of the distortion algorithm. This can be used to experiment with various parameters to see their effects. Find it here: https://github.com/logicplace/dye_warper
Because opening raw files isn't something the average person likes to do, I have converted the entirety of Mabi's "colors" directory to PNG format. This not only includes the dye palettes, but also some specialized palettes like "money" and "best_firewood". Note that, while the Money palette specifies a flashy color code, I have not interpreted it as such. It neither flashes, nor is it the proper color. (Due to how the flashy system works)
Each palette has a folder. In it, you'll find "raw.png", which is the 1-to-1 conversion from the raw file. Some palettes are tiny and hard to see, so "raw_big.png" blows them up to standard size. A sample distortion is included as "sample_distort.png". Finally, a list of every color contained in the palette is provided as "color.html". I warn you, these are often quite large and not very conducive to casual pursuing. Useful if you want to ctrl-f for a particular color, though.
Find it here: http://xcelled.rydian.net/colors/