Sign In

crabshank

User Group
Trusted Members
Join date
18-Oct-2018
Last activity
21-Jul-2019
Posts
3

Post History

Post
#1250165
Topic
Curves (based on G'MIC) and HSV dither hlsl
Time

An example (using the shader posted):

http://www.framecompare.com/screenshotcomparison/WYD7NNNX

I also have an image remapping page that does histogram matching for selected channels. It also presents all the options to white balance (just give it an image containing areas that are supposed to be greyscale)

https://github.com/crabshank/HLSL-Reshade-colour-remappers/blob/master/Image histogram.html

Post
#1250040
Topic
Curves (based on G'MIC) and HSV dither hlsl
Time

Since I thought that the Curves function in G’MIC (GIMP) was very good for colour mapping, I wanted to use it for video in some way. So I created this code that lets you remap RGB and HSV values. It just does straight line interpolation, not curves.

I also have a dithering shader that allows you to increase the mean or standard deviation of a channel by adding (pseudo-)random amounts according to a uniform distribution (almost). I strongly suggest using grey dithering’s standard deviation settings for deblocking video.

sampler s0 : register(s0);
float4 p0 :  register(c0);
float4 p1 :  register(c1);

#define width   (p0[0])
#define height  (p0[1])
#define counter (p0[2])
#define clock   (p0[3])
#define one_over_width  (p1[0])
#define one_over_height (p1[1])


float3 rgb2hsv(float3 c)
{
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
    float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
 
    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}


float3 hsv2rgb(float3 c)
{
    float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
//Source: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl

//Bounds for interpolation//
static float r_x_b[2]={0,1};static float r_y_b[2]={0,1};static float g_x_b[2]={0,1};static float g_y_b[2]={0,1};static float b_x_b[2]={0,1};static float b_y_b[2]={0,1};static float h_x_b[2]={0,1};static float h_y_b[2]={0,1};static float s_x_b[2]={0,1};static float s_y_b[2]={0,1};static float v_x_b[2]={0,1};static float v_y_b[2]={0,1};

#define red_on 0
#define red_points 3

static float2 r[red_points] = {
0, 0,    // row 1; x,y
128,128,
255,255
};

#define green_on 0
#define green_points 3

static float2 g[green_points] = {
0, 0,    // row 1; x,y
128,128,
255,255
};

#define blue_on 0
#define blue_points 3

static float2 b[blue_points] = {
0, 0,    // row 1; x,y
128,128,
255,255
};


static float rotate_hues = 0; //-360 to 360

#define hue_on 1
#define hue_points 7

static float2 h[hue_points] = {
0, 0,    // row 1; x,y
10,10,
120,128,
185,183,
294,302,
302,310,
360,360
};

#define sat_on 1
#define sat_range 100
#define sat_points 3

static float2 s[sat_points] = {
0, 0,    // row 1; x,y
69,80,
100,100
};

#define val_on 1
#define val_range 100
#define val_points 4

static float2 v[val_points]= {
0, 0,    // row 1; x,y
35,34,
77,84,
100,100
};

#define split 1
#define noWorseWB 0

float red_map(float red){int i=0;int exact=0;[unroll(red_points)]for(i=0;i<red_points;i++){if(r[i][0]/255==red) {red=r[i][1]/255;exact=1;i=red_points-1;}else{if(r[i][0]/255<red&&r[i][0]/255>=r_x_b[0]){r_x_b[0]=r[i][0]/255;r_y_b[0]=r[i][1]/255;} if(r[i][0]/255<=r_x_b[1]&&red<r[i][0]/255){r_x_b[1]=r[i][0]/255;r_y_b[1]=r[i][1]/255;}}} if(exact==0){red=r_y_b[0]+(red-r_x_b[0])*((r_y_b[1]-r_y_b[0])/(r_x_b[1]-r_x_b[0]));}return red;} 

float green_map(float green){int i=0;int exact=0;[unroll(green_points)]for(i=0;i<green_points;i++){if(g[i][0]/255==green) {green=g[i][1]/255;exact=1;i=green_points-1;}else{if(g[i][0]/255<green&&g[i][0]/255>=g_x_b[0]){g_x_b[0]=g[i][0]/255;g_y_b[0]=g[i][1]/255;} if(g[i][0]/255<=g_x_b[1]&&green<g[i][0]/255){g_x_b[1]=g[i][0]/255;g_y_b[1]=g[i][1]/255;}}} if(exact==0){green=g_y_b[0]+(green-g_x_b[0])*((g_y_b[1]-g_y_b[0])/(g_x_b[1]-g_x_b[0]));}return green;} 

float blue_map(float blue){int i=0;int exact=0;[unroll(blue_points)]for(i=0;i<blue_points;i++){if(b[i][0]/255==blue) {blue=b[i][1]/255;exact=1;i=blue_points-1;}else{if(b[i][0]/255<blue&&b[i][0]/255>=b_x_b[0]){b_x_b[0]=b[i][0]/255;b_y_b[0]=b[i][1]/255;} if(b[i][0]/255<=b_x_b[1]&&blue<b[i][0]/255){b_x_b[1]=b[i][0]/255;b_y_b[1]=b[i][1]/255;}}} if(exact==0){blue=b_y_b[0]+(blue-b_x_b[0])*((b_y_b[1]-b_y_b[0])/(b_x_b[1]-b_x_b[0]));}return blue;} 

float hue_rotate(float hue,float rot){rot*=pow(360,-1);float r=hue+rot;if(r<0){return 1+r;}else if(r>1){return r-1;}else{return r;}}

float hue_map(float hue){int i=0;int exact=0;[unroll(hue_points)]for(i=0;i<hue_points;i++){if(h[i][0]/360==hue) {hue=h[i][1]/360;exact=1;i=hue_points-1;}else{if(h[i][0]/360<hue&&h[i][0]/360>=h_x_b[0]){h_x_b[0]=h[i][0]/360;h_y_b[0]=h[i][1]/360;} if(h[i][0]/360<=h_x_b[1]&&hue<h[i][0]/360){h_x_b[1]=h[i][0]/360;h_y_b[1]=h[i][1]/360;}}} if(exact==0){hue=h_y_b[0]+(hue-h_x_b[0])*((h_y_b[1]-h_y_b[0])/(h_x_b[1]-h_x_b[0]));}return hue;} 

float sat_map(float sat){int i=0;int exact=0;[unroll(sat_points)]for(i=0;i<sat_points;i++){if(s[i][0]/sat_range==sat) {sat=s[i][1]/sat_range;exact=1;i=sat_points-1;}else{if(s[i][0]/sat_range<sat&&s[i][0]/sat_range>=s_x_b[0]){s_x_b[0]=s[i][0]/sat_range;s_y_b[0]=s[i][1]/sat_range;} if(s[i][0]/sat_range<=s_x_b[1]&&sat<s[i][0]/sat_range){s_x_b[1]=s[i][0]/sat_range;s_y_b[1]=s[i][1]/sat_range;}}} if(exact==0){sat=s_y_b[0]+(sat-s_x_b[0])*((s_y_b[1]-s_y_b[0])/(s_x_b[1]-s_x_b[0]));}return sat;} 

float val_map(float val){int i=0;int exact=0;[unroll(val_points)]for(i=0;i<val_points;i++){if(v[i][0]/val_range==val) {val=v[i][1]/val_range;exact=1;i=val_points-1;}else{if(v[i][0]/val_range<val&&v[i][0]/val_range>=v_x_b[0]){v_x_b[0]=v[i][0]/val_range;v_y_b[0]=v[i][1]/val_range;} if(v[i][0]/val_range<=v_x_b[1]&&val<v[i][0]/val_range){v_x_b[1]=v[i][0]/val_range;v_y_b[1]=v[i][1]/val_range;}}} if(exact==0){val=v_y_b[0]+(val-v_x_b[0])*((v_y_b[1]-v_y_b[0])/(v_x_b[1]-v_x_b[0]));}return val;}

float4 remapper(float4 c0){
float3 orig=c0.rgb;
if(red_on==1){c0.r=red_map(c0.r);}		//red
if(green_on==1){c0.g=green_map(c0.g);}	//green
if(blue_on==1){c0.b=blue_map(c0.b);}	//blue

if (noWorseWB==1){

float3 origHSV=rgb2hsv(orig.rgb);
float3 newHSV=rgb2hsv(c0.rgb);
float origMin=min(orig.r,min(orig.g,orig.b));
float newMin=min(c0.r,min(c0.g,c0.b));

float ogChoice=origMin*(1-origHSV.y)+pow(1-origMin,2);
float nwChoice=newMin*(1-newHSV.y)+pow(1-newMin,2);

if (ogChoice>nwChoice){
c0.rgb=orig.rgb;
}

}

float3 colorHSV= rgb2hsv(c0.rgb);
	if(rotate_hues!=0){
	colorHSV.x=hue_rotate(colorHSV.x,rotate_hues);
	c0.rgb=hsv2rgb(colorHSV); colorHSV= rgb2hsv(c0.rgb); //hue rotate
}


	if(hue_on==1){
colorHSV.x=hue_map(colorHSV.x);
c0.rgb=hsv2rgb(colorHSV); 
colorHSV= rgb2hsv(c0.rgb); //hue
	}

if(sat_on==1){
colorHSV.y=sat_map(colorHSV.y); 
c0.rgb=hsv2rgb(colorHSV); 
colorHSV= rgb2hsv(c0.rgb); //sat
}

if(val_on==1){
colorHSV.z=val_map(colorHSV.z);
c0.rgb=hsv2rgb(colorHSV);
colorHSV= rgb2hsv(c0.rgb); //val
}

	return c0;


}


float4 main(float2 tex : TEXCOORD0) : COLOR {
	float4 c0 = tex2D(s0, tex);
	
float divLine=0.5;

float divThk=(0.0008*width)*one_over_width;

if (split==1){
if(tex.x*width>=(divLine-divThk)*width && tex.x*width<=(divLine+divThk)*width){
c0.xyz=0;
return c0;

}

if(tex.x*width>(divLine+divThk)*width){
	
return remapper(c0);

}
else {

return c0;

}
}else{

return remapper(c0);

}

}

Here’s the HSV+CMY dither:

sampler s0 : register(s0);
float4 p0 :  register(c0);
float4 p1 :  register(c1);

#define width   (p0[0])
#define height  (p0[1])
#define counter (p0[2])
#define clock   (p0[3])
#define one_over_width  (p1[0])
#define one_over_height (p1[1])



float3 rgb2hsv(float3 c)
{
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}


float3 hsv2rgb(float3 c)
{
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
} 
//Source: http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl

static float d_x_b[2]={0,1};static float d_y_b[2]={0,1};
 
#define dither_points 7

static float2 d[dither_points] = {
0,0,
1,0,
64.90915,63.75,
131.4898,127.5,
194.1036,191.25,
254,255,
255,255
};

float dither_map(float dither){int i=0;int exact=0;[unroll(dither_points)]for(i=0;i<dither_points;i++){if(d[i][0]/255==dither) {dither=d[i][1]/255;exact=1;i=dither_points-1;}else{if(d[i][0]/255<dither&&d[i][0]/255>=d_x_b[0]){d_x_b[0]=d[i][0]/255;d_y_b[0]=d[i][1]/255;} if(d[i][0]/255<=d_x_b[1]&&dither<d[i][0]/255){d_x_b[1]=d[i][0]/255;d_y_b[1]=d[i][1]/255;}}} if(exact==0){dither=d_y_b[0]+(dither-d_x_b[0])*((d_y_b[1]-d_y_b[0])/(d_x_b[1]-d_x_b[0]));}return dither;} 


float random( float2 p )
{
// We need irrationals for pseudo randomness.
// Most (all?) known transcendental numbers will (generally) work.
const float2 r = float2(
23.1406926327792690,  // e^pi (Gelfond's constant)
 2.6651441426902251); // 2^sqrt(2) (Gelfond-Schneider constant)

float t=frac(acos(p.x/p.y)+sin(p.x)*r.y+cos(p.y)*r.x+p.x*p.y*r.y);

t= frac((800*cos(t/20)+1400)*t);  
t= frac(pow( frac((0.01*t+sin(500*t*t))+tan(t*500)*500),2));

float rMap =3.98;
float tOld=t;
int i=0;

[unroll(100)]for (i=0;i<100;i++){
tOld=rMap*tOld*(1-tOld);
}
 
 float w = frac(10000*tOld+0.597*tOld);


return dither_map(w);

}

float hue_rotate(float hue,float rot){rot*=pow(360,-1);float r=hue+rot;if(r<0){return 1+r;}else if(r>1){return r-1;}else{return r;}} 


float3 h_dither(float3 colorHSV,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*colorHSV.x,(tex.y+height*one_over_width)*colorHSV.x));
float randm=rnd*-1*((rand*-4)+1); // averages to rnd

 //shift the hue by dither_shift
colorHSV.x= hue_rotate(colorHSV.x,randm);
float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
colorHSV.x= hue_rotate(colorHSV.x,randm);

if(gamma!=1){


float colorSc=colorHSV.x*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-colorHSV.x)*-1*((rand*-4)+1);
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-colorHSV.x)*-1*((rand*-4)+1);  
}
colorHSV.x= hue_rotate(colorHSV.x,randm*360);
}


