Fix crt-cyclon and update others (#3240)

* Fix crt-cyclon and update others

- Fix some crt-cyclon parameters;
- Update bicubic and lanczos3.

* Update crt-geom.fx and geom.fx

- Added image center X and Y to crt-geom.fx and geom.fx.
This commit is contained in:
Hyllian 2024-07-06 06:35:17 -03:00 committed by GitHub
parent b9155ec5ac
commit 91962508fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 139 additions and 106 deletions

View File

@ -32,11 +32,8 @@ uniform float SCANLINE <
ui_label = "Scanline Weight"; ui_label = "Scanline Weight";
> = 0.3; > = 0.3;
uniform float INTERLACE < uniform bool INTERLACE <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Interlacing On/Off"; ui_label = "Interlacing On/Off";
> = 1.0; > = 1.0;
@ -64,11 +61,8 @@ uniform float MSIZE <
ui_label = "Mask Size"; ui_label = "Mask Size";
> = 1.0; > = 1.0;
uniform float SLOT < uniform bool SLOT <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Slot Mask On/Off"; ui_label = "Slot Mask On/Off";
> = 1.0; > = 1.0;
@ -112,11 +106,8 @@ uniform float bogus_geom <
ui_label = " [ GEOMETRY SETTINGS ] "; ui_label = " [ GEOMETRY SETTINGS ] ";
> = 0.0; > = 0.0;
uniform float bzl < uniform bool bzl <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Bezel On/Off"; ui_label = "Bezel On/Off";
> = 1.0; > = 1.0;
@ -148,7 +139,7 @@ uniform float centerx <
ui_type = "drag"; ui_type = "drag";
ui_min = -5.0; ui_min = -5.0;
ui_max = 5.0; ui_max = 5.0;
ui_step = 0.0; ui_step = 0.05;
ui_label = "Image Center X"; ui_label = "Image Center X";
> = 0.0; > = 0.0;
@ -176,11 +167,8 @@ uniform float WARPY <
ui_label = "Curvature Vertical"; ui_label = "Curvature Vertical";
> = 0.01; > = 0.01;
uniform float vig < uniform bool vig <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Vignette On/Off"; ui_label = "Vignette On/Off";
> = 1.0; > = 1.0;
@ -236,7 +224,7 @@ uniform float BLACK <
ui_type = "drag"; ui_type = "drag";
ui_min = -0.20; ui_min = -0.20;
ui_max = 0.20; ui_max = 0.20;
ui_step = 0.0; ui_step = 0.01;
ui_label = "Black Level"; ui_label = "Black Level";
> = 0.0; > = 0.0;
@ -250,9 +238,9 @@ uniform float RG <
uniform float RB < uniform float RB <
ui_type = "drag"; ui_type = "drag";
ui_min = 0.0; ui_min = -0.25;
ui_max = -0.25; ui_max = 0.25;
ui_step = 0.2; ui_step = 0.01;
ui_label = "Blue <-to-> Red Hue"; ui_label = "Blue <-to-> Red Hue";
> = 0.0; > = 0.0;
@ -323,9 +311,10 @@ uniform float2 NormalizedInternalPixelSize < source = "normalized_internal_pixel
uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >;
uniform float UpscaleMultiplier < source = "upscale_multiplier"; >; uniform float UpscaleMultiplier < source = "upscale_multiplier"; >;
uniform float2 ViewportSize < source = "viewportsize"; >; uniform float2 ViewportSize < source = "viewportsize"; >;
uniform int FrameCount < source = "framecount"; >; uniform int FrameCount < source = "framecount"; >;
sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=LINEAR;MinFilter=LINEAR;MipFilter=LINEAR;};
texture tBezel < source = "crt-cyclon/bezel.png"; > texture tBezel < source = "crt-cyclon/bezel.png"; >
{ {
Width = BUFFER_WIDTH; Width = BUFFER_WIDTH;
@ -442,8 +431,9 @@ uniform float2 BufferHeight < source = "bufferheight"; >;
float4 CRT_CYCLON_PS(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target float4 CRT_CYCLON_PS(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target
{ {
float4 SourceSize = float4(1.0 / (NormalizedInternalPixelSize * UpscaleMultiplier), NormalizedInternalPixelSize * UpscaleMultiplier); float4 SourceSize = float4(1.0 / NormalizedNativePixelSize, NormalizedNativePixelSize);
float2 OutputSize = ViewportSize; float2 OutputSize = ViewportSize;
float2 scale = BufferViewportRatio.xy; float2 scale = BufferViewportRatio.xy;
float2 warpcoords = (vTexCoord-float2(0.5,0.5)) * BufferViewportRatio + float2(0.5,0.5); float2 warpcoords = (vTexCoord-float2(0.5,0.5)) * BufferViewportRatio + float2(0.5,0.5);
@ -458,7 +448,7 @@ float3x3 hue = float3x3(
float4 bez = float4(0.0,0.0,0.0,0.0); float4 bez = float4(0.0,0.0,0.0,0.0);
// if (bzl == 1.0) bez = tex2D(sBezel,vTexCoord*SourceSize.xy/OriginalSize.xy*0.97+float2(0.015,0.015)); // if (bzl == 1.0) bez = tex2D(sBezel,vTexCoord*SourceSize.xy/OriginalSize.xy*0.97+float2(0.015,0.015));
// if (bzl == 1.0) bez = tex2D(sBezel,vTexCoord*scale*0.97+float2(0.015,0.015)); // if (bzl == 1.0) bez = tex2D(sBezel,vTexCoord*scale*0.97+float2(0.015,0.015));
if (bzl == 1.0) bez = tex2D(sBezel,warpcoords*0.97+float2(0.015,0.015)); // This fix Bezel to adjust to Game's aspect ratio. if (bzl == true) bez = tex2D(sBezel,warpcoords*0.97+float2(0.015,0.015)); // This fix Bezel to adjust to Game's aspect ratio.
bez.rgb = lerp(bez.rgb, float3(ambient,ambient,ambient),0.5); bez.rgb = lerp(bez.rgb, float3(ambient,ambient,ambient),0.5);
@ -473,10 +463,10 @@ float3x3 hue = float3x3(
pos.x = lerp(pos.x, i.x*ps.x, 0.2); pos.x = lerp(pos.x, i.x*ps.x, 0.2);
// Convergence // Convergence
float3 res0 = tex2D(ReShade::BackBuffer,pos).rgb; float3 res0 = tex2D(sBackBuffer,pos).rgb;
float resr = tex2D(ReShade::BackBuffer,pos + dx*CONV_R).r; float resr = tex2D(sBackBuffer,pos + dx*CONV_R).r;
float resb = tex2D(ReShade::BackBuffer,pos + dx*CONV_B).b; float resb = tex2D(sBackBuffer,pos + dx*CONV_B).b;
float resg = tex2D(ReShade::BackBuffer,pos + dx*CONV_G).g; float resg = tex2D(sBackBuffer,pos + dx*CONV_G).g;
float3 res = float3( res0.r*(1.0-C_STR) + resr*C_STR, float3 res = float3( res0.r*(1.0-C_STR) + resr*C_STR,
res0.g*(1.0-C_STR) + resg*C_STR, res0.g*(1.0-C_STR) + resg*C_STR,
@ -484,7 +474,7 @@ float3x3 hue = float3x3(
); );
// Vignette // Vignette
float x = 0.0; float x = 0.0;
if (vig == 1.0){ if (vig == true){
x = vTexCoord.x*scale.x-0.5; x = vTexCoord.x*scale.x-0.5;
// x = vTexCoord.x-0.5; // x = vTexCoord.x-0.5;
x = x*x;} x = x*x;}
@ -508,7 +498,7 @@ float3x3 hue = float3x3(
{ {
s = frac(bpos.y*SourceSize.y/2.0-0.5); s = frac(bpos.y*SourceSize.y/2.0-0.5);
// if (INTERLACE == 1.0) s = mod(float(FrameCount),2.0) < 1.0 ? s: s+0.5; // if (INTERLACE == 1.0) s = mod(float(FrameCount),2.0) < 1.0 ? s: s+0.5;
if (INTERLACE == 1.0) s = (float(FrameCount) % 2.0) < 1.0 ? s: s+0.5; if (INTERLACE == true) s = (float(FrameCount) % 2.0) < 1.0 ? s: s+0.5;
} }
// Calculate CRT-Geom scanlines weight and apply // Calculate CRT-Geom scanlines weight and apply
float weight = scanlineWeights(s, res, x); float weight = scanlineWeights(s, res, x);
@ -521,7 +511,7 @@ float3x3 hue = float3x3(
float CGWG = lerp(Maskl, Maskh, l); float CGWG = lerp(Maskl, Maskh, l);
res *= Mask(xy, CGWG); res *= Mask(xy, CGWG);
// Apply slot mask on top of Trinitron-like mask // Apply slot mask on top of Trinitron-like mask
if (SLOT == 1.0) res *= lerp(slot(xy/2.0),float3(1.0,1.0,1.0),CGWG); if (SLOT == true) res *= lerp(slot(xy/2.0),float3(1.0,1.0,1.0),CGWG);
if (POTATO == 0.0) res = inv_gamma(res,pwr); if (POTATO == 0.0) res = inv_gamma(res,pwr);
else {res = sqrt(res); res *= lerp(1.3,1.1,l);} else {res = sqrt(res); res *= lerp(1.3,1.1,l);}
@ -536,7 +526,7 @@ float3x3 hue = float3x3(
res -= float3(BLACK,BLACK,BLACK); res -= float3(BLACK,BLACK,BLACK);
res *= blck; res *= blck;
// Apply bezel code, adapted from New-Pixie // Apply bezel code, adapted from New-Pixie
if (bzl >0.0) if (bzl == true)
res.rgb = lerp(res.rgb, lerp(max(res.rgb, 0.0), pow( abs(bez.rgb), float3( 1.4,1.4,1.4 ) ), bez.w * bez.w), float3( 1.0,1.0,1.0 ) ); res.rgb = lerp(res.rgb, lerp(max(res.rgb, 0.0), pow( abs(bez.rgb), float3( 1.4,1.4,1.4 ) ), bez.w * bez.w), float3( 1.0,1.0,1.0 ) );

View File

@ -124,6 +124,22 @@ uniform float overscan_y <
ui_label = "CRTGeom Vert. Overscan %"; ui_label = "CRTGeom Vert. Overscan %";
> = 100.0; > = 100.0;
uniform float centerx <
ui_type = "drag";
ui_min = -9.99;
ui_max = 9.99;
ui_step = 0.01;
ui_label = "Image Center X";
> = 0.00;
uniform float centery <
ui_type = "drag";
ui_min = -9.99;
ui_max = 9.99;
ui_step = 0.01;
ui_label = "Image Center Y";
> = 0.00;
uniform float DOTMASK < uniform float DOTMASK <
ui_type = "drag"; ui_type = "drag";
ui_min = 0.0; ui_min = 0.0;
@ -273,6 +289,15 @@ float3 vs_maxscale(float2 sinangle, float2 cosangle)
return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y)); return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
} }
// Code snippet borrowed from crt-cyclon. (credits to DariusG)
float2 Warp(float2 pos)
{
pos = pos*2.0 - 1.0;
pos *= float2(1.0 + pos.y*pos.y*0, 1.0 + pos.x*pos.x*0);
pos = pos*0.5 + 0.5;
return pos;
}
// Vertex shader generating a triangle covering the entire screen // Vertex shader generating a triangle covering the entire screen
@ -282,6 +307,9 @@ void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, ou
texcoord.y = (id == 1) ? 2.0 : 0.0; texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
// center screen
texcoord = Warp(texcoord - float2(centerx,centery)/100.0);
float2 SourceSize = 1.0/NormalizedNativePixelSize; float2 SourceSize = 1.0/NormalizedNativePixelSize;
float2 OutputSize = ViewportSize*BufferViewportRatio; float2 OutputSize = ViewportSize*BufferViewportRatio;
@ -453,6 +481,7 @@ float fwidth(float value){
} }
float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_VertexOut vVARS) : SV_Target float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_VertexOut vVARS) : SV_Target
{ {
// Here's a helpful diagram to keep in mind while trying to // Here's a helpful diagram to keep in mind while trying to
@ -478,6 +507,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_
// Texture coordinates of the texel containing the active pixel. // Texture coordinates of the texel containing the active pixel.
float2 xy; float2 xy;
if (CURVATURE > 0.5) if (CURVATURE > 0.5)
xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch); xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch);
else else

View File

@ -1,4 +1,4 @@
#include "../ReShade.fxh" #include "ReShade.fxh"
/* /*
Bicubic multipass Shader Bicubic multipass Shader
@ -86,19 +86,18 @@ float3 bicubic_ar(float fp, float3 C0, float3 C1, float3 C2, float3 C3)
} }
float4 PS_Bicubic_X(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target float4 PS_Bicubic_X(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target
{ {
// Both dimensions are unfiltered, so it looks for lores pixels. // Both dimensions are unfiltered, so it looks for lores pixels.
float2 ps = NormalizedNativePixelSize; float2 ps = NormalizedNativePixelSize;
float2 posi = uv_tx.xy + ps * float2(0.5, 0.0); float2 pos = uv_tx.xy/ps - float2(0.5, 0.0);
float2 fp = frac(posi / ps); float2 tc = (floor(pos) + float2(0.5, 0.5)) * ps;
float2 fp = frac(pos);
float2 tc = posi - (fp + 0.5) * ps; float3 C0 = tex2D(ReShade::BackBuffer, tc + ps*float2(-1.0, 0.0)).rgb;
float3 C1 = tex2D(ReShade::BackBuffer, tc + ps*float2( 0.0, 0.0)).rgb;
float3 C0 = tex2D(ReShade::BackBuffer, tc + ps*float2(-1.0, 1.0)).rgb; float3 C2 = tex2D(ReShade::BackBuffer, tc + ps*float2( 1.0, 0.0)).rgb;
float3 C1 = tex2D(ReShade::BackBuffer, tc + ps*float2( 0.0, 1.0)).rgb; float3 C3 = tex2D(ReShade::BackBuffer, tc + ps*float2( 2.0, 0.0)).rgb;
float3 C2 = tex2D(ReShade::BackBuffer, tc + ps*float2( 1.0, 1.0)).rgb;
float3 C3 = tex2D(ReShade::BackBuffer, tc + ps*float2( 2.0, 1.0)).rgb;
float3 color = bicubic_ar(fp.x, C0, C1, C2, C3); float3 color = bicubic_ar(fp.x, C0, C1, C2, C3);
@ -106,28 +105,27 @@ float4 PS_Bicubic_X(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Targe
} }
float4 PS_Bicubic_Y(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target float4 PS_Bicubic_Y(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target
{ {
// One must be careful here. Horizontal dimension is already filtered, so it looks for x in hires. // One must be careful here. Horizontal dimension is already filtered, so it looks for x in hires.
float2 ps = float2(1.0/(ViewportSize.x*BufferToViewportRatio.x), NormalizedNativePixelSize.y); float2 ps = float2(1.0/(ViewportSize.x*BufferToViewportRatio.x), NormalizedNativePixelSize.y);
float2 posi = uv_tx.xy + ps * float2(0.5, 0.5); float2 pos = uv_tx.xy/ps - float2(0.0, 0.5);
float2 fp = frac(posi / ps); float2 tc = (floor(pos) + float2(0.5, 0.5)) * ps;
float2 fp = frac(pos);
float2 tc = posi - (fp + 0.5) * ps; float3 C0 = tex2D(sBicubic_P0, tc + ps*float2(0.0, -1.0)).rgb;
float3 C1 = tex2D(sBicubic_P0, tc + ps*float2(0.0, 0.0)).rgb;
float3 C0 = tex2D(sBicubic_P0, tc + ps*float2(1.0, -1.0)).rgb; float3 C2 = tex2D(sBicubic_P0, tc + ps*float2(0.0, 1.0)).rgb;
float3 C1 = tex2D(sBicubic_P0, tc + ps*float2(1.0, 0.0)).rgb; float3 C3 = tex2D(sBicubic_P0, tc + ps*float2(0.0, 2.0)).rgb;
float3 C2 = tex2D(sBicubic_P0, tc + ps*float2(1.0, 1.0)).rgb;
float3 C3 = tex2D(sBicubic_P0, tc + ps*float2(1.0, 2.0)).rgb;
float3 color = bicubic_ar(fp.y, C0, C1, C2, C3); float3 color = bicubic_ar(fp.y, C0, C1, C2, C3);
return float4(color, 1.0); return float4(color, 1.0);
} }
technique Bicubic technique Bicubic
{ {
pass pass
{ {
VertexShader = PostProcessVS; VertexShader = PostProcessVS;
@ -139,5 +137,4 @@ technique Bicubic
VertexShader = PostProcessVS; VertexShader = PostProcessVS;
PixelShader = PS_Bicubic_Y; PixelShader = PS_Bicubic_Y;
} }
} }

View File

@ -28,7 +28,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
http://www.gnu.org/copyleft/gpl.html http://www.gnu.org/copyleft/gpl.html
*/ */
uniform bool LANCZOS3_ANTI_RINGING < uniform bool LANCZOS3_ANTI_RINGING <
ui_type = "radio"; ui_type = "radio";
ui_label = "Lanczos3 Anti-Ringing"; ui_label = "Lanczos3 Anti-Ringing";
@ -41,6 +40,7 @@ uniform float2 ViewportSize < source = "viewportsize"; >;
texture2D tLanczos3_P0{Width=BUFFER_WIDTH;Height=BUFFER_HEIGHT;Format=RGBA8;}; texture2D tLanczos3_P0{Width=BUFFER_WIDTH;Height=BUFFER_HEIGHT;Format=RGBA8;};
sampler2D sLanczos3_P0{Texture=tLanczos3_P0;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; sampler2D sLanczos3_P0{Texture=tLanczos3_P0;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;};
#define AR_STRENGTH 1.0 #define AR_STRENGTH 1.0
#define FIX(c) (max(abs(c),1e-5)) #define FIX(c) (max(abs(c),1e-5))
#define PI 3.1415926535897932384626433832795 #define PI 3.1415926535897932384626433832795
@ -48,10 +48,10 @@ sampler2D sLanczos3_P0{Texture=tLanczos3_P0;AddressU=CLAMP;AddressV=CLAMP;Addres
float3 weight3(float x) float3 weight3(float x)
{ {
float3 Sample = FIX(2.0 * PI * float3(x - 1.5, x - 0.5, x + 0.5)); float3 Sampling = FIX(2.0 * PI * float3(x - 1.5, x - 0.5, x + 0.5));
// Lanczos3. Note: we normalize outside this function, so no point in multiplying by radius. // Lanczos3. Note: we normalize outside this function, so no point in multiplying by radius.
return sin(Sample) * sin(Sample / radius) / (Sample * Sample); return sin(Sampling) * sin(Sampling / radius) / (Sampling * Sampling);
} }
float3 lanczos3ar(float fp, float3 C0, float3 C1, float3 C2, float3 C3, float3 C4, float3 C5) float3 lanczos3ar(float fp, float3 C0, float3 C1, float3 C2, float3 C3, float3 C4, float3 C5)
@ -79,23 +79,21 @@ float3 lanczos3ar(float fp, float3 C0, float3 C1, float3 C2, float3 C3, float3 C
} }
float4 PS_Lanczos3_X(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target
float4 PS_Lanczos3_X(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target
{ {
// Both dimensions are unfiltered, so it looks for lores pixels. // Both dimensions are unfiltered, so it looks for lores pixels.
float2 ps = NormalizedNativePixelSize; float2 ps = NormalizedNativePixelSize;
float2 posi = uv_tx.xy + ps * float2(0.5, 0.0); float2 pos = uv_tx.xy/ps - float2(0.5, 0.0);
float2 fp = frac(posi / ps); float2 tc = (floor(pos) + float2(0.5, 0.5)) * ps;
float2 fp = frac(pos);
float2 xystart = posi - (fp + 0.5) * ps; float3 C0 = tex2D(ReShade::BackBuffer, tc + ps*float2(-2.0, 0.0)).rgb;
float3 C1 = tex2D(ReShade::BackBuffer, tc + ps*float2(-1.0, 0.0)).rgb;
float ypos = xystart.y + ps.y; float3 C2 = tex2D(ReShade::BackBuffer, tc + ps*float2( 0.0, 0.0)).rgb;
float3 C3 = tex2D(ReShade::BackBuffer, tc + ps*float2( 1.0, 0.0)).rgb;
float3 C0 = tex2D(ReShade::BackBuffer, float2(xystart.x - ps.x * 2.0, ypos)).rgb; float3 C4 = tex2D(ReShade::BackBuffer, tc + ps*float2( 2.0, 0.0)).rgb;
float3 C1 = tex2D(ReShade::BackBuffer, float2(xystart.x - ps.x * 1.0, ypos)).rgb; float3 C5 = tex2D(ReShade::BackBuffer, tc + ps*float2( 3.0, 0.0)).rgb;
float3 C2 = tex2D(ReShade::BackBuffer, float2(xystart.x , ypos)).rgb;
float3 C3 = tex2D(ReShade::BackBuffer, float2(xystart.x + ps.x * 1.0, ypos)).rgb;
float3 C4 = tex2D(ReShade::BackBuffer, float2(xystart.x + ps.x * 2.0, ypos)).rgb;
float3 C5 = tex2D(ReShade::BackBuffer, float2(xystart.x + ps.x * 3.0, ypos)).rgb;
float3 color = lanczos3ar(fp.x, C0, C1, C2, C3, C4, C5); float3 color = lanczos3ar(fp.x, C0, C1, C2, C3, C4, C5);
@ -103,32 +101,29 @@ float4 PS_Lanczos3_X(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Targ
} }
float4 PS_Lanczos3_Y(float4 pos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target float4 PS_Lanczos3_Y(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target
{ {
// One must be careful here. Horizontal dimension is already filtered, so it looks for x in hires. // One must be careful here. Horizontal dimension is already filtered, so it looks for x in hires.
float2 ps = float2(1.0/(ViewportSize.x*BufferToViewportRatio.x), NormalizedNativePixelSize.y); float2 ps = float2(1.0/(ViewportSize.x*BufferToViewportRatio.x), NormalizedNativePixelSize.y);
float2 posi = uv_tx.xy + ps * float2(0.5, 0.5); float2 pos = uv_tx.xy/ps - float2(0.0, 0.5);
float2 fp = frac(posi / ps); float2 tc = (floor(pos) + float2(0.5, 0.5)) * ps;
float2 fp = frac(pos);
float2 xystart = posi - (fp + 0.5) * ps; float3 C0 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, -2.0)).rgb;
float3 C1 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, -1.0)).rgb;
float xpos = xystart.x + ps.x; float3 C2 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 0.0)).rgb;
float3 C3 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 1.0)).rgb;
float3 C0 = tex2D(sLanczos3_P0, float2(xpos, xystart.y - ps.y * 2.0)).rgb; float3 C4 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 2.0)).rgb;
float3 C1 = tex2D(sLanczos3_P0, float2(xpos, xystart.y - ps.y * 1.0)).rgb; float3 C5 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 3.0)).rgb;
float3 C2 = tex2D(sLanczos3_P0, float2(xpos, xystart.y )).rgb;
float3 C3 = tex2D(sLanczos3_P0, float2(xpos, xystart.y + ps.y * 1.0)).rgb;
float3 C4 = tex2D(sLanczos3_P0, float2(xpos, xystart.y + ps.y * 2.0)).rgb;
float3 C5 = tex2D(sLanczos3_P0, float2(xpos, xystart.y + ps.y * 3.0)).rgb;
float3 color = lanczos3ar(fp.y, C0, C1, C2, C3, C4, C5); float3 color = lanczos3ar(fp.y, C0, C1, C2, C3, C4, C5);
return float4(color, 1.0); return float4(color, 1.0);
} }
technique Lanczos3 technique Lanczos3
{ {
pass pass
{ {
VertexShader = PostProcessVS; VertexShader = PostProcessVS;
@ -140,5 +135,4 @@ technique Lanczos3
VertexShader = PostProcessVS; VertexShader = PostProcessVS;
PixelShader = PS_Lanczos3_Y; PixelShader = PS_Lanczos3_Y;
} }
} }

