White point adjuster

More
1 year 2 months ago - 3 weeks 3 days ago #1 by crabshank
White point adjuster was created by crabshank
This shader allows you to change the white point in the xyY space of CIE 1931 and thus allows for easy white balancing:






N.B. This white balances to D65.
#include "ReShadeUI.fxh"

uniform int mode < __UNIFORM_COMBO_INT1
    ui_items = "sRGB\0Rec 601 NTSC\0Rec. 601 PAL\0Rec. 709\0Rec.2020\0DCI-P3\0Display P3\0Orginal NTSC\0Rec. 601 D93\0Rec. 709 D93\0DCI-P3 (D60/ACES)\0";
> = 0;

uniform bool Linear <
ui_tooltip = "Take linear RGB as input and output linear RGB";
> = false;

uniform float2 Custom_xy < __UNIFORM_DRAG_FLOAT2
	ui_min = 0.0; ui_step=0.001; ui_max = 1.0;
	ui_tooltip = "N.B. output will be D65 (white point for most colour spaces)";
> =float2(0.312727,0.329023);

uniform bool Two_dimensional_input <> = false;

uniform int Two_dimensional_input_type <__UNIFORM_COMBO_INT1
    ui_items = "Crosshairs on\0Crosshairs off\0Direct point-based\0";
	> = 0;

uniform float Two_dimensional_input_Range < __UNIFORM_SLIDER_FLOAT1
	ui_min = 2.0; ui_max = 0.0;
> = 2.0;


uniform int Debug <__UNIFORM_COMBO_INT1
    ui_items = "Disabled\0Blacken sat <= Debug_thresh\0Saturation change map\0";
    ui_tooltip = "Saturation change map: Sat unchanged => Green; Sat decreased => Cyan to Blue; Sat increased => Magenta to Orange";
	> = 0;


uniform float Debug_thresh < __UNIFORM_DRAG_FLOAT1
	ui_min = 0; ui_max =1;
> = 0.015;

uniform int Decimals < __UNIFORM_SLIDER_INT1
	ui_min = 1; ui_max =4;
> = 3;

#include "ReShade.fxh"
#include "DrawText_mod.fxh"

#define rcptwoFiveFive 1.0/255.0
#define rcpTwoFour 1.0/2.4
#define rcpOFiveFive 1.0/1.055
#define rcpTwelveNineTwo 1.0/12.92
#define recAlpha 1.09929682680944
#define rcpRecAlpha 1.0/1.09929682680944
#define recBeta 0.018053968510807
#define recBetaLin 0.004011993002402
#define rcpFourFive 1.0/4.5
#define rcpTxFourFive 10.0/4.5
#define invTwoTwo 5.0/11.0
#define invTwoSix 5.0/13.0

uniform bool buttondown < source = "mousebutton"; keycode = 0; mode = ""; >;

uniform float2 mousepoint < source = "mousepoint"; >;

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


float3 WPconv(float3 XYZ,float3 from, float3 to){

float3x3 Bradford=float3x3(0.8951,0.2664,-0.1614,
-0.7502,1.7135,0.0367,
0.0389,-0.0685,1.0296);

float3x3 BradfordInv=float3x3(0.9869929,-0.1470543,0.1599627,
0.4323053,0.5183603,0.0492912,
-0.0085287,0.0400428,0.9684867);


float3 BradFrom= mul(Bradford,from);
float3 BradTo= mul(Bradford,to);

float3x3 CR=float3x3(BradTo.x/BradFrom.x,0,0,
0,BradTo.y/BradFrom.y,0,
0,0,BradTo.z/BradFrom.z);

float3x3 convBrad= mul(mul(BradfordInv,CR),Bradford);

float3 outp=mul(convBrad,XYZ);
return outp;


}

float3 WPconv2Grey(float3 from, float3 to){

float3x3 Bradford=float3x3(0.8951,0.2664,-0.1614,
-0.7502,1.7135,0.0367,
0.0389,-0.0685,1.0296);

float3x3 BradfordInv=float3x3(0.9869929,-0.1470543,0.1599627,
0.4323053,0.5183603,0.0492912,
-0.0085287,0.0400428,0.9684867);

float3 BradFrom= mul(Bradford,from);
float3 BradTo= mul(Bradford,to);

float3x3 CR=float3x3(BradTo.x/BradFrom.x,0,0,
0,BradTo.y/BradFrom.y,0,
0,0,BradTo.z/BradFrom.z);

float3x3 convBrad= mul(mul(BradfordInv,CR),Bradford);

float3 outp=mul(convBrad,float3(0.95047,1,1.08883));

return outp;

}