float3 color = hsv2rgb(colorHSV);

return color;
}


float3 s_dither(float3 colorHSV,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*colorHSV.y,(tex.y+height*one_over_width)*colorHSV.y));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

 //shift the saturation by dither_shift
colorHSV.y= saturate(colorHSV.y+(randm/100));

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
colorHSV.y= saturate(colorHSV.y+(randm/100));


if(gamma!=1){


float colorSc=colorHSV.y*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-colorHSV.y)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-colorHSV.y)*-1*((rand*-4)+1);   //;
}

colorHSV.y= saturate(colorHSV.y+randm);
}


float3 color = hsv2rgb(colorHSV);

return color;
}


float3 v_dither(float3 colorHSV,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*colorHSV.z,(tex.y+height*one_over_width)*colorHSV.z));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

colorHSV.z= saturate(colorHSV.z+(randm/100));

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
colorHSV.z= saturate(colorHSV.z+(randm/100));

if(gamma!=1){


float colorSc=colorHSV.z*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-colorHSV.z)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-colorHSV.z)*-1*((rand*-4)+1);   //;
}

colorHSV.z= saturate(colorHSV.z+randm);
}



float3 color = hsv2rgb(colorHSV);

return color;
}

float r_dither(float color,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
color= saturate(color+(randm/255));





if(gamma!=1){


float colorSc=color*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-color)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-color)*-1*((rand*-4)+1);   //;
}

