Hue shift shader not playing nice on IOS only?

Hi there, hoping some of you gurus here can assist me with this.

I have a cross-platform app. This particular GLSL shader code is used to shift the hue of a particular texture.

It works great on Android and when debugging on Desktop, but on an iPad this is the result (excuse photos of screen, easiest way to get data from this device).

Code:

const mat3 rgb2yiq = mat3(0.299, 0.595716, 0.211456, 0.587, -0.274453, -0.522591, 0.114, -0.321263, 0.311135);
const mat3 yiq2rgb = mat3(1.0, 1.0, 1.0, 0.9563, -0.2721, -1.1070, 0.6210, -0.6474, 1.7046);

vec4 outColor = texture2D(u_texture, v_texCoord) * v_color;

// Hue shift
if (u_hueAdjust > 0.0 && u_hueAdjust < 1.0)
{
  vec3 yColor = rgb2yiq * outColor;

  float originalHue = atan(yColor.b, yColor.g);
  float finalHue = originalHue + u_hueAdjust * 6.28318; //convert 0-1 to radians

  float chroma = sqrt(yColor.b * yColor.b + yColor.g * yColor.g);

  vec3 yFinalColor = vec3(yColor.r, chroma * cos(finalHue), chroma * sin(finalHue));
  outColor.rgb = yiq2rgb * yFinalColor;
}

Obviously there’s some really weird artifacts that seem to affect certain areas, in particular black/white colors. But also in general a subtle change in color is noted that isn’t attributable to a desired hue-change effect.

Overall this shader is wonky on IOS (but working fine on Android/Desktop), but after playing with it for a while I’m completely out of ideas, anyone lead me in the right direction?

Thanks for any ideas!

A legendary hero on stackoverflow pointed me to this (c++ - Robust atan(y,x) on GLSL for converting XY coordinate to angle - Stack Overflow)

atan(y,x) doesn’t play nice when x is 0.0, in some cases

Replaced atan(y,x) with
(x == 0.0 ? sign(y)*PI/2 : atan(y, x))

This code converts yColor.gb to polar coordinates, modifies its angle, then converts back to Cartesian coordinates. You can avoid the issue of (0,0) having an indeterminate angle by avoiding polar coordinates. Convert the hue change angle u_hueAdjust * 6.28318 to a rotation matrix then transform the vector yColor.gb by it. IOW:

  vec3 yColor = rgb2yiq * outColor;

  float hueAngle = u_hueAdjust * 6.28318; //convert 0-1 to radians
  float c = cos(hueAngle);
  float s = sin(hueAngle);
  vec3 yFinalColor = vec3(yColor.r, mat2(c,s,-s,c) * yColor.gb);

  outColor.rgb = yiq2rgb * yFinalColor;

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.