Ancurio / mkxp

Free Software implementation of the Ruby Game Scripting System (RGSS)
GNU General Public License v2.0
511 stars 129 forks source link

Hue of Battlers is wrong #151

Closed sorlok closed 7 years ago

sorlok commented 7 years ago

If I make a game with the following Battler image: http://i.cubeupload.com/v8FbYp.png

...and then create an Enemy that has this image with hue=160, I get this in RPG Maker VX: http://i.cubeupload.com/rTRsbs.png

...and this in MKXP: http://i.cubeupload.com/f6Ok2p.png

I've tracked this through the code a bit, and it seems to be correct as of Bitmap::hueChange(), at which point it's handed off to the Hue Shader.

Any idea what might be going on here?

sorlok commented 7 years ago

In particular, looking at the Hue chart, we have: http://i.cubeupload.com/HIzQq4.png

Top is RMVX, bottom is MKXP.

So it looks like MKXP has calculated the hue offset correctly, but has inadvertently lightened/darkened some parts of the image.

Ancurio commented 7 years ago

The hue shader is not 100% accurate because it uses YIQ colorspace conversion for performance (from here); basically, the color is mapped to a point on a slice of the YIQ cube like this one (Y=0.5), then rotated along the origin and converted back to RGB.

I will try to investigate / find a better branch-less algorithm when I get the time. This one looks promising though.

Ancurio commented 7 years ago

I wrote a test app with Qt4 to compare the two algorithms, against a reference HSV based shift (if you happen to be on Linux): source code / binary

If you uncomment the "unclamped" RGB rotation version, you can clearly see how it washes out at all the points which are rotated out of the RGB cube and clamped, similarly to YIQ. However, it doesn't quite "brown out" as YIQ does. I'd say it's a small improvement. Specifically for your 4-color square battler, it happens to match the reference a lot better (but that's also at a convenient angle, if you shift by 180° instead, you'll see that it doesn't quite hit the yellow).

On the other hand, the code is a whole lot simpler compared to YIQ, and also faster, since the fragment shader only has to do one matrix vector multiplication instead of two and a bunch of other trigonometry, and the nasty I == 0 check is also gone. So I'd definitely consider switching to it regardless of accuracy gains. Tell me what you think.

cube_screen

sorlok commented 7 years ago

Just had a chance to try this out. The RGB rotation looks a lot better (I can see some areas where it is off a bit, but in all those cases, the YIQ is even worse).

Since it's simpler, (probably) faster, and at least slightly better than YIQ, I think replacing it is the right thing to do.

sorlok commented 7 years ago

Just checking in: any update on this?

Ancurio commented 7 years ago

I've found a good code snippet that implements RGB<->HSV conversion without branching and implemented that, but I want to test perf of it relative to RGB rotation, for which I haven't found the time yet.

sorlok commented 7 years ago

Sounds good. Thanks for the update.

Ancurio commented 7 years ago

Sorry for the delay, had some huge real life issues T_T

I pushed the new algorithm to master, can you try it out?

sorlok commented 7 years ago

No worries for the delay, and I hope your RL issues got resolved. :)

My initial experiments with the new algorithm look good! I'll close this now, and do more testing next week (currently on the road). Thanks again for the fix!