float3 XYZ2rgb(float3 XYZ, int mode, int lin){

float3 v1=float3(0,0,0);
float3 v2=float3(0,0,0);
float3 v3=float3(0,0,0);

[branch]if (mode==1){ //Rec 601 NTSC
    v1.x=3.505396;
    v1.y=-1.7394894;
    v1.z=-0.543964;
    v2.x=-1.0690722;
    v2.y=1.9778245;
    v2.z=0.0351722;
    v3.x=0.05632;
    v3.y=-0.1970226;
    v3.z=1.0502026;
}else if (mode==2){ //Rec 601 PAL
    v1.x=3.0628971;
    v1.y=-1.3931791;
    v1.z=-0.4757517;
    v2.x=-0.969266;
    v2.y=1.8760108;
    v2.z=0.041556;
    v3.x=0.0678775;
    v3.y=-0.2288548;
    v3.z=1.069349;
}else if(mode==5){ //DCI-P3
    v1.x=2.72539403049173;
    v1.y=-1.01800300622718;
    v1.z=-0.440163195190036;
    v2.x=-0.795168025808764;
    v2.y=1.68973205484362;
    v2.z=0.022647190608478;
    v3.x=0.0412418913957;
    v3.y=-0.087639019215862;
    v3.z=1.10092937864632;
}else if(mode==6){
    v1.x=2.49318075532897;
    v1.y=-0.93126552549714;
    v1.z=-0.402659723758882;
    v2.x=-0.829503115821079;
    v2.y=1.76269412111979;
    v2.z=0.02362508874174;
    v3.x=0.035853625780072;
    v3.y=-0.076188954782652;
    v3.z=0.957092621518022;
}else if (mode==4){ //Rec 2020
    v1.x=1.71651066976197;
    v1.y=-0.355641669986716;
    v1.z=-0.253345541821907;
    v2.x=-0.666693001182624;
    v2.y=1.61650220834691;
    v2.z=0.015768750389995;
    v3.x=0.017643638767459;
    v3.y=-0.042779781669045;
    v3.z=0.942305072720018;
}else if (mode==7){ //Original NTSC
    v1.x=1.9096754;
    v1.y=-0.5323648;
    v1.z=-0.2881607;
    v2.x=-0.9849649;
    v2.y=1.9997772;
    v2.z=-0.0283168;
    v3.x=0.0582407;
    v3.y=-0.1182463;
    v3.z=0.896554;
}else if (mode==8){ //Rec 601 D93
    v1.x=4.2126707;
    v1.y=-2.0904617;
    v1.z=-0.6537183;
    v2.x=-1.0597177;
    v2.y=1.9605182;
    v2.z=0.0348645;
    v3.x=0.0420119;
    v3.y=-0.1469691;
    v3.z=0.7833991;
}else if (mode==9){ //Rec 709 D93
    v1.x=3.8294307;
    v1.y=-1.8165248;
    v1.z=-0.5891432;
    v2.x=-0.9585901;
    v2.y=1.8553477;
    v2.z=0.0410983;
    v3.x=0.0414369;
    v3.y=-0.1519354;
    v3.z=0.7873016;
}else if (mode==10){ //DCI-P3 D60/ACES
    v1.x=2.40274141422225;
    v1.y=-0.897484163940685;
    v1.z=-0.388053369996071;
    v2.x=-0.832579648740884;
    v2.y=1.76923175357438;
    v2.z=0.023712711514772;
    v3.x=0.038823381466857;
    v3.y=-0.082499685617071;
    v3.z=1.03636859971248;
}else{ //sRGB - Rec 709
    v1.x=3.2404542;
    v1.y=-1.5371385;
    v1.z=-0.4985314;
    v2.x=-0.969266;
    v2.y=1.8760108;
    v2.z=0.041556;
    v3.x=0.0556434;
    v3.y=-0.2040259;
    v3.z=1.0572252;
}		
		float3 RGB=float3(dot(v1, XYZ),dot(v2, XYZ),dot(v3, XYZ));

[branch]if(lin==0){
if ((mode==0)||(mode==6)){ //sRGB transfer
      RGB=(RGB > 0.0404482362771082 )?pow(abs((RGB+0.055)*rcpOFiveFive),2.4):RGB*rcpTwelveNineTwo;
}else if ((mode==5)||(mode==10)){ //DCI-P3
      RGB=pow(RGB,2.6);
}else if (mode==7){ //Original NTSC - Source: 47 CFR, Section 73.682 - TV transmission standards
      RGB=pow(RGB,2.2);
}else{ //Rec transfer
      RGB=(RGB < recBetaLin )?rcpFourFive*RGB:pow(-1*(rcpRecAlpha*(1-recAlpha-RGB)),rcpTxFourFive);
}
}

return RGB;

}

