// // Gives you the abilty to quickly tweak the hue saturation and lightness // and value of the incoming image // // ----------------------------------------------------------------------------- // PARAMETERS: // ----------------------------------------------------------------------------- //transforms float4x4 tW: WORLD; //the models world matrix float4x4 tV: VIEW; //view matrix as set via Renderer (EX9) float4x4 tP: PROJECTION; float4x4 tWVP: WORLDVIEWPROJECTION; //texture texture Image ; sampler Samp = sampler_state //sampler for doing the texture-lookup { Texture = (Image); //apply a texture to the sampler MipFilter = LINEAR; //sampler states MinFilter = LINEAR; MagFilter = LINEAR; }; // texture transformation marked with semantic TEXTUREMATRIX to achieve // symmetric transformations float4x4 tTex: TEXTUREMATRIX ; // input for hue offset float hue < string uiname="Hue offset"; float uimin=-1.0; float uimax=1.0; > = 0.0; // input for hue change float sat < string uiname="value offset"; float uimin=-1.0; float uimax=1.0; > = 0.0; // input for hue change float value < string uiname="Lightness offset"; float uimin=-1.0; float uimax=1.0; > = 0.0; //the data structure: "vertexshader to pixelshader" //used as output data with the VS function //and as input data with the PS function struct vs2ps { float4 Pos : POSITION; float2 TexCd : TEXCOORD0; }; // --------------------------------------------------------------------------- // Functions // --------------------------------------------------------------------------- // converts an RGB value to an HSV value // taken from // http://www.ati.com/developer/shaderx/ShaderX2_AdvancedImageProcessing.pdf float4 RGB_to_HSV (float4 incolor) { float delta; float colorMax, colorMin; float h,s,v; colorMax = max (incolor.r,incolor.g); colorMax = max (colorMax,incolor.b); colorMin = min (incolor.r,incolor.g); colorMin = min (colorMin,incolor.b); v = colorMax; // this is value if (colorMax != 0) { s = (colorMax - colorMin) / colorMax; } if (s != 0) // if not achromatic { delta = colorMax - colorMin; if (incolor.r == colorMax) { h = (incolor.g-incolor.b)/delta; } else if (incolor.g == colorMax) { h = 2.0 + (incolor.b-incolor.r) / delta; } else // b is max { h = 4.0 + (incolor.r-incolor.g)/delta; } h *= 60; if( h < 0) { h +=360; } h = h/360.0; // moving h to be between 0 and 1. } float4 hsv = {h,s,v,1.0}; return hsv; } float4 HSV_to_RGB (float4 hsv) { float4 outcolor = {0.0,0.0,0.0,1.0}; float p,q,t; float h,s,v; float i; if (hsv[1] == 0) { outcolor = hsv[2]; } else { h = hsv.x * 360.0; s = hsv.y; v = hsv.z; if (h == 360.0) { h = 0; } h /= 60; i = floor (h); p = v * (1.0 - s); q = v * (1.0 - (s * (h-i))); t = v * (1.0 - (s * (1.0 -(h-i)))); if (i == 0) { outcolor.r = v; outcolor.g = t; outcolor.b = p; } else if (i == 1) { outcolor.r = q; outcolor.g = v; outcolor.b = p; } else if (i == 2) { outcolor.r = p; outcolor.g = v; outcolor.b = t; } else if (i == 3) { outcolor.r = p; outcolor.g = q; outcolor.b = v; } else if (i == 4) { outcolor.r = t; outcolor.g = p; outcolor.b = v; } else if (i == 5) { outcolor.r = v; outcolor.g = p; outcolor.b = q; } else { outcolor.r = v; outcolor.g = t; outcolor.b = p; } } return outcolor; } // -------------------------------------------------------------------------------------------------- // VERTEXSHADERS // -------------------------------------------------------------------------------------------------- vs2ps VS( float4 PosO : POSITION, float4 TexCd : TEXCOORD0) { //inititalize all fields of output struct with 0 vs2ps Out = (vs2ps)0; //transform position Out.Pos = mul(PosO, tWVP); //transform texturecoordinates Out.TexCd = mul(TexCd, tTex); return Out; } // -------------------------------------------------------------------------------------------------- // PIXELSHADERS: // -------------------------------------------------------------------------------------------------- float4 psRGBToHSV(vs2ps In): COLOR { float4 col = tex2D(Samp, In.TexCd); float4 outColor = {0.0,0.0,0.0,1.0}; float4 temp = {0.0,0.0,0.0,1.0}; float4 hsv = {hue,sat,value,1.0}; //convert the pixel color from rgb to hsv temp = RGB_to_HSV(col); temp[0] = saturate (abs(temp[0] + hue)); temp[1] = saturate (temp[1] + sat); temp[2] = saturate (temp[2] + value); //convert back outColor = HSV_to_RGB(temp); // add the alpha back in as it gets stripped to save instructions in the // hsvToRgb functions outColor.a = col.a; return outColor; } float4 psColorize(vs2ps In): COLOR { float4 col = tex2D(Samp, In.TexCd); float4 outColor = {0.0,0.0,0.0,1.0}; outColor = RGB_to_HSV(col); // the only difference between the 2 techniques is that this one does // not try to add to the incoming hue for the pixel, it just takes the // absolute value from the slider outColor[0] = (abs(hue)); outColor[1] = saturate (outColor[1] + sat); outColor[2] = saturate (outColor[2] + value); outColor = HSV_to_RGB(outColor); outColor.a = col.a; return outColor; } // -------------------------------------------------------------------------------------------------- // TECHNIQUES: // -------------------------------------------------------------------------------------------------- technique ColorOffset { pass P0 { VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_2_0 psRGBToHSV(); } } technique Colorize { pass P0 { VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_2_0 psColorize(); } } technique TFixedFunction { pass P0 { //transforms WorldTransform[0] = (tW); ViewTransform = (tV); ProjectionTransform = (tP); //texturing Sampler[0] = (Samp); TextureTransform[0] = (tTex); TexCoordIndex[0] = 0; TextureTransformFlags[0] = COUNT2; //Wrap0 = U; // useful when mesh is round like a sphere Lighting = FALSE; //shaders VertexShader = NULL; PixelShader = NULL; } }