Welcome, Guest.
Username: Password: Remember me

TOPIC: White point adjuster

White point adjuster 4 weeks 6 hours ago #1

This shader allows you to change the white point in the xyY space of CIE 1931 and thus allows for easy white balancing:



(NB. with either debug setting get your grey point to go black (0,0,0) to set a white balance; I eyeballed this one and right is mine, so IDK if it's exact.)




#include "ReShadeUI.fxh"


uniform float2 Customxy < __UNIFORM_DRAG_FLOAT2
	ui_min = 0.0; ui_step=0.000001; ui_max = 1.0;
> = float2(0.312727,0.329023);

uniform bool Split <> = false;

uniform bool Flip_split <> = false;

uniform bool Debug <> = false;

uniform float Split_position < __UNIFORM_SLIDER_FLOAT1
	ui_min = 0; ui_max =1;
	ui_tooltip = "0 is on the far left, 1 on the far right.";
> = 0.5;

uniform bool RGBdebug <> = true;

uniform float RGBdebugAmplification < __UNIFORM_DRAG_FLOAT1
	ui_min = 0.0000001; ui_max =2;
	ui_tooltip = "A lower value exaggerates small differences more";
> = 0.5;


#include "ReShade.fxh"

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 rgb2xyY(float3 rgb){

    float3 rgbNew=float3(rgb.r,rgb.g,rgb.b); 

	float3 XYZ;

	rgbNew=(rgbNew > 0.0404482362771082)?pow(abs((rgbNew+0.055)/1.055),2.4):rgbNew/12.92;

    XYZ.x =  0.4124564*rgbNew.r + 0.3575761*rgbNew.g + 0.1804375*rgbNew.b;
    XYZ.y =  0.2126729*rgbNew.r + 0.7151522*rgbNew.g + 0.072175*rgbNew.b;
    XYZ.z =  0.0193339*rgbNew.r + 0.119192*rgbNew.g + 0.9503041*rgbNew.b;

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

}

//Source: https://stackoverflow.com/a/45263428; http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

float3 xyY2XYZ(float3 xyY){
	float X=(xyY.z/xyY.y)*xyY.x;
	float Z=(xyY.z/xyY.y)*(1-xyY.x-xyY.y);
	
	return float3(X,xyY.z,Z);
}

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);
}


float3 xyY2rgb(float3 xyY){
float Y=xyY.z;
float X=(Y/xyY.y)*xyY.x;
float Z=(Y/xyY.y)*(1-xyY.x-xyY.y);

float3 RGB;

 RGB.r = X *  3.2404542 + Y * -1.5371385 + Z * -0.4985314;
 RGB.g = X * -0.969266 + Y *  1.8760108 + Z *  0.041556;
 RGB.b = X *  0.0556434 + Y * -0.2040259 + Z *  1.0572252;

	RGB=( RGB > 0.00313066844250063 )?1.055 * pow(abs(RGB),1/2.4) - 0.055:12.92 *RGB;

return RGB;

}
//Source: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

float3 WPChangeRGB(float3 color, float3 from, float3 to){

return xyY2rgb(XYZ2xyY(WPconv(xyY2XYZ(rgb2xyY(color.rgb)),from,to)));

}


float3 WPChangexyY(float3 color, float3 from, float3 to){

return XYZ2xyY(WPconv(xyY2XYZ(color.xyz),from,to));

}

float3 WPChangeXYZ(float3 color, float3 from, float3 to){

return WPconv(xyY2XYZ(rgb2xyY(color.xyz)),from,to);

}

float4 whitePoint(float4 color,float on){

float4 c0=color;

float2 D65xy=float2(0.312727,0.329023);

float3 D65XYZ=float3((1/D65xy.y)*D65xy.x,1,(1/D65xy.y)*(1-D65xy.x-D65xy.y));
float3 CustomXYZ=float3((1/Customxy.y)*Customxy.x,1,(1/Customxy.y)*(1-Customxy.x-Customxy.y));

float3 from = D65XYZ; 
float3 to = CustomXYZ;

float2 WPcc=Customxy;	

float rgbExagg=RGBdebugAmplification;

float3 xyY=rgb2xyY(color.rgb);

float3 OGxyY= xyY;
xyY=WPChangexyY(xyY,from, to);

float3 WPxyY= xyY;

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

color=(on==0)?c0:color;

//float distWPline=sqrt(pow(abs(WPxyY.x-WPcc.x),2)+pow(abs(WPxyY.y-WPcc.y),2));
//color.rgb=min(distWPline,1);

float rgbTot=color.r+color.g+color.b;
float rgbAvg=pow(3,-1)*rgbTot;


float distGrey=sqrt(pow(abs(rgbAvg-color.r),2)+pow(abs(rgbAvg-color.g),2)+pow(abs(rgbAvg-color.b),2));

float3 debug;

debug=(RGBdebug==1)?float3(pow(abs(rgbAvg-color.r),rgbExagg),pow(abs(rgbAvg-color.g),rgbExagg),pow(abs(rgbAvg-color.b),rgbExagg)):(pow(abs(distGrey+1),2)-1)*pow(abs(pow(1+0.5*sqrt(3),2)-1),-1);

color.rgb=(Debug!=1)?color.rgb:debug;

return color;
}



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

float4 c0=tex2D(ReShade::BackBuffer, texcoord);
float4 c1=whitePoint(c0,1);
float4 c2=whitePoint(c0,0);


float4 c3=(texcoord.x>=Split_position*Split)?c1:c2;
float4 c4=(texcoord.x<=Split_position*Split)?c1:c2;

float4 c5=(Flip_split*Split==1)?c4:c3;

float divLine = abs(texcoord.x - Split_position) < BUFFER_RCP_WIDTH;
c5 =(Split==0)?c5: c5*(1.0 - divLine); //invert divline

return c5;

}

technique White_Point
{
	pass
	{
		VertexShader = PostProcessVS;
		PixelShader = WhitePointPass;
	}
}

N.B, I also have a hlsl shader for video in my Github here:
Last Edit: 2 days 15 hours ago by crabshank.
The administrator has disabled public write access.
The following user(s) said Thank You: MaxG3D, jas01, andrew, Raughie

White point adjuster 3 days 6 hours ago #2

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.
The administrator has disabled public write access.