float3 rgb2XYZ(float3 rgb,int mode, int lin){

	  float3 rgbLin=rgb;
	  
[branch]if(lin==0){
if ((mode==0)||(mode==6)){ //sRGB transfer
    rgbLin=(rgb> 0.00313066844250063)?1.055 * pow(rgb,rcpTwoFour) - 0.055:12.92 *rgb;
}else if ((mode==5)||(mode==10)){ //DCI-P3
    rgbLin=pow(rgb,invTwoSix);
}else if (mode==7){ //Original NTSC
    rgbLin=pow(rgb,invTwoTwo);
}else{ //Rec transfer
    rgbLin=(rgb< recBeta)?4.5*rgb:recAlpha*pow(rgb,0.45)-(recAlpha-1);
}
}

float3 v1;
float3 v2;
float3 v3;

[branch]if (mode==1){ //Rec 601 NTSC
    v1.x=0.3935891;
    v1.y=0.3652497;
    v1.z=0.1916313;
    v2.x=0.2124132;
    v2.y=0.7010437;
    v2.z=0.0865432;
    v3.x=0.0187423;
    v3.y=0.1119313;
    v3.z=0.9581563;
}else if (mode==2){ //Rec 601 PAL
    v1.x=0.430619;
    v1.y=0.3415419;
    v1.z=0.1783091;
    v2.x=0.2220379;
    v2.y=0.7066384;
    v2.z=0.0713236;
    v3.x=0.0201853;
    v3.y=0.1295504;
    v3.z=0.9390944;
}else if(mode==5){ //DCI-P3
    v1.x=0.445169815564552;
    v1.y=0.277134409206778;
    v1.z=0.172282669815565;
    v2.x=0.209491677912731;
    v2.y=0.721595254161044;
    v2.z=0.068913067926226;
    v3.x=0;
    v3.y=0.047060560053981;
    v3.z=0.907355394361973;
}else if(mode==6){
    v1.x=0.48663265;
    v1.y=0.2656631625;
    v1.z=0.1981741875;
    v2.x=0.2290036;
    v2.y=0.691726725;
    v2.z=0.079269675;
    v3.x=0;
    v3.y=0.0451126125;
    v3.z=1.0437173875;
}else if (mode==4){ //Rec 2020
    v1.x=0.637010191411101;
    v1.y=0.144615027396969;
    v1.z=0.16884478119193;
    v2.x=0.26272171736164;
    v2.y=0.677989275502262;
    v2.z=0.059289007136098;
    v3.x=0;
    v3.y=0.028072328847647;
    v3.z=1.06075767115235;
}else if (mode==7){ //Original NTSC
    v1.x=0.6069928;
    v1.y=0.1734485;
    v1.z=0.2005713;
    v2.x=0.2989666;
    v2.y=0.5864212;
    v2.z=0.1146122;
    v3.x=0;
    v3.y=0.0660756;
    v3.z=1.1174687;
}else if (mode==8){ //Rec 601 D93
    v1.x=0.3275085;
    v1.y=0.3684739;
    v1.z=0.2568954;
    v2.x=0.1767506;
    v2.y=0.7072321;
    v2.z=0.1160173;
    v3.x=0.0155956;
    v3.y=0.1129194;
    v3.z=1.2844772;
}else if (mode==9){ //Rec 709 D93
    v1.x=0.3490195;
    v1.y=0.3615584;
    v1.z=0.2422998;
    v2.x=0.1799632;
    v2.y=0.7231169;
    v2.z=0.0969199;
    v3.x=0.0163603;
    v3.y=0.1205195;
    v3.z=1.2761125;
}else if (mode==10){ //DCI-P3 D60/ACES
    v1.x=0.504949534191744;
    v1.y=0.264681488895262;
    v1.z=0.18301505148284;
    v2.x=0.23762331020788;
    v2.y=0.689170669198985;
    v2.z=0.073206020593136;
    v3.x=0;
    v3.y=0.04494591320863;
    v3.z=0.963879271142956;
}else{ //sRGB - Rec 709
    v1.x=0.4124564;
    v1.y=0.3575761;
    v1.z=0.1804375;
    v2.x=0.2126729;
    v2.y=0.7151522;
    v2.z=0.072175;
    v3.x=0.0193339;
    v3.y=0.119192;
    v3.z=0.9503041;
}

	
	return float3(dot(v1, rgbLin),dot(v2, rgbLin), dot(v3, rgbLin));


}

