Welcome, Guest.
Username: Password: Remember me

TOPIC: Crosshair overlay shader

Crosshair overlay shader 2 months 5 days ago #1

  • 63OR63
  • 63OR63's Avatar
  • Offline
  • Posts: 2
  • Thank you received: 5
Here is the rough code of my crosshair overlay for ReShade 3. It may use an external texture and apply hue/brightness/contrast/saturation adjustment to it. It may be filled with a solid color or radial gradient. It may use an inverted and oversaturated color from the background. It may have stroke. Opacity and position may be changed.
Features which I planned to implement, but haven't find a way to:
- Blurring the stroke
- Averaging the screen to use as a base color for inversion mode.
I'm abandoning the development, but maybe someone will find it interesting enough and put things in order.
uniform float Opacity <
	ui_type = "drag";
	ui_min = 0.0; ui_max = 1.0;
	ui_label = "Opacity";
> = 1.0;

uniform int ModPosX <
	ui_type = "drag";
	ui_min = -10; ui_max = 10;
	ui_label = "X Axis Shift";
> = 0;

uniform int ModPosY <
	ui_type = "drag";
	ui_min = -10; ui_max = 10;
	ui_label = "Y Axis Shift";
> = 0;

uniform bool UseStroke <
	ui_type = "checkbox";
	ui_label = "Stroke";
> = true;

uniform float3 StrokeColor <
	ui_type = "color";
	ui_label = "Stroke Color";
> = float3(0.0, 0.0, 0.0);

uniform float StrokeOpacity <
	ui_type = "drag";
	ui_min = 0.0; ui_max = 1.0;
	ui_label = "Stroke Opacity";
> = 0.3;

uniform int XhairMode <
	ui_type = "combo";
	ui_items = "Texture file\0Solid Color\0Gradient\0Inversion\0";
	ui_label = "Xhair mode";
> = 3;

uniform float Hue <
	ui_type = "drag";
	ui_min = -180.0; ui_max = 180.0;
	ui_label = "[Texture mode] Hue";
> = 0.0;
uniform float Brightness <
	ui_type = "drag";
	ui_min = -1.0; ui_max = 1.0;
	ui_label = "[Texture mode] Brightness";
> = 0.0;
uniform float Contrast <
	ui_type = "drag";
	ui_min = 0.0; ui_max = 1.0;
	ui_label = "[Texture mode] Contrast";
> = 0.0;
uniform float Saturation <
	ui_type = "drag";
	ui_min = 0.0; ui_max = 2.0;
	ui_label = "[Texture mode] Saturation";
> = 1.0;

uniform float3 SolidColor <
	ui_type = "color";
	ui_label = "[Solid color mode] Color";
> = float3(0.0, 1.0, 1.0);

uniform float3 GradientColor1 <
	ui_type = "color";
	ui_label = "[Gradient mode] Color 1";
> = float3(0.0, 1.0, 0.0);

uniform float3 GradientColor2 <
	ui_type = "color";
	ui_label = "[Gradient mode] Color 2";
> = float3(0.0, 1.0, 1.0);

uniform float ModR <
	ui_type = "drag";
	ui_min = 0.01; ui_max = 1.0;
	ui_label = "[Gradient mode] Radius";
> = 0.02;

#include "Reshade.fxh"

texture xhairTex	<  source = "xhair.png"; > {Width = 1920; Height = 1080; Format = RGBA8;};
sampler	xhairSampler 	{ Texture = xhairTex; };

texture xhairMaskTex	<  source = "xhair_mask.png"; > {Width = 1920; Height = 1080; Format = RGBA8;};
sampler	xhairMaskSampler 	{ Texture = xhairMaskTex; };

float3x3 QuaternionToMatrix(float4 quat)
{
	float3 cross = quat.yzx * quat.zxy;
	float3 square= quat.xyz * quat.xyz;
	float3 wimag = quat.w * quat.xyz;

	square = square.xyz + square.yzx;

	float3 diag = 0.5 - square;
	float3 a = (cross + wimag);
	float3 b = (cross - wimag);

	return float3x3(
	2.0 * float3(diag.x, b.z, a.y),
	2.0 * float3(a.z, diag.y, b.x),
	2.0 * float3(b.y, a.x, diag.z));
}

float4 ColorShift(float4 outputColor, float H, float B, float C, float S)
{
	float3 intensity;
	float3 root3 = float3(0.57735, 0.57735, 0.57735);
	float half_angle = 0.5 * radians(H);
	float4 rot_quat = float4((root3 * sin(half_angle)), cos(half_angle));
	float3x3 rot_Matrix = QuaternionToMatrix(rot_quat);
	outputColor.rgb = mul(rot_Matrix, outputColor.rgb);
	outputColor.rgb = (outputColor.rgb - 0.5) *(C + 1.0) + 0.5;
	outputColor.rgb = outputColor.rgb + B;
	float3 lumCoeff = float3(0.2125, 0.7154, 0.0721);
	intensity = float(dot(outputColor.rgb, lumCoeff));
	outputColor.rgb = lerp(intensity, outputColor.rgb, S);

	return outputColor;
}