View File

@ -32,11 +32,8 @@
uniform float geom_curvature < uniform bool geom_curvature <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Geom Curvature Toggle"; ui_label = "Geom Curvature Toggle";
> = 1.0; > = 1.0;
@ -56,11 +53,8 @@ uniform float geom_d <
ui_label = "Geom Distance"; ui_label = "Geom Distance";
> = 1.5; > = 1.5;
uniform float geom_invert_aspect < uniform bool geom_invert_aspect <
ui_type = "drag"; ui_type = "radio";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 1.0;
ui_label = "Geom Curvature Aspect Inversion"; ui_label = "Geom Curvature Aspect Inversion";
> = 0.0; > = 0.0;
@ -112,6 +106,22 @@ uniform float geom_overscan_y <
ui_label = "Geom Vert. Overscan %"; ui_label = "Geom Vert. Overscan %";
> = 100.0; > = 100.0;
uniform float centerx <
ui_type = "drag";
ui_min = -9.99;
ui_max = 9.99;
ui_step = 0.01;
ui_label = "Image Center X";
> = 0.00;
uniform float centery <
ui_type = "drag";
ui_min = -9.99;
ui_max = 9.99;
ui_step = 0.01;
ui_label = "Image Center Y";
> = 0.00;
uniform float geom_lum < uniform float geom_lum <
ui_type = "drag"; ui_type = "drag";
ui_min = 0.5; ui_min = 0.5;
@ -164,7 +174,7 @@ sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BO
#endif #endif
// aspect ratio // aspect ratio
#define aspect (geom_invert_aspect>0.5?float2(0.75,1.0):float2(1.0,0.75)) #define aspect (geom_invert_aspect==true?float2(0.75,1.0):float2(1.0,0.75))
#define overscan (float2(1.01,1.01)); #define overscan (float2(1.01,1.01));
@ -228,6 +238,15 @@ float3 vs_maxscale(float2 sinangle, float2 cosangle)
return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y)); return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
} }
// Code snippet borrowed from crt-cyclon. (credits to DariusG)
float2 Warp(float2 pos)
{
pos = pos*2.0 - 1.0;
pos *= float2(1.0 + pos.y*pos.y*0, 1.0 + pos.x*pos.x*0);
pos = pos*0.5 + 0.5;
return pos;
}
// Vertex shader generating a triangle covering the entire screen // Vertex shader generating a triangle covering the entire screen
@ -237,7 +256,10 @@ void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, ou
texcoord.y = (id == 1) ? 2.0 : 0.0; texcoord.y = (id == 1) ? 2.0 : 0.0;
position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
// float2 SourceSize = 1.0/NormalizedNativePixelSize; // center screen
texcoord = Warp(texcoord - float2(centerx,centery)/100.0);
// float2 SourceSize = 1.0/NormalizedNativePixelSize;
float2 SourceSize = ViewportSize*BufferViewportRatio; float2 SourceSize = ViewportSize*BufferViewportRatio;
// Precalculate a bunch of useful values we'll need in the fragment // Precalculate a bunch of useful values we'll need in the fragment
@ -333,7 +355,7 @@ float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_
// Texture coordinates of the texel containing the active pixel. // Texture coordinates of the texel containing the active pixel.
float2 xy; float2 xy;
if (geom_curvature > 0.5) if (geom_curvature == true)
xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch); xy = transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch);
else else
xy = vTexCoord; xy = vTexCoord;