float3 rgb2XYZ_grey(float3 rgb,int mode, int lin){

float3 rgbLin=rgb;
	  
[branch]if(lin==0){
if ((mode==0)||(mode==6)){ //sRGB transfer
    rgbLin=(rgb> 0.00313066844250063)?1.055 * pow(rgb,rcpTwoFour) - 0.055:12.92 *rgb;
}else if ((mode==5)||(mode==10)){ //DCI-P3
    rgbLin=pow(rgb,invTwoSix);
}else if (mode==7){ //Original NTSC
    rgbLin=pow(rgb,invTwoTwo);
}else{ //Rec transfer
    rgbLin=(rgb< recBeta)?4.5*rgb:recAlpha*pow(rgb,0.45)-(recAlpha-1);
}
}

float3 v1;
float3 v2;
float3 v3;

[branch]if (mode==1){ //Rec 601 NTSC
    v1.x=0.3935891;
    v1.y=0.3652497;
    v1.z=0.1916313;
    v2.x=0.2124132;
    v2.y=0.7010437;
    v2.z=0.0865432;
    v3.x=0.0187423;
    v3.y=0.1119313;
    v3.z=0.9581563;
}else if (mode==2){ //Rec 601 PAL
    v1.x=0.430619;
    v1.y=0.3415419;
    v1.z=0.1783091;
    v2.x=0.2220379;
    v2.y=0.7066384;
    v2.z=0.0713236;
    v3.x=0.0201853;
    v3.y=0.1295504;
    v3.z=0.9390944;
}else if(mode==5){ //DCI-P3
    v1.x=0.445169815564552;
    v1.y=0.277134409206778;
    v1.z=0.172282669815565;
    v2.x=0.209491677912731;
    v2.y=0.721595254161044;
    v2.z=0.068913067926226;
    v3.x=0;
    v3.y=0.047060560053981;
    v3.z=0.907355394361973;
}else if(mode==6){
    v1.x=0.48663265;
    v1.y=0.2656631625;
    v1.z=0.1981741875;
    v2.x=0.2290036;
    v2.y=0.691726725;
    v2.z=0.079269675;
    v3.x=0;
    v3.y=0.0451126125;
    v3.z=1.0437173875;
}else if (mode==4){ //Rec 2020
    v1.x=0.637010191411101;
    v1.y=0.144615027396969;
    v1.z=0.16884478119193;
    v2.x=0.26272171736164;
    v2.y=0.677989275502262;
    v2.z=0.059289007136098;
    v3.x=0;
    v3.y=0.028072328847647;
    v3.z=1.06075767115235;
}else if (mode==7){ //Original NTSC
    v1.x=0.6069928;
    v1.y=0.1734485;
    v1.z=0.2005713;
    v2.x=0.2989666;
    v2.y=0.5864212;
    v2.z=0.1146122;
    v3.x=0;
    v3.y=0.0660756;
    v3.z=1.1174687;
}else if (mode==8){ //Rec 601 D93
    v1.x=0.3275085;
    v1.y=0.3684739;
    v1.z=0.2568954;
    v2.x=0.1767506;
    v2.y=0.7072321;
    v2.z=0.1160173;
    v3.x=0.0155956;
    v3.y=0.1129194;
    v3.z=1.2844772;
}else if (mode==9){ //Rec 709 D93
    v1.x=0.3490195;
    v1.y=0.3615584;
    v1.z=0.2422998;
    v2.x=0.1799632;
    v2.y=0.7231169;
    v2.z=0.0969199;
    v3.x=0.0163603;
    v3.y=0.1205195;
    v3.z=1.2761125;
}else if (mode==10){ //DCI-P3 D60/ACES
    v1.x=0.504949534191744;
    v1.y=0.264681488895262;
    v1.z=0.18301505148284;
    v2.x=0.23762331020788;
    v2.y=0.689170669198985;
    v2.z=0.073206020593136;
    v3.x=0;
    v3.y=0.04494591320863;
    v3.z=0.963879271142956;
}else{ //sRGB - Rec 709
    v1.x=0.4124564;
    v1.y=0.3575761;
    v1.z=0.1804375;
    v2.x=0.2126729;
    v2.y=0.7151522;
    v2.z=0.072175;
    v3.x=0.0193339;
    v3.y=0.119192;
    v3.z=0.9503041;
}


    float rgbNewTot=rgbLin.x+rgbLin.y+rgbLin.z;
    float rgbNewAvg=rgbNewTot/3;
    float3 rgbNew=rgbNewAvg;

	return float3(dot(v1, rgbNew),dot(v2, rgbNew), dot(v3, rgbNew));

}

//Source: https://stackoverflow.com/a/45263428; http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.htm; https://en.wikipedia.org/wiki/Rec._2020#Transfer_characteristics

float3 WPChangeRGB(float3 color, float3 from, float3 to, int mode, int lin){

float3 XYZed=rgb2XYZ(color.rgb,mode, lin);
return XYZ2rgb(WPconv(XYZed,from,to),mode, lin);

}

float3 xy2XYZ(float2 xyCoord){
return float3((1/xyCoord.y)*xyCoord.x,1,(1/xyCoord.y)*(1-xyCoord.x-xyCoord.y));
}

float3 XYZ2xyY(float3 XYZ){
	float XYZtot=XYZ.x+XYZ.y+XYZ.z;
	
	float x=XYZ.x/XYZtot;
	float y=XYZ.y/XYZtot;
	return float3(x,y,XYZ.y);
}


