## Hue Shader - kind of works, anyone want to take a stab at it?

Aug 07 2008 | 6:51 pm
Hello..
I noticed there was a lack of a hue rotation shader, which makes certain things difficult. I took a stab at it, and it ... kind of works. Im not certain what I am doing wrong, and frankly, kindof moved on. So I post it here for those who want to give it a shot and repair it:
// http://www.graficaobscura.com/matrix/index.html - Hue rotation Matrix calculations.
This should be pretty straightforward, so I assume im making an assumption I should not be about either the linear RGB colorspace (which, im 99 % sure is what textures are usually handed off as),
Other than that, anyone? Beuller?

• Aug 07 2008 | 6:53 pm
By The way, I STILL CANT EDIT MESSAGES, EVEN 0.5 NANO SECONDS AFTER I POSTED THEM. GOD I CANT STAND THE FORUM !~@#!@#
• Aug 08 2008 | 8:29 am
is it possible your code is right-multiplying the rotation matrices
while the original code is left-multiplying?
best-
parag.
• Aug 08 2008 | 10:24 am
no nevermind.
• Aug 08 2008 | 10:33 am
is this right?
// based on "Hue Rotation while preserving luminance"
// http://www.graficaobscura.com/matrix/index.html
// Paul Haeberli
//
// ported to glsl by vade
uniform float hue;
// define our varying texture coordinates
varying vec2 texcoord0;
// define our rectangular texture samplers
uniform sampler2DRect tex0;
// no need to compute these...
const float sqrt2 = 1.414213562373095;
const float sqrt3 = 1.732050807568877;
const float oneoversqrt2 = 0.707106781186548;
const float oneoversqrt3 = 0.577350269189626;
//const vec4 lumcoeff = vec4(0.299,0.587,0.114, 1.0);
const vec4 lumcoeff = vec4(0.3086,0.6094,0.0820, 1.0);
const float zsx = lumcoeff.x/lumcoeff.z;
const float zsy = lumcoeff.y/lumcoeff.z;
// matrix functions.
mat4 ident = mat4(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// red
mat4 rotateXMat(float rs, float rc)
{
return mat4(1.0, 0.0, 0.0, 0.0,
0.0, rc, rs, 0.0,
0.0, -rs, rc, 0.0,
0.0, 0.0, 0.0, 1.0);
}
// green
mat4 rotateYMat(float rs, float rc)
{
return mat4(rc, 0.0, -rs, 0.0,
0.0, 1.0, 0.0, 0.0,
rs, 0.0, rc, 0.0,
0.0, 0.0, 0.0, 1.0);
}
// blue
mat4 rotateZMat( float rs, float rc)
{
return mat4(rc, rs, 0.0, 0.0,
-rs, rc, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
}
mat4 shearZMatrix(float dx, float dy)
{
return mat4(1.0, 0.0, dx, 0.0,
0.0, 1.0, dy, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
}
vec4 xformpnt(mat4 matrix, vec4 inputVec)
{
return vec4( inputVec.x*matrix[0][0] + inputVec.y*matrix[1][0] +
inputVec.z*matrix[2][0] + matrix[3][0],
inputVec.x*matrix[0][1] + inputVec.y*matrix[1][1] +
inputVec.z*matrix[2][1] + matrix[3][1],
inputVec.x*matrix[0][2] + inputVec.y*matrix[1][2] +
inputVec.z*matrix[2][2] + matrix[3][2], 1.0);
}
void main (void)
{
vec4 inputVec = texture2DRect(tex0, texcoord0);
// setup our transform mat - cant convert a const
mat4 transformMat = ident;
// rotate grey vector into positive Z
transformMat = rotateXMat(oneoversqrt2, oneoversqrt2) * transformMat;
transformMat = rotateYMat(-oneoversqrt3, sqrt2/sqrt3) * transformMat;
// shear to preserve lumanince
vec4 something = xformpnt(transformMat, inputVec);
float zsx = something.x/something.z;
float zsy = something.x/something.z;
transformMat = shearZMatrix(zsx,zsy) * transformMat;
// rotate hue, make angle input in degrees
transformMat = rotateZMat(hue_rs, hue_rc) * transformMat;
// unshear to preserve luminance
transformMat = shearZMatrix(-zsx,-zsy) * transformMat;
// unrotate
transformMat = rotateYMat(oneoversqrt3, sqrt2/sqrt3 ) * transformMat;
transformMat = rotateXMat(-oneoversqrt2, oneoversqrt2) * transformMat;
// do the hue transformation on our pixels
inputVec *= transformMat;
// convert to a vec with proper rgb values from our mat4.
// gl_FragColor = vec4(input0Mat[0][0], input0Mat[1][1],
input0Mat[2][2], input0Mat[3][3] );
gl_FragColor = inputVec;
}
• Aug 08 2008 | 3:53 pm
Looks like we have a winner! Great stuff. Ill upload a zip with everything bundled, with credits to you in the source, of course. Thanks, I know a few folks who will really appreciate this.
• Aug 08 2008 | 4:21 pm
Here is the full shader jxs with vert and frag. I did not include an example/help patch.
The only parameter is 'hue', in degrees.
Thanks again PKM. I noticed your fixes do a bunch of additional matrix multiplies in there. Nice catches. :) This actually is of great help with some other stuff im working on :)
• Aug 08 2008 | 5:15 pm
of a y and not using the lumcoeffs. Just change these lines:
vec4 something = xformpnt(transformMat, inputVec);
float zsx = something.x/something.z;
float zsy = something.x/something.z;
transformMat = shearZMatrix(zsx,zsy) * transformMat;
to:
vec4 something = xformpnt(transformMat, lumcoeff);
float zsx = something.x/something.z;
float zsy = something.y/something.z;
transformMat = shearZMatrix(zsx,zsy) * transformMat;
Though to be honest, it looks more interesting with the typo...
• Aug 08 2008 | 5:35 pm
Or maybe this is actually what it should be? But how does gl_FragColor
accept that 4x4 * 1x4 = 4x4?
vec4 inputVec = texture2DRect(tex0, texcoord0);
// setup our transform mat - cant convert a const
mat4 transformMat = ident;
// rotate grey vector into positive Z
transformMat = rotateXMat(oneoversqrt2, oneoversqrt2) * transformMat;
transformMat = rotateYMat(-oneoversqrt3, sqrt2/sqrt3) * transformMat;
// shear to preserve lumanince
vec4 something = xformpnt(transformMat, lumcoeff);
float zsx = something.x/something.z;
float zsy = something.y/something.z;
transformMat = shearZMatrix(zsx,zsy) * transformMat;
// rotate hue, make angle input in degrees
transformMat = rotateZMat(hue_rs, hue_rc) * transformMat;
// unshear to preserve luminance
transformMat = shearZMatrix(-zsx,-zsy) * transformMat;
// unrotate
transformMat = rotateYMat(oneoversqrt3, sqrt2/sqrt3 ) * transformMat;
transformMat = rotateXMat(-oneoversqrt2, oneoversqrt2) * transformMat;
// do the hue transformation on our pixels
inputVec = transformMat * inputVec;
// convert to a vec with proper rgb values from our mat4.
gl_FragColor = inputVec;
Ok I'm checking gimp/ps in a second to see what it's really supposed
to look like...
• Aug 08 2008 | 5:38 pm
ok yea the last one i sent is what photoshop says.
sorry for the confusion! :)
• Jun 16 2009 | 3:39 am
Hi,
I just tried loading this shader into a jit.gl.slab, and for some reason everything just passes through completely unaffected. Sending "param hue \$1" doesn't seem to do anything. Any thoughts as to why this might be the case?
.mmb
• Sep 15 2010 | 1:58 pm