color= saturate(color+randm);
}





return color;

}

float g_dither(float color,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
color= saturate(color+(randm/255));

if(gamma!=1){


float colorSc=color*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-color)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-color)*-1*((rand*-4)+1);   //;
}

color= saturate(color+randm);
}

return color;
}

float b_dither(float color,float2 tex,float rnd,float sdv, float gamma){


float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
color= saturate(color+(randm/255));

if(gamma!=1){


float colorSc=color*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-color)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-color)*-1*((rand*-4)+1);   //;
}

color= saturate(color+randm);
}

return color;
}



float3 c_dither(float color,float2 tex,float rnd,float sdv, float gamma){

color=1-color; //Red -> cyan

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));  //Act on cyan
float newCyan=color;	//Remember cyan
color=1-color; //Cyan -> red

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
newCyan= saturate(newCyan+(randm/255));

if(gamma!=1){


float colorSc=newCyan*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-newCyan)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-newCyan)*-1*((rand*-4)+1);   //;
}

newCyan= saturate(newCyan+randm);
}
color=1-newCyan;
return color;
}


float3 m_dither(float color,float2 tex,float rnd,float sdv, float gamma){
color=1-color;

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));
float newMagenta=color;
color=1-color;

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
newMagenta= saturate(newMagenta+(randm/255));