float4 whitePoint(float4 color, float2 CustomxyIn, int lin){

float4 c0=color;

float2 D65xy=float2(0.312727,0.329023);

float3 D65XYZ=xy2XYZ(D65xy);
float3 CustomXYZ=xy2XYZ(CustomxyIn);

float3 from = D65XYZ; 
float3 to = CustomXYZ;

color.rgb= WPChangeRGB(color.rgb, from, to,mode,lin);

return color;
}

float4 WhitePointPass2D(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target
{

float4 c0=tex2D(ReShade::BackBuffer, texcoord);

int linr=(Linear==true)?1:0;

float2 Customxy=Custom_xy;

float xCoord_Pos;
float yCoord_Pos;

[branch]if(Two_dimensional_input==true){
	
float x_Range=(BUFFER_WIDTH>=BUFFER_HEIGHT)?Two_dimensional_input_Range*(BUFFER_RCP_HEIGHT/BUFFER_RCP_WIDTH):Two_dimensional_input_Range;

float y_Range=(BUFFER_WIDTH>=BUFFER_HEIGHT)?Two_dimensional_input_Range:Two_dimensional_input_Range*(BUFFER_RCP_WIDTH/BUFFER_RCP_HEIGHT);

Customxy.x= (buttondown==0)?  mousepoint.x*ReShade::PixelSize.x*((Customxy.x+0.5*x_Range)-(Customxy.x-0.5*x_Range))+(Customxy.x-0.5*x_Range):Customxy.x;

xCoord_Pos=(buttondown==1)?(Customxy.x-(Customxy.x-0.5*x_Range))/((Customxy.x+0.5*x_Range)-(Customxy.x-0.5*x_Range)):mousepoint.x*ReShade::PixelSize.x;

Customxy.y= (buttondown==0)?mousepoint.y*ReShade::PixelSize.y*((Customxy.y+0.5*y_Range)-(Customxy.y-0.5*y_Range))+(Customxy.y-0.5*y_Range):Customxy.y;

yCoord_Pos=(buttondown==1)?(Customxy.y-(Customxy.y-0.5*y_Range))/((Customxy.y+0.5*y_Range)-(Customxy.y-0.5*y_Range)):mousepoint.y*ReShade::PixelSize.y;

float4 p0=tex2D(ReShade::BackBuffer, mousepoint*ReShade::PixelSize);

float3 WPgf= rgb2XYZ(float3(p0.rgb*rcptwoFiveFive),mode,linr);
float3 WPgt= rgb2XYZ_grey(float3(p0.rgb*rcptwoFiveFive),mode,linr);



		Customxy.xy=(buttondown==0)?XYZ2xyY(WPconv2Grey(WPgf,WPgt)).xy:Customxy;

}


float4 c1=whitePoint(c0,Customxy,linr);

[branch]if(Debug==1){
float max_rgb=max(max(c1.r,c1.g),c1.b);
float min_rgb=min(min(c1.r,c1.g),c1.b);
float sat=(max_rgb==0)?0:(max_rgb-min_rgb)/max_rgb;

c1.rgb=(sat<=Debug_thresh)?0:c1.rgb;
}else if(Debug==2){
float max_rgb=max(max(c1.r,c1.g),c1.b);
float min_rgb=min(min(c1.r,c1.g),c1.b);
float sat=(max_rgb==0)?0:(max_rgb-min_rgb)/max_rgb;

float max_rgb_og=max(max(c0.r,c0.g),c0.b);
float min_rgb_og=min(min(c0.r,c0.g),c0.b);
float sat_og=(max_rgb_og==0)?0:(max_rgb_og-min_rgb_og)/max_rgb_og;

float hue_dbg=120;
    
	hue_dbg=(sat<sat_og)?lerp(157.5,240,(sat_og-sat)/sat_og):hue_dbg; 
    hue_dbg=(sat>sat_og)?lerp(307.5,367.5,(sat-sat_og)/(1-sat_og)):hue_dbg;
    hue_dbg=(hue_dbg==360)?0:hue_dbg;
    hue_dbg=(hue_dbg>360)?hue_dbg-360:hue_dbg;
	
	c1.rgb=hsv2rgb(float3(hue_dbg/360.0,1,1-Debug_thresh));

}

float4 c2;
float4 c3;

[branch]if(Two_dimensional_input==true){
	
c2.rgb =(abs(texcoord.x-xCoord_Pos)<BUFFER_RCP_WIDTH || abs(texcoord.y-yCoord_Pos)<BUFFER_RCP_HEIGHT)?float3(0.369,0.745,0):c1.rgb;

c3.rgb =(abs(texcoord.x-xCoord_Pos)<3*BUFFER_RCP_WIDTH && abs(texcoord.y-yCoord_Pos)<3*BUFFER_RCP_HEIGHT)?float3(0.498,1,0):c1.rgb;

[branch]if(Two_dimensional_input_type==0){
	c1.rgb=c2.rgb;
}else if(Two_dimensional_input_type==1){
		c1.rgb=c3.rgb;
}

float4 res =float4(c1.rgb,0);

float textSize=25;

DrawText_Digit(   DrawText_Shift(DrawText_Shift(float2(0.5*BUFFER_WIDTH,0), int2(-14, 0), textSize, 1), int2(8, 0), textSize, 1) , 
textSize, 1, texcoord,  Decimals, Customxy.x, res,1);

DrawText_Digit(   DrawText_Shift(DrawText_Shift(float2(0.5*BUFFER_WIDTH,0), int2(-5, 0), textSize, 1), int2(8, 0), textSize, 1) , 
textSize, 1, texcoord,  Decimals,  Customxy.y, res,1);

c1.rgb=res.rgb;
}

return c1;

}

technique White_Point_2D
{
	pass
	{
		VertexShader = PostProcessVS;
		PixelShader = WhitePointPass2D;
	}
}

Requires a modded DrawText header file as well, for the new 2D input (call it "DrawText_mod.fxh"!):
//Original by kingeric1992, modded by crabshank 08/10/2019

#ifndef _DRAWTEXT_H_
#define _DRAWTEXT_H_

#define _DRAWTEXT_GRID_X 14.0
#define _DRAWTEXT_GRID_Y 7.0

///////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                   //
//  Available functions:                                                                             //
//      DrawText_String( offset, text size, xy ratio, input coord, string array, array size, output) //
//          float2 offset       = top left corner of string, screen hight pixel unit.                //
//          float  text size    = text size, screen hight pixel unit.                                //
//          float  xy ratio     = xy ratio of text.                                                  //
//          float2 input coord  = current texture coord.                                             //
//          int    string array = string data in float2 array format, ex: "Demo Text"                //
//              int String0[9] = { __D, __e, __m, __o, __Space, __T, __e, __x, __t};                 //
//          int    string size  = size of the string array.                                          //
//          float  output       = output.                                                            //
//                                                                                                   //
//      DrawText_Digit( offset, text size, xy ratio, input coord, precision after dot, data, output) //
//          float2 offset       = same as DrawText_String.                                           //
//          float  text size    = same as DrawText_String.                                           //
//          float  xy ratio     = same as DrawText_String.                                           //
//          float2 input coord  = same as DrawText_String.                                           //
//          int    precision    = digits after dot.                                                  //
//          float  data         = input float.                                                       //
//          float  output       = output.                                                            //
//                                                                                                   //
//      float2 DrawText_Shift(shift, text size, xy ratio)                                            //
//          float2 shift        = shift line(y) and column.                                          //
//          float text size     = same as DrawText_String.                                           //
//          float xy ratio      = same as DrawText_String.                                           //
//                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////


//Sample Usage

/*
float4 main_fragment( float4 position : POSITION,
                      float2 txcoord  : TEXCOORD) : COLOR {
    float res = 0.0;

    int line0[9]  = { __D, __e, __m, __o, __Space, __T, __e, __x, __t };   //Demo Text
    int line1[15] = { __b, __y, __Space, __k, __i, __n, __g, __e, __r, __i, __c, __1, __9, __9, __2 }; //by kingeric1992
    int line2[6]  = { __S, __i, __z, __e, __Colon, __Space }; // Size: %d.

    DrawText_String(float2(100.0 , 100.0), 32, 1, txcoord,  line0, 9, res);
    DrawText_String(float2(100.0 , 134.0), textSize, 1, txcoord,  line1, 15, res);
    DrawText_String(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), 18, 1, txcoord,  line2, 6, res);
    DrawText_Digit(DrawText_Shift(DrawText_Shift(float2(100.0 , 134.0), int2(0, 1), textSize, 1), int2(8, 0), 18, 1),
                    18, 1, txcoord,  0, textSize, res);

    return res;
}

*/

//Text display
//Character indexing
#define __Space       0 //  (space)
#define __Exclam      1 //  !
#define __Quote       2 //  "
#define __Pound       3 //  #
#define __Dollar      4 //  $
#define __Percent     5 //  %
#define __And         6 //  &
#define __sQuote      7 //  '
#define __rBrac_O     8 //  (
#define __rBrac_C     9 //  )
#define __Asterisk   10 //  *
#define __Plus       11 //  +
#define __Comma      12 //  ,
#define __Minus      13 //  -

#define __Dot        14 //  .
#define __Slash      15 //  /
#define __0          16 //  0
#define __1          17 //  1
#define __2          18 //  2
#define __3          19 //  3
#define __4          20 //  4
#define __5          21 //  5
#define __6          22 //  6
#define __7          23 //  7
#define __8          24 //  8
#define __9          25 //  9
#define __Colon      26 //  :
#define __sColon     27 //  ;

#define __Less       28 //  <
#define __Equals     29 //  =
#define __Greater    30 //  >
#define __Question   31 //  ?
#define __at         32 //  @
#define __A          33 //  A
#define __B          34 //  B
#define __C          35 //  C
#define __D          36 //  D
#define __E          37 //  E
#define __F          38 //  F
#define __G          39 //  G
#define __H          40 //  H
#define __I          41 //  I

#define __J          42 //  J
#define __K          43 //  K
#define __L          44 //  L
#define __M          45 //  M
#define __N          46 //  N
#define __O          47 //  O
#define __P          48 //  P
#define __Q          49 //  Q
#define __R          50 //  R
#define __S          51 //  S
#define __T          52 //  T
#define __U          53 //  U
#define __V          54 //  V
#define __W          55 //  W

#define __X          56 //  X
#define __Y          57 //  Y
#define __Z          58 //  Z
#define __sBrac_O    59 //  [
#define __Backslash  60 //  \..
#define __sBrac_C    61 //  ]
#define __Caret      62 //  ^
#define __Underscore 63 //  _
#define __Punc       64 //  `
#define __a          65 //  a
#define __b          66 //  b
#define __c          67 //  c
#define __d          68 //  d
#define __e          69 //  e

#define __f          70 //  f
#define __g          71 //  g
#define __h          72 //  h
#define __i          73 //  i
#define __j          74 //  j
#define __k          75 //  k
#define __l          76 //  l
#define __m          77 //  m
#define __n          78 //  n
#define __o          79 //  o
#define __p          80 //  p
#define __q          81 //  q
#define __r          82 //  r
#define __s          83 //  s

#define __t          84 //  t
#define __u          85 //  u
#define __v          86 //  v
#define __w          87 //  w
#define __x          88 //  x
#define __y          89 //  y
#define __z          90 //  z
#define __cBrac_O    91 //  {
#define __vBar       92 //  |
#define __cBrac_C    93 //  }
#define __Tilde      94 //  ~
#define __tridot     95 // (...)
#define __empty0     96 // (null)
#define __empty1     97 // (null)
//Character indexing ends

texture Texttex < source = "FontAtlas.png"; > {
    Width  = 512;
    Height = 512;
};

sampler samplerText {
    Texture = Texttex;
};

//accomodate for undef array size.
#define DrawText_String(  pos, size, ratio, tex, array, arrSize, output ) \
    {   float  text = 0.0; \
        float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size; \
        uv.y      = saturate(uv.y); \
        uv.x     *= ratio * 2.0; \
        float  id = array[int(trunc(uv.x))]; \
        if(uv.x  <= arrSize && uv.x >= 0.0) \
            text  = tex2D(samplerText, (frac(uv) + float2( id % 14.0, trunc(id / 14.0))) \
            / float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y) ).x; \
        output += text;  }

