Bitmap: Use more accurate HSV-based hue shift algorithm

The previously YIQ-based algorithm turned out to be both slow,
and horribly inaccurate.

Another algorithm based on rotating the color value in the
RGB cube along the diagonal axis was also considered, which was
acceptable in terms of accuracy, and very fast.

In the end, I decided on a HSV-based one, because it is by far
the most accurate one, while still being a tad faster than the
YIQ solution.
Algorithm source: gamedev.stackexchange.com/a/59808/24839

A very simple GPU time benchmark when shifting a 2048^2 bitmap:

         YIQ rot   RGB rot   HSV shift
radeon   13.4 ms   2.8 ms    11.4 ms
intel    13.0 ms   6.0 ms    10.5 ms

radeon: HD 3650 mobility
intel:  N3540 integrated (Baytrail)

However hue shifting has never shown up as a bottleneck before,
so these are more academic.
This commit is contained in:
Jonas Kulla 2016-10-04 15:16:57 +02:00
parent 0ec1fce4ac
commit 541e24f678
4 changed files with 34 additions and 52 deletions

View file

@ -854,13 +854,10 @@ void Bitmap::hueChange(int hue)
quad.setTexPosRect(texRect, texRect);
quad.setColor(Vec4(1, 1, 1, 1));
/* Calculate hue parameter */
hue = wrapRange(hue, 0, 359);
float hueAdj = -((M_PI * 2) / 360) * hue;
HueShader &shader = shState->shaders().hue;
shader.bind();
shader.setHueAdjust(hueAdj);
/* Shader expects normalized value */
shader.setHueAdjust(wrapRange(hue, 0, 359) / 360.0f);
FBO::bind(newTex.fbo);
p->pushSetViewport(shader);

View file

@ -551,7 +551,6 @@ HueShader::HueShader()
ShaderBase::init();
GET_U(hueAdjust);
GET_U(inputTexture);
}
void HueShader::setHueAdjust(float value)
@ -559,11 +558,6 @@ void HueShader::setHueAdjust(float value)
gl.Uniform1f(u_hueAdjust, value);
}
void HueShader::setInputTexture(TEX::ID tex)
{
setTexUniform(u_inputTexture, 0, tex);
}
SimpleMatrixShader::SimpleMatrixShader()
{

View file

@ -241,10 +241,9 @@ public:
HueShader();
void setHueAdjust(float value);
void setInputTexture(TEX::ID tex);
private:
GLint u_hueAdjust, u_inputTexture;
GLint u_hueAdjust;
};
class SimpleMatrixShader : public ShaderBase