if(gamma!=1){


float colorSc=newMagenta*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-newMagenta)*-1*((rand*-4)+1);
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-newMagenta)*-1*((rand*-4)+1); 
}

newMagenta= saturate(newMagenta+randm);
}

color=1-newMagenta;
return color;

}


float3 y_dither(float color,float2 tex,float rnd,float sdv, float gamma){
color=1-color;

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= saturate(color+(randm/255));
float newYellow=color;
color=1-color;

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
newYellow= saturate(newYellow+(randm/255));

if(gamma!=1){


float colorSc=newYellow*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-newYellow)*-1*((rand*-4)+1);
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-newYellow)*-1*((rand*-4)+1); 
}

newYellow= saturate(newYellow+randm);
}

color=1-newYellow;

return color;

}

float grey_dither(float color,float2 tex,float rnd,float sdv, float gamma){

float rand=random(float2((tex.x+width*one_over_height)*color,(tex.y+height*one_over_width)*color));
float randm=rnd*-1*((rand*-4)+1); // averages to color + rnd

color= color+(randm/255);

float sAB=sdv*sqrt(12)*0.5;
randm=sAB*(2*rand-1)*-1;
color= color+(randm/255);
if(gamma!=1){


float colorSc=color*2;
if(colorSc<0.5){
randm=(pow(abs(0.5*colorSc),gamma)-color)*-1*((rand*-4)+1); //
}else{
randm=((1-(0.5*pow(abs(2-colorSc),gamma)))-color)*-1*((rand*-4)+1);   //;
}

color= color+randm;
}
return color;

}