float2 DrawText_Shift( float2 pos, int2 shift, float size, float ratio ) {
    return pos + size * shift * float2(0.5, 1.0) / ratio;
}


	float mulTenIntPow(float number,float power){
float sign=(power>=0)?1:-1;
int pwr=uint(round(abs(power)));
[flatten]if(pwr>1){
for(int i=0; i<pwr;i++){
number=(sign==1)?number*10:number/10;
}
}else{
number=(sign==1)?number*10:number/10;
}

return number;
}

float rounder (float places,float number){
float sign=(number>=0)?1:-1;
int integer=int(round(mulTenIntPow(abs(number),places)));

return sign*(mulTenIntPow(float(round(integer)),-places));
}



void DrawText_Digit( float2 pos, float size, float ratio, float2 tex, int digit, float data, inout float4 res,float textGrey) {
    int digits[13] = {
        __0, __1, __2, __3, __4, __5, __6, __7, __8, __9, __Minus, __Space, __Dot
    };

    float2 uv = (tex * float2(BUFFER_WIDTH, BUFFER_HEIGHT) - pos) / size;
    uv.y      = saturate(uv.y);
    uv.x     *= ratio * 2.0;

data=rounder(digit,data);
    float  t  = abs(data);
    int numDigits = max(ceil(log2(t)/3.32192809),1);

    //early exit:
   if(uv.x <-numDigits-1 || uv.x > digit+1) return;

int index = 0;

[flatten]if(int(uv.x)==0){
index=round(trunc(frac(mulTenIntPow(t,-1))*10));
}else if(int(uv.x)<=-1){
index=round(trunc(frac(trunc(mulTenIntPow(t,uv.x))/10)*10));
}else if(int(uv.x)>=1){
index=round(frac(trunc(mulTenIntPow(t,int(uv.x)))/10)*10);
}

index=(int(uv.x)==0&&int(ceil(uv.x))==1)?12:index;

[flatten]if(int(uv.x)==-numDigits){
if(data>=0){
index=11;
}else{
index=10;
}
}

index=digits[int(index)];

    res  +=(textGrey*2-1)*tex2D(samplerText, (frac(uv) + float2( index % 14.0, trunc(index / 14.0))) /
               float2( _DRAWTEXT_GRID_X, _DRAWTEXT_GRID_Y)).x;
}

