Forums > Jitter

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

August 7, 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?


August 7, 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 !~@#!@#



PKM
August 8, 2008 | 8:29 am

is it possible your code is right-multiplying the rotation matrices
while the original code is left-multiplying?

best-
parag.



PKM
August 8, 2008 | 10:24 am

no nevermind.



PKM
August 8, 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

float hue_rs = sin(radians(hue));
float hue_rc = cos(radians(hue));
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;
}


August 8, 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.


August 8, 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 :)



PKM
August 8, 2008 | 5:15 pm

Sorry vade- I had a serious type in there originally with an x instead
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…



PKM
August 8, 2008 | 5:35 pm

Or maybe this is actually what it should be? But how does gl_FragColor
accept that 4×4 * 1×4 = 4×4?

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

float hue_rs = sin(radians(hue));
float hue_rc = cos(radians(hue));
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…



PKM
August 8, 2008 | 5:38 pm

ok yea the last one i sent is what photoshop says.

sorry for the confusion! :)


June 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


September 15, 2010 | 1:58 pm

I tried your shader and I got the error: "jit.gl.shader: error reading shader xml file"

I think it misses some part of the codes to make it working… I’m quite beginner in coding shader…

could you send the whole finale version of the shader please?

Thanks


September 16, 2010 | 6:12 pm

Yeah I tried taking a stab at this one a few weeks ago…if you get stuck in a bind without a working shader and need something similar and are on a mac..I use this: [jit.gl.imageunit @fx "Hue Adjust"] ..the imageunits can be useful in certain situations, but a normal glsl shader would be nice too..will just take some time for vade to come back around here, he still comes though


March 12, 2014 | 10:43 pm

Hi guys,
I needed something like this for a project of mine and was grateful to find this post. However it seems C74 has changed up the forums (now on WordPress) and lost the attachments for this thread in the process. I’ve pieced the working .jxs back together from PKM’s post and some of the the other stock color shaders. Please find the shader (just install in the jitter-shaders/color directory) and a quick test patch for it attached. Hope this is useful for future users.

I’m not sure if this version corrects for luminance shift across hue (the human eye is apparently not equally sensitive to all shades) but I don’t much mind since I’m using it for special effects rather than corrective editing.

Apparently the new forums don’t allow .jxs uploads; just remove the .txt extension and install normally.


Viewing 14 posts - 1 through 14 (of 14 total)