float4 PS_Xhair(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
	float2 texcoordMod = float2(texcoord.x - ModPosX / ReShade::ScreenSize.x, texcoord.y - ModPosY / ReShade::ScreenSize.y);
	float4 xhair_tex = tex2D(xhairSampler, texcoordMod);
	float4 xhair_mask = tex2D(xhairMaskSampler, texcoordMod).a;
	float4 back = tex2D(ReShade::BackBuffer, texcoord);
	float4 center = tex2D(ReShade::BackBuffer, float2(0.5f + ModPosX / ReShade::ScreenSize.x, 0.5f + ModPosY / ReShade::ScreenSize.y));
	float4 drawBackground;
	float4 drawXhair;
	float4 drawOpacity;

	float4 outXhair;

	if (XhairMode == 0)			// Texture file mode
	{
		xhair_tex = ColorShift(xhair_tex, Hue, Brightness, Contrast, Saturation);

		drawBackground = back;
		drawXhair = xhair_tex;
		drawOpacity = xhair_tex.a*Opacity;
	}
	if (XhairMode == 1)			// Solid color mode
	{
		drawBackground = back;
		drawXhair = float4(SolidColor, 1.0);
		drawOpacity = xhair_mask*Opacity;
	}
	if (XhairMode == 2)			// Gradient mode
	{
	    float4 fragColor;

		float2 uv = float2( (2 * vpos.x - ReShade::ScreenSize.x) / ReShade::ScreenSize.y, (2 * vpos.y - ReShade::ScreenSize.y) / ReShade::ScreenSize.y );

	    float radius = sqrt(uv.x * uv.x + uv.y * uv.y) / ModR;

	    float4 color1 = float4(GradientColor1, 1.0);
	    float4 color2 = float4(GradientColor2, 1.0);

		fragColor = lerp(color1, color2, radius);

		drawBackground = back;
		drawXhair = fragColor;
		drawOpacity = xhair_mask*Opacity;
	}
	if (XhairMode == 3)			// Inversion mode
	{
		float4 inv_center = 1-center;
		inv_center = ColorShift(inv_center, 0, 0, 0, 180);

		drawBackground = back;
		drawXhair = inv_center;
		drawOpacity = xhair_mask*Opacity;
	}

	if (UseStroke && XhairMode != 0)
	{
		float4 strokeN = tex2D(xhairMaskSampler, float2(texcoordMod.x, texcoordMod.y-1/ReShade::ScreenSize.y));
		float4 strokeS = tex2D(xhairMaskSampler, float2(texcoordMod.x, texcoordMod.y+1/ReShade::ScreenSize.y));
		float4 strokeW = tex2D(xhairMaskSampler, float2(texcoordMod.x-1/ReShade::ScreenSize.x, texcoordMod.y));
		float4 strokeE = tex2D(xhairMaskSampler, float2(texcoordMod.x+1/ReShade::ScreenSize.x, texcoordMod.y));
		float4 strokeNW = tex2D(xhairMaskSampler, float2(texcoordMod.x-1/ReShade::ScreenSize.x, texcoordMod.y-1/ReShade::ScreenSize.y));
		float4 strokeNE = tex2D(xhairMaskSampler, float2(texcoordMod.x+1/ReShade::ScreenSize.x, texcoordMod.y-1/ReShade::ScreenSize.y));
		float4 strokeSW = tex2D(xhairMaskSampler, float2(texcoordMod.x-1/ReShade::ScreenSize.x, texcoordMod.y+1/ReShade::ScreenSize.y));
		float4 strokeSE = tex2D(xhairMaskSampler, float2(texcoordMod.x+1/ReShade::ScreenSize.x, texcoordMod.y+1/ReShade::ScreenSize.y));
		float stroke = saturate(strokeN.a + strokeS.a + strokeW.a + strokeE.a + strokeNW.a + strokeNE.a + strokeSW.a + strokeSE.a);

		float4 drawStroke = lerp(back,float4(StrokeColor,1.0),stroke*StrokeOpacity);

		drawBackground = drawStroke;
	}

	outXhair = lerp(drawBackground,drawXhair,drawOpacity);

	return outXhair;
}

technique xhair
{
	pass HudPass
	{
		VertexShader = PostProcessVS;
		PixelShader = PS_Xhair;
	}
}
Rename the following textures to "xhair.png" and "xhair_mask.png" accordingly:
Textures [ Click to expand ]
Last Edit: 2 months 3 days ago by 63OR63.
The administrator has disabled public write access.
The following user(s) said Thank You: Wicked Sick, DeMondo, AladinZ, Gar Stazi

Crosshair overlay shader 1 month 5 days ago #2

Thank you. I have used your Shader to produce Scanlines as elaborated here: reshade.me/forum/shader-discussion/2401-...ripes-like-scanlines

Have a good Life.
The administrator has disabled public write access.