#endif

So the new aforementioned 2D input works when you toggle the 2D input tickbox and you move the mouse to change the current xy values which are printed at the top of the frame. If you click the left mouse button, it will show the output at the xy point specified in the UI and its screen position.

So, move the mouse to find your desired xy co-ordinates and then set the drags in the UI accordingly.

UPDATE: I've just added a new 2D input that lets you put your mouse over a pixel and it will give you the xy co-ordinates necessary to turn that pixel grey.

I've added the option to switch betweeen crosshairs and just a square for the 2D input display. I've also updated the modded DrawText header file.

I've made a new debug and adjustable range (on the screen) for the 2D input. The debug is based on GIMP's max RGB, It's very senstive and still goes close to black when it goes closer to grey.



N.B, I also have a hlsl shader for use with Avisynth video in my Github here .

No debug version here .
Last edit: 3 weeks 3 days ago by crabshank. Reason: Added new debug mode.
The following user(s) said Thank You: MaxG3D, jas01, andrew, Marty, Raughie

Please Log in or Create an account to join the conversation.

More
1 year 1 month ago #2 by crabshank
Replied by crabshank on topic White point adjuster
I am going to be rewriting all my code to optimise it, this is the first shader for which I have done that and I hope it's better. This code also has new elements in the conversion matrices that should be more accurate.