#define greyDebug 0
#define split 0

#define hueDither  0
#define hueDitherAmnt 0  //Move average value up or down by an amount by dithering
#define hueDitherSdv 0 //Change standard deviation
#define hueDitherScurve 1



#define satDither 0
#define satDitherAmnt 0
#define satDitherSdv 0
#define satDitherScurve 1


#define valDither 0
#define valDitherAmnt 0
#define valDitherSdv 0
#define valDitherScurve 1


#define redDither 0
#define redDitherAmnt 0
#define redDitherSdv 0
#define redDitherScurve 1


#define greenDither 0
#define greenDitherAmnt 0
#define greenDitherSdv 0
#define greenDitherScurve 1



#define blueDither 0
#define blueDitherAmnt 0
#define blueDitherSdv 0
#define blueDitherScurve 1


#define cyanDither 0
#define cyanDitherAmnt 0
#define cyanDitherSdv 0
#define cyanDitherScurve 1



#define magentaDither 0
#define magentaDitherAmnt 0
#define magentaDitherSdv 0
#define magentaDitherScurve 1


#define yellowDither 0
#define yellowDitherAmnt 0
#define yellowDitherSdv 0
#define yellowDitherScurve 1

#define rgbDither 0
#define rgbDitherAmnt 0
#define rgbDitherSdv 0
#define rgbDitherScurve 1


#define greyDither 0
#define greyDitherAmnt 0
#define greyDitherSdv 0
#define greyDitherScurve 1