Please Log in or Create an account to join the conversation.

More
1 year 3 weeks ago - 1 year 3 weeks ago #3 by crabshank
Replied by crabshank on topic White point adjuster
UPDATE:
I have added debug amplification (exaggerates the differences between values close to grey) to non-RGB debug mode as well.
Last edit: 1 year 3 weeks ago by crabshank.
The following user(s) said Thank You: jas01

Please Log in or Create an account to join the conversation.

More
1 year 3 weeks ago - 1 year 3 weeks ago #4 by Marty McFly
Replied by Marty McFly on topic White point adjuster
For some reason I thought this bar on the left side was some white scale UI you draw with the shader and was like "wait wtf, you shittin me" :P



Much needed effect, a lot of games impose stupid simple color filters and getting rid of them is annoying.
Btw, for your consideration:

XYZ.x = 0.4124564*rgbNew.r + 0.3575761*rgbNew.g + 0.1804375*rgbNew.b;

and

XYZ.x = dot(float3(0.4124564,0.3575761, 0.1804375), rgbNew.rgb)

are same and second one is much faster and iirc also how the matrix muls are implemented. If not, consider converting to dot products as well to speed it up. Not that it matters much for this lightweight filter, but maybe good to know.
Last edit: 1 year 3 weeks ago by Marty McFly.
The following user(s) said Thank You: crabshank

Please Log in or Create an account to join the conversation.

More
1 year 3 weeks ago - 1 year 3 weeks ago #5 by crabshank
Replied by crabshank on topic White point adjuster
Updated code ^.

Thanks for that @Marty Mcfly, I checked all my other code for such dot products but I couldn't find any. I decided to keep the muls for readibility and compactness, rather than line after line of dot().

All I need now is a 2D drag UI for the xy points *fingers crossed*.
Last edit: 1 year 3 weeks ago by crabshank.

Please Log in or Create an account to join the conversation.

More
1 year 1 week ago - 1 year 1 week ago #6 by crabshank
Replied by crabshank on topic White point adjuster
UPDATE: Added 2D input.

Thanks to BlueSkyDefender and kingeric1992 on Discord for their help.
Last edit: 1 year 1 week ago by crabshank.
The following user(s) said Thank You: jas01

Please Log in or Create an account to join the conversation.

More
1 year 1 day ago #7 by crabshank
Replied by crabshank on topic White point adjuster
UPDATE: Option for a square instead of crosshairs for the 2D input added, and also I've changed my modded DrawText header file (I've also done the same for Grey Gamma and Line Thinning).

Please Log in or Create an account to join the conversation.

More
11 months 3 weeks ago #8 by crabshank
Replied by crabshank on topic White point adjuster
UPDATE: I've just added a new 2D input that lets you put your mouse over a pixel and it will give you the xy co-ordinates necessary to turn that pixel grey, for easier white balancing.

I've also removed a little bit of bloat from the code.
The following user(s) said Thank You: jas01

Please Log in or Create an account to join the conversation.

More
11 months 3 weeks ago #9 by crabshank
Replied by crabshank on topic White point adjuster
URGENT UPDATE: Fixed the issues that were giving inaccurate results for the direct point-based input.

Please Log in or Create an account to join the conversation.

More
9 months 1 day ago #10 by crabshank
Replied by crabshank on topic White point adjuster
Added version without debugging, for more speed.

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #11 by crabshank
Replied by crabshank on topic White point adjuster
UPDATE: Removed bloat.

Please Log in or Create an account to join the conversation.