float4 ditherer(float4 c0, float2 tex){
float3 colorHSV= rgb2hsv(c0.rgb);
if (hueDither==1){
c0.rgb=h_dither(colorHSV,tex,hueDitherAmnt,hueDitherSdv,hueDitherScurve); colorHSV= rgb2hsv(c0.rgb);
}

if (satDither==1){
c0.rgb=s_dither(colorHSV,tex,satDitherAmnt,satDitherSdv,satDitherScurve); colorHSV= rgb2hsv(c0.rgb);
}

if (valDither==1){
c0.rgb =v_dither(colorHSV,tex,valDitherAmnt,valDitherSdv,valDitherScurve); colorHSV= rgb2hsv(c0.rgb);
}

if (redDither==1){
c0.r =r_dither(c0.r,tex,redDitherAmnt,redDitherSdv,redDitherScurve);
}

if (greenDither==1){
c0.g =g_dither(c0.g,tex,greenDitherAmnt,greenDitherSdv,greenDitherScurve);
}

if (blueDither==1){
c0.b =b_dither(c0.b,tex,blueDitherAmnt,blueDitherSdv,blueDitherScurve);
}

if (cyanDither==1){
c0.r =c_dither(c0.r,tex,cyanDitherAmnt,cyanDitherSdv,cyanDitherScurve);
}

if (magentaDither==1){
c0.g =m_dither(c0.g,tex,magentaDitherAmnt,magentaDitherSdv,magentaDitherScurve);
}

if (yellowDither==1){
c0.b =y_dither(c0.b,tex,yellowDitherAmnt,yellowDitherSdv,yellowDitherScurve);
}

if (rgbDither==1){
c0.r =r_dither(c0.r,tex,rgbDitherAmnt,rgbDitherSdv,rgbDitherScurve);
c0.g =g_dither(c0.g,tex,rgbDitherAmnt,rgbDitherSdv,rgbDitherScurve);
c0.b =b_dither(c0.b,tex,rgbDitherAmnt,rgbDitherSdv,rgbDitherScurve);
}

if (greyDither==1){
c0.rgb =saturate(c0.rgb +(grey_dither(max(c0.r,max(c0.g,c0.b)),tex,greyDitherAmnt,greyDitherSdv,greyDitherScurve)-(max(c0.r,max(c0.g,c0.b)))));
}

if (greyDebug==1){
float greyDebugPwr=5;

float3 mxrgb=c0.rgb;



if(abs(max(max(c0.r,c0.g),c0.b)-min(min(c0.r,c0.g),c0.b))==0){
mxrgb.rgb=max(max(c0.r,c0.g),c0.b);
}else{
float mmdiff=abs(max(max(c0.r,c0.g),c0.b)-min(min(c0.r,c0.g),c0.b));
if(c0.r==max(max(c0.r,c0.g),c0.b)){
//mxrgb.r+=1;
mxrgb.r=-pow(pow(mmdiff,-1*(mmdiff-1)),greyDebugPwr)+1;
}

if(c0.g==max(max(c0.r,c0.g),c0.b)){
//mxrgb.g+=1;
mxrgb.g=-pow(pow(mmdiff,-1*(mmdiff-1)),greyDebugPwr)+1;
}

if(c0.b==max(max(c0.r,c0.g),c0.b)){
//mxrgb.b+=1;
mxrgb.b=-pow(pow(mmdiff,-1*(mmdiff-1)),greyDebugPwr)+1;
}



}

c0.rgb=mxrgb.rgb;

}
return c0;
} 

float4 main(float2 tex : TEXCOORD0) : COLOR {
float4 c0 = tex2D(s0, tex);

float divLine=0.5;

float divThk=(0.0008*width)*one_over_width;

if (split==1){
if(tex.x*width>=(divLine-divThk)*width && tex.x*width<=(divLine+divThk)*width){
c0.xyz=0;
return c0;

}
if(tex.x*width>(divLine+divThk)*width){

return ditherer(c0,tex);

}
else {

return c0;

}}
else{

return ditherer(c0,tex);

}
return c0;
}