Resources: Fix crt-lottes under Direct3D

And add additional builtin shaders.
This commit is contained in:
Stenzek 2023-12-28 20:43:52 +10:00
parent 344d2ccd5d
commit a22eef63b9
No known key found for this signature in database
8 changed files with 978 additions and 4 deletions

View file

@ -133,7 +133,7 @@ float3 ToLinear(float3 c)
}
float3 ToSrgb(float3 c)
{
return pow(c, float3(1.0 / 2.2));
return pow(c, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2));
}
#else
float ToLinear1(float c)

View file

@ -0,0 +1,298 @@
#include "ReShade.fxh"
// newpixie CRT
// by Mattias Gustavsson
// adapted for slang by hunterk
/*
------------------------------------------------------------------------------
This software is available under 2 licenses - you may choose the one you like.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2016 Mattias Gustavsson
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/
uniform float acc_modulate <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 0.01;
ui_label = "Accumulate Modulation [CRT-NewPixie]";
> = 0.65;
texture2D tAccTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler sAccTex { Texture=tAccTex; };
//PASS 1
float3 PrevColor(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target
{
return tex2D(ReShade::BackBuffer, uv).rgb;
}
float4 PS_NewPixie_Accum(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target
{
float4 a = tex2D(sAccTex, uv.xy) * float4(acc_modulate,acc_modulate,acc_modulate,acc_modulate);
float4 b = tex2D(ReShade::BackBuffer, uv.xy);
return max( a, b * 0.96 );
}
//PASS 2 AND 3
texture GaussianBlurTex { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
sampler GaussianBlurSampler { Texture = GaussianBlurTex;};
uniform float blur_x <
ui_type = "drag";
ui_min = 0.0;
ui_max = 5.0;
ui_step = 0.25;
ui_label = "Horizontal Blur [CRT-NewPixie]";
> = 1.0;
uniform float blur_y <
ui_type = "drag";
ui_min = 0.0;
ui_max = 5.0;
ui_step = 0.25;
ui_label = "Vertical Blur [CRT-NewPixie]";
> = 1.0;
float4 PS_NewPixie_Blur(float4 pos : SV_Position, float2 uv_tx : TEXCOORD0) : SV_Target
{
float2 blur = float2(blur_x, blur_y) * ReShade::PixelSize.xy;
float2 uv = uv_tx.xy;
float4 sum = tex2D( ReShade::BackBuffer, uv ) * 0.2270270270;
sum += tex2D(ReShade::BackBuffer, float2( uv.x - 4.0 * blur.x, uv.y - 4.0 * blur.y ) ) * 0.0162162162;
sum += tex2D(ReShade::BackBuffer, float2( uv.x - 3.0 * blur.x, uv.y - 3.0 * blur.y ) ) * 0.0540540541;
sum += tex2D(ReShade::BackBuffer, float2( uv.x - 2.0 * blur.x, uv.y - 2.0 * blur.y ) ) * 0.1216216216;
sum += tex2D(ReShade::BackBuffer, float2( uv.x - 1.0 * blur.x, uv.y - 1.0 * blur.y ) ) * 0.1945945946;
sum += tex2D(ReShade::BackBuffer, float2( uv.x + 1.0 * blur.x, uv.y + 1.0 * blur.y ) ) * 0.1945945946;
sum += tex2D(ReShade::BackBuffer, float2( uv.x + 2.0 * blur.x, uv.y + 2.0 * blur.y ) ) * 0.1216216216;
sum += tex2D(ReShade::BackBuffer, float2( uv.x + 3.0 * blur.x, uv.y + 3.0 * blur.y ) ) * 0.0540540541;
sum += tex2D(ReShade::BackBuffer, float2( uv.x + 4.0 * blur.x, uv.y + 4.0 * blur.y ) ) * 0.0162162162;
return sum;
}
//PASS 4
uniform int FCount < source = "framecount"; >;
texture tFrame < source = "crt-newpixie/crtframe.png"; >
{
Width = 1024;
Height = 1024;
MipLevels = 1;
};
sampler sFrame { Texture = tFrame; AddressU = BORDER; AddressV = BORDER; MinFilter = LINEAR; MagFilter = LINEAR;};
uniform bool use_frame <
ui_type = "boolean";
ui_label = "Use Frame Image [CRT-NewPixie]";
> = false;
uniform float curvature <
ui_type = "drag";
ui_min = 0.0001;
ui_max = 4.0;
ui_step = 0.25;
ui_label = "Curvature [CRT-NewPixie]";
> = 2.0;
uniform bool wiggle_toggle <
ui_type = "boolean";
ui_label = "Interference [CRT-NewPixie]";
> = false;
uniform bool scanroll <
ui_type = "boolean";
ui_label = "Rolling Scanlines [CRT-NewPixie]";
> = true;
float3 tsample( sampler samp, float2 tc, float offs, float2 resolution )
{
tc = tc * float2(1.025, 0.92) + float2(-0.0125, 0.04);
float3 s = pow( abs( tex2D( samp, float2( tc.x, 1.0-tc.y ) ).rgb), float3( 2.2,2.2,2.2 ) );
return s*float3(1.25,1.25,1.25);
}
float3 filmic( float3 LinearColor )
{
float3 x = max( float3(0.0,0.0,0.0), LinearColor-float3(0.004,0.004,0.004));
return (x*(6.2*x+0.5))/(x*(6.2*x+1.7)+0.06);
}
float2 curve( float2 uv )
{
uv = (uv - 0.5);// * 2.0;
uv *= float2(0.925, 1.095);
uv *= curvature;
uv.x *= 1.0 + pow((abs(uv.y) / 4.0), 2.0);
uv.y *= 1.0 + pow((abs(uv.x) / 3.0), 2.0);
uv /= curvature;
uv += 0.5;
uv = uv *0.92 + 0.04;
return uv;
}
float rand(float2 co){ return frac(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453); }
#define resolution ReShade::ScreenSize.xy
#define mod(x,y) (x-y*floor(x/y))
float4 PS_NewPixie_Final(float4 pos: SV_Position, float2 uv_tx : TEXCOORD0) : SV_Target
{
// stop time variable so the screen doesn't wiggle
float time = mod(FCount, 849.0) * 36.0;
float2 uv = uv_tx.xy;
uv.y = 1.0 - uv_tx.y;
/* Curve */
float2 curved_uv = lerp( curve( uv ), uv, 0.4 );
float scale = -0.101;
float2 scuv = curved_uv*(1.0-scale)+scale/2.0+float2(0.003, -0.001);
uv = scuv;
/* Main color, Bleed */
float3 col;
float x = wiggle_toggle* sin(0.1*time+curved_uv.y*13.0)*sin(0.23*time+curved_uv.y*19.0)*sin(0.3+0.11*time+curved_uv.y*23.0)*0.0012;
float o =sin(uv_tx.y*1.5)/resolution.x;
x+=o*0.25;
// make time do something again
time = float(mod(FCount, 640) * 1);
col.r = tsample(ReShade::BackBuffer,float2(x+scuv.x+0.0009,scuv.y+0.0009),resolution.y/800.0, resolution ).x+0.02;
col.g = tsample(ReShade::BackBuffer,float2(x+scuv.x+0.0000,scuv.y-0.0011),resolution.y/800.0, resolution ).y+0.02;
col.b = tsample(ReShade::BackBuffer,float2(x+scuv.x-0.0015,scuv.y+0.0000),resolution.y/800.0, resolution ).z+0.02;
float i = clamp(col.r*0.299 + col.g*0.587 + col.b*0.114, 0.0, 1.0 );
i = pow( 1.0 - pow(i,2.0), 1.0 );
i = (1.0-i) * 0.85 + 0.15;
/* Ghosting */
float ghs = 0.15;
float3 r = tsample(GaussianBlurSampler, float2(x-0.014*1.0, -0.027)*0.85+0.007*float2( 0.35*sin(1.0/7.0 + 15.0*curved_uv.y + 0.9*time),
0.35*sin( 2.0/7.0 + 10.0*curved_uv.y + 1.37*time) )+float2(scuv.x+0.001,scuv.y+0.001),
5.5+1.3*sin( 3.0/9.0 + 31.0*curved_uv.x + 1.70*time),resolution).xyz*float3(0.5,0.25,0.25);
float3 g = tsample(GaussianBlurSampler, float2(x-0.019*1.0, -0.020)*0.85+0.007*float2( 0.35*cos(1.0/9.0 + 15.0*curved_uv.y + 0.5*time),
0.35*sin( 2.0/9.0 + 10.0*curved_uv.y + 1.50*time) )+float2(scuv.x+0.000,scuv.y-0.002),
5.4+1.3*sin( 3.0/3.0 + 71.0*curved_uv.x + 1.90*time),resolution).xyz*float3(0.25,0.5,0.25);
float3 b = tsample(GaussianBlurSampler, float2(x-0.017*1.0, -0.003)*0.85+0.007*float2( 0.35*sin(2.0/3.0 + 15.0*curved_uv.y + 0.7*time),
0.35*cos( 2.0/3.0 + 10.0*curved_uv.y + 1.63*time) )+float2(scuv.x-0.002,scuv.y+0.000),
5.3+1.3*sin( 3.0/7.0 + 91.0*curved_uv.x + 1.65*time),resolution).xyz*float3(0.25,0.25,0.5);
col += float3(ghs*(1.0-0.299),ghs*(1.0-0.299),ghs*(1.0-0.299))*pow(clamp(float3(3.0,3.0,3.0)*r,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
col += float3(ghs*(1.0-0.587),ghs*(1.0-0.587),ghs*(1.0-0.587))*pow(clamp(float3(3.0,3.0,3.0)*g,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
col += float3(ghs*(1.0-0.114),ghs*(1.0-0.114),ghs*(1.0-0.114))*pow(clamp(float3(3.0,3.0,3.0)*b,float3(0.0,0.0,0.0),float3(1.0,1.0,1.0)),float3(2.0,2.0,2.0))*float3(i,i,i);
/* Level adjustment (curves) */
col *= float3(0.95,1.05,0.95);
col = clamp(col*1.3 + 0.75*col*col + 1.25*col*col*col*col*col,float3(0.0,0.0,0.0),float3(10.0,10.0,10.0));
/* Vignette */
float vig = (0.1 + 1.0*16.0*curved_uv.x*curved_uv.y*(1.0-curved_uv.x)*(1.0-curved_uv.y));
vig = 1.3*pow(vig,0.5);
col *= vig;
time *= scanroll;
/* Scanlines */
float scans = clamp( 0.35+0.18*sin(6.0*time-curved_uv.y*resolution.y*1.5), 0.0, 1.0);
float s = pow(scans,0.9);
col = col * float3(s,s,s);
/* Vertical lines (shadow mask) */
col*=1.0-0.23*(clamp((mod(uv_tx.xy.x, 3.0))/2.0,0.0,1.0));
/* Tone map */
col = filmic( col );
/* Noise */
/*float2 seed = floor(curved_uv*resolution.xy*float2(0.5))/resolution.xy;*/
float2 seed = curved_uv*resolution.xy;;
/* seed = curved_uv; */
col -= 0.015*pow(float3(rand( seed +time ), rand( seed +time*2.0 ), rand( seed +time * 3.0 ) ), float3(1.5,1.5,1.5) );
/* Flicker */
col *= (1.0-0.004*(sin(50.0*time+curved_uv.y*2.0)*0.5+0.5));
/* Clamp */
// if(max(abs(uv.x-0.5),abs(uv.y-0.5))>0.5)
// col = float3(0.0,0.0,0.0);
// if (curved_uv.x < 0.0 || curved_uv.x > 1.0)
// col *= 0.0;
// if (curved_uv.y < 0.0 || curved_uv.y > 1.0)
// col *= 0.0;
uv = curved_uv;
/* Frame */
float2 fscale = float2( 0.026, -0.018);//float2( -0.018, -0.013 );
uv = float2(uv.x, 1.-uv.y);
float4 f= tex2D(sFrame,uv_tx.xy);//*((1.0)+2.0*fscale)-fscale-float2(-0.0, 0.005));
f.xyz = lerp( f.xyz, float3(0.5,0.5,0.5), 0.5 );
float fvig = clamp( -0.00+512.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y), 0.2, 0.8 );
col = lerp( col, lerp( max( col, 0.0), pow( abs( f.xyz ), float3( 1.4,1.4,1.4 ) ) * fvig, f.w * f.w), float3( use_frame,use_frame,use_frame ) );
return float4( col, 1.0 );
}
technique CRTNewPixie
{
pass PS_CRTNewPixie_Accum
{
VertexShader=PostProcessVS;
PixelShader=PS_NewPixie_Accum;
}
pass PS_CRTNewPixie_SaveBuffer {
VertexShader=PostProcessVS;
PixelShader=PrevColor;
RenderTarget = tAccTex;
}
pass PS_CRTNewPixie_Blur
{
VertexShader = PostProcessVS;
PixelShader = PS_NewPixie_Blur;
RenderTarget = GaussianBlurTex;
}
pass PS_CRTNewPixie_Final
{
VertexShader = PostProcessVS;
PixelShader = PS_NewPixie_Final;
}
}

View file

@ -0,0 +1,446 @@
#include "ReShade.fxh"
//
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
//
// by Timothy Lottes
//
// This is more along the style of a really good CGA arcade monitor.
// With RGB inputs instead of NTSC.
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
//
// Left it unoptimized to show the theory behind the algorithm.
//
// It is an example what I personally would want as a display option for pixel art games.
// Please take and use, change, or whatever.
//
#ifndef CRTS_DEBUG
#define CRTS_DEBUG 0
#endif
#ifndef CRTS_2_TAP
#define CRTS_2_TAP 0
#endif
uniform bool CRTS_WARP <
ui_type = "boolean";
ui_label = "Enable Warping [CRT Lottes 2.0]";
> = true;
uniform float CRTS_WARP_X <
ui_type = "drag";
ui_min = 0.0;
ui_max = 512.0;
ui_label = "CRT Warping X [CRT Lottes 2.0]";
> = 64.0;
uniform float CRTS_WARP_Y <
ui_type = "drag";
ui_min = 0.0;
ui_max = 512.0;
ui_label = "CRT Warping Y [CRT Lottes 2.0]";
> = 48.0;
uniform bool CRTS_TONE <
ui_type = "boolean";
ui_label = "Enable CRT Tonemapping [CRT Lottes 2.0]";
> = true;
uniform bool CRTS_CONTRAST <
ui_type = "boolean";
ui_label = "Enable CRT Contrast [CRT Lottes 2.0]";
> = false;
uniform bool CRTS_SATURATION <
ui_type = "boolean";
ui_label = "Enable CRT Saturation [CRT Lottes 2.0]";
> = false;
uniform int CRTS_MASK_TYPE <
ui_type = "combo";
ui_items = "None\0Aperture Grille\0Aperture Grille (Lite)\0Shadow Mask\0";
ui_label = "Mask Type [CRT Lottes 2.0]";
> = 2;
//--------------------------------------------------------------
// Scanline thinness
// 0.50 = fused scanlines
// 0.70 = recommended default
// 1.00 = thinner scanlines (too thin)
uniform float INPUT_THIN <
ui_type = "drag";
ui_min = 0.5;
ui_max = 1.0;
ui_label = "Scanlines Thinnes [CRT Lottes 2.0]";
> = 0.70;
//--------------------------------------------------------------
// Horizonal scan blur
// -3.0 = pixely
// -2.5 = default
// -2.0 = smooth
// -1.0 = too blurry
uniform float INPUT_BLUR <
ui_type = "drag";
ui_min = -3.0;
ui_max = 0.0;
ui_label = "Horizontal Scan Blur [CRT Lottes 2.0]";
> = -2.5;
//--------------------------------------------------------------
// Shadow mask effect, ranges from,
// 0.25 = large amount of mask (not recommended, too dark)
// 0.50 = recommended default
// 1.00 = no shadow mask
uniform float INPUT_MASK <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_label = "Shadow Mask Intensity [CRT Lottes 2.0]";
> = 0.5;
//--------------------------------------------------------------
uniform int INPUT_X <
ui_type = "drag";
ui_min = 1;
ui_max = BUFFER_WIDTH;
ui_label = "Resolution Width [CRT Lottes 2.0]";
> = 640;
uniform int INPUT_Y <
ui_type = "drag";
ui_min = 1;
ui_max = BUFFER_HEIGHT;
ui_label = "Resolution Height [CRT Lottes 2.0]";
> = 480;
//--------------------------------------------------------------
// Setup the function which returns input image color
void ToLinear(inout float3 color)
{
float3 c1 = color.rgb / 12.92;
float3 c2 = pow((color.rgb + 0.055)/1.055, 2.4);
color.r = (color.r <= 0.04045) ? c1.r : c2.r;
color.g = (color.g <= 0.04045) ? c1.g : c2.g;
color.b = (color.b <= 0.04045) ? c1.b : c2.b;
}
void ToSRGB(inout float3 color)
{
float3 c1 = color.rgb * 12.92;
float3 c2 = 1.055 * pow(color.rgb, 0.4166) - 0.055;
color.r = (color.r < 0.0031308) ? c1.r : c2.r;
color.g = (color.g < 0.0031308) ? c1.g : c2.g;
color.b = (color.b < 0.0031308) ? c1.b : c2.b;
}
float3 CrtsFetch(float2 uv)
{
float3 color = tex2D(ReShade::BackBuffer, uv).rgb;
ToLinear(color);
return color;
}
float4 CrtsTone(
float contrast,
float saturation,
float thin,
float mask)
{
mask = INPUT_MASK;
if (CRTS_MASK_TYPE <= 0){
mask=1.0;
}
if(CRTS_MASK_TYPE == 2){
mask=0.5+INPUT_MASK*0.5;
}
float4 ret;
float midOut=0.18/((1.5-thin)*(0.5*mask+0.5));
float pMidIn=pow(0.18,contrast);
ret.x=contrast;
ret.y=((-pMidIn)+midOut)/((1.0-pMidIn)*midOut);
ret.z=((-pMidIn)*midOut+pMidIn)/(midOut*(-pMidIn)+midOut);
ret.w=contrast+saturation;
return ret;
}
float3 CrtsMask(float2 pos,float dark)
{
if (CRTS_MASK_TYPE == 1){
float3 m=dark;
float x=frac(pos.x*(1.0/3.0));
if(x<(1.0/3.0))m.r=1.0;
else if(x<(2.0/3.0))m.g=1.0;
else m.b=1.0;
return m;
} else if (CRTS_MASK_TYPE == 2){
float3 m=1.0;
float x=frac(pos.x*(1.0/3.0));
if(x<(1.0/3.0))m.r=dark;
else if(x<(2.0/3.0))m.g=dark;
else m.b=dark;
return m;
} else if(CRTS_MASK_TYPE <= 0){
return 1.0;
} else if(CRTS_MASK_TYPE >= 3){
pos.x+=pos.y*3.0;
float3 m=dark;
float x=frac(pos.x*(1.0/6.0));
if(x<(1.0/3.0))m.r=1.0;
else if(x<(2.0/3.0))m.g=1.0;
else m.b=1.0;
return m;
} else {
return 0.0;
}
}
float3 CrtsFilter(
//--------------------------------------------------------------
// SV_POSITION, fragCoord.xy
float2 ipos,
//--------------------------------------------------------------
// inputSize / outputSize (in pixels)
float2 inputSizeDivOutputSize,
//--------------------------------------------------------------
// 0.5 * inputSize (in pixels)
float2 halfInputSize,
//--------------------------------------------------------------
// 1.0 / inputSize (in pixels)
float2 rcpInputSize,
//--------------------------------------------------------------
// 1.0 / outputSize (in pixels)
float2 rcpOutputSize,
//--------------------------------------------------------------
// 2.0 / outputSize (in pixels)
float2 twoDivOutputSize,
//--------------------------------------------------------------
// inputSize.y
float inputHeight,
//--------------------------------------------------------------
// Warp scanlines but not phosphor mask
// 0.0 = no warp
// 1.0/64.0 = light warping
// 1.0/32.0 = more warping
// Want x and y warping to be different (based on aspect)
float2 warp,
//--------------------------------------------------------------
// Scanline thinness
// 0.50 = fused scanlines
// 0.70 = recommended default
// 1.00 = thinner scanlines (too thin)
// Shared with CrtsTone() function
float thin,
//--------------------------------------------------------------
// Horizonal scan blur
// -3.0 = pixely
// -2.5 = default
// -2.0 = smooth
// -1.0 = too blurry
float blur,
//--------------------------------------------------------------
// Shadow mask effect, ranges from,
// 0.25 = large amount of mask (not recommended, too dark)
// 0.50 = recommended default
// 1.00 = no shadow mask
// Shared with CrtsTone() function
float mask,
//--------------------------------------------------------------
// Tonal curve parameters generated by CrtsTone()
float4 tone
//--------------------------------------------------------------
){
//--------------------------------------------------------------
#if (CRTS_DEBUG == 1)
float2 uv=ipos*rcpOutputSize;
// Show second half processed, and first half un-processed
if(uv.x<0.5)
{
// Force nearest to get squares
uv*=1.0/rcpInputSize;
uv=floor(uv)+float2(0.5,0.5);
uv*=rcpInputSize;
float3 color=CrtsFetch(uv);
return color;
}
#endif
float2 pos;
float vin;
if (CRTS_WARP){
// Convert to {-1 to 1} range
pos=ipos*twoDivOutputSize-float2(1.0,1.0);
// Distort pushes image outside {-1 to 1} range
pos*=float2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
// TODO: Vignette needs optimization
vin=1.0-((1.0-saturate(pos.x*pos.x))*(1.0-saturate(pos.y*pos.y)));
vin=saturate((-vin)*inputHeight+inputHeight);
// Leave in {0 to inputSize}
pos=pos*halfInputSize+halfInputSize;
} else {
pos=ipos*inputSizeDivOutputSize;
}
// Snap to center of first scanline
float y0=floor(pos.y-0.5)+0.5;
#if (CRTS_2_TAP == 1)
// Using Inigo's "Improved Texture Interpolation"
// http://iquilezles.org/www/articles/texture/texture.htm
pos.x+=0.5;
float xi=floor(pos.x);
float xf=pos.x-xi;
xf=xf*xf*xf*(xf*(xf*6.0-15.0)+10.0);
float x0=xi+xf-0.5;
float2 p=float2(x0*rcpInputSize.x,y0*rcpInputSize.y);
// Coordinate adjusted bilinear fetch from 2 nearest scanlines
float3 colA=CrtsFetch(p);
p.y+=rcpInputSize.y;
float3 colB=CrtsFetch(p);
#else
// Snap to center of one of four pixels
float x0=floor(pos.x-1.5)+0.5;
// Inital UV position
float2 p=float2(x0*rcpInputSize.x,y0*rcpInputSize.y);
// Fetch 4 nearest texels from 2 nearest scanlines
float3 colA0=CrtsFetch(p);
p.x+=rcpInputSize.x;
float3 colA1=CrtsFetch(p);
p.x+=rcpInputSize.x;
float3 colA2=CrtsFetch(p);
p.x+=rcpInputSize.x;
float3 colA3=CrtsFetch(p);
p.y+=rcpInputSize.y;
float3 colB3=CrtsFetch(p);
p.x-=rcpInputSize.x;
float3 colB2=CrtsFetch(p);
p.x-=rcpInputSize.x;
float3 colB1=CrtsFetch(p);
p.x-=rcpInputSize.x;
float3 colB0=CrtsFetch(p);
#endif
// Vertical filter
// Scanline intensity is using sine wave
// Easy filter window and integral used later in exposure
float off=pos.y-y0;
float pi2=6.28318530717958;
float hlf=0.5;
float scanA=cos(min(0.5, off *thin )*pi2)*hlf+hlf;
float scanB=cos(min(0.5,(-off)*thin+thin)*pi2)*hlf+hlf;
#if (CRTS_2_TAP == 1)
if (CRTS_WARP){
// Get rid of wrong pixels on edge
scanA*=vin;
scanB*=vin;
}
// Apply vertical filter
float3 color=(colA*scanA)+(colB*scanB);
#else
// Horizontal kernel is simple gaussian filter
float off0=pos.x-x0;
float off1=off0-1.0;
float off2=off0-2.0;
float off3=off0-3.0;
float pix0=exp2(blur*off0*off0);
float pix1=exp2(blur*off1*off1);
float pix2=exp2(blur*off2*off2);
float pix3=exp2(blur*off3*off3);
float pixT=rcp(pix0+pix1+pix2+pix3);
if (CRTS_WARP){
// Get rid of wrong pixels on edge
pixT*=vin;
}
scanA*=pixT;
scanB*=pixT;
// Apply horizontal and vertical filters
float3 color=
(colA0*pix0+colA1*pix1+colA2*pix2+colA3*pix3)*scanA +
(colB0*pix0+colB1*pix1+colB2*pix2+colB3*pix3)*scanB;
#endif
// Apply phosphor mask
color*=CrtsMask(ipos,mask);
// Optional color processing
if (CRTS_TONE){
// Tonal control, start by protecting from /0
float peak=max(1.0/(256.0*65536.0),max(color.r,max(color.g,color.b)));
// Compute the ratios of {R,G,B}
float3 ratio=color*rcp(peak);
// Apply tonal curve to peak value
if (CRTS_CONTRAST){
peak=pow(peak,tone.x);
}
peak=peak*rcp(peak*tone.y+tone.z);
// Apply saturation
if (CRTS_SATURATION){
ratio=pow(ratio,float3(tone.w,tone.w,tone.w));
}
// Reconstruct color
return ratio*peak;
} else {
return color;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PS_CRTLottes2018(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0)
{
color = tex2D(ReShade::BackBuffer, texcoord.xy);
color.rgb=CrtsFilter(
vpos.xy,
float2(INPUT_X,INPUT_Y)/ReShade::ScreenSize.xy,
float2(INPUT_X,INPUT_Y)*0.5,
1.0/float2(INPUT_X,INPUT_Y),
1.0/ReShade::ScreenSize.xy,
2.0/ReShade::ScreenSize.xy,
INPUT_Y,
float2(1.0/CRTS_WARP_X,1.0/CRTS_WARP_Y),
INPUT_THIN,
INPUT_BLUR,
INPUT_MASK,
CrtsTone(1.0,0.0,INPUT_THIN,INPUT_MASK));
ToSRGB(color.rgb);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
technique CRTLottes2018
{
pass
{
VertexShader = PostProcessVS;
PixelShader = PS_CRTLottes2018;
}
}

View file

@ -0,0 +1,149 @@
/**
* Film Grain post-process shader v1.1
* Martins Upitis (martinsh) devlog-martinsh.blogspot.com 2013
*
* This work is licensed under a Creative Commons Attribution 3.0 Unported License.
* So you are free to share, modify and adapt it for your needs, and even use it for commercial use.
*
* Uses perlin noise shader by toneburst from http://machinesdontcare.wordpress.com/2009/06/25/3d-perlin-noise-sphere-vertex-shader-sourcecode/
*/
#include "ReShadeUI.fxh"
uniform float grainamount < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 0.2;
ui_label = "Amount";
> = 0.05;
uniform float coloramount < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_label = "Color Amount";
> = 0.6;
uniform float lumamount < __UNIFORM_SLIDER_FLOAT1
ui_min = 0.0; ui_max = 1.0;
ui_label = "Luminance Amount";
> = 1.0;
uniform float grainsize < __UNIFORM_SLIDER_FLOAT1
ui_min = 1.5; ui_max = 2.5;
ui_label = "Grain Particle Size";
> = 1.6;
#include "ReShade.fxh"
uniform float timer < source = "timer"; >;
float4 rnm(in float2 tc)
{
// A random texture generator, but you can also use a pre-computed perturbation texture
float noise = sin(dot(tc, float2(12.9898, 78.233))) * 43758.5453;
float noiseR = frac(noise) * 2.0 - 1.0;
float noiseG = frac(noise * 1.2154) * 2.0 - 1.0;
float noiseB = frac(noise * 1.3453) * 2.0 - 1.0;
float noiseA = frac(noise * 1.3647) * 2.0 - 1.0;
return float4(noiseR, noiseG, noiseB, noiseA);
}
float pnoise3D(in float3 p)
{
// Perm texture texel-size
static const float permTexUnit = 1.0 / 256.0;
// Half perm texture texel-size
static const float permTexUnitHalf = 0.5 / 256.0;
// Integer part
// Scaled so +1 moves permTexUnit texel and offset 1/2 texel to sample texel centers
float3 pi = permTexUnit * floor(p) + permTexUnitHalf;
// Fractional part for interpolation
float3 pf = frac(p);
// Noise contributions from (x=0, y=0), z=0 and z=1
float perm00 = rnm(pi.xy).a;
float3 grad000 = rnm(float2(perm00, pi.z)).rgb * 4.0 - 1.0;
float n000 = dot(grad000, pf);
float3 grad001 = rnm(float2(perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n001 = dot(grad001, pf - float3(0.0, 0.0, 1.0));
// Noise contributions from (x=0, y=1), z=0 and z=1
float perm01 = rnm(pi.xy + float2(0.0, permTexUnit)).a;
float3 grad010 = rnm(float2(perm01, pi.z)).rgb * 4.0 - 1.0;
float n010 = dot(grad010, pf - float3(0.0, 1.0, 0.0));
float3 grad011 = rnm(float2(perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n011 = dot(grad011, pf - float3(0.0, 1.0, 1.0));
// Noise contributions from (x=1, y=0), z=0 and z=1
float perm10 = rnm(pi.xy + float2(permTexUnit, 0.0)).a;
float3 grad100 = rnm(float2(perm10, pi.z)).rgb * 4.0 - 1.0;
float n100 = dot(grad100, pf - float3(1.0, 0.0, 0.0));
float3 grad101 = rnm(float2(perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n101 = dot(grad101, pf - float3(1.0, 0.0, 1.0));
// Noise contributions from (x=1, y=1), z=0 and z=1
float perm11 = rnm(pi.xy + float2(permTexUnit, permTexUnit)).a;
float3 grad110 = rnm(float2(perm11, pi.z)).rgb * 4.0 - 1.0;
float n110 = dot(grad110, pf - float3(1.0, 1.0, 0.0));
float3 grad111 = rnm(float2(perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0;
float n111 = dot(grad111, pf - float3(1.0, 1.0, 1.0));
// Blend contributions along x
float fade_x = pf.x * pf.x * pf.x * (pf.x * (pf.x * 6.0 - 15.0) + 10.0);
float4 n_x = lerp(float4(n000, n001, n010, n011), float4(n100, n101, n110, n111), fade_x);
// Blend contributions along y
float fade_y = pf.y * pf.y * pf.y * (pf.y * (pf.y * 6.0 - 15.0) + 10.0);
float2 n_xy = lerp(n_x.xy, n_x.zw, fade_y);
// Blend contributions along z
float fade_z = pf.z * pf.z * pf.z * (pf.z * (pf.z * 6.0 - 15.0) + 10.0);
float n_xyz = lerp(n_xy.x, n_xy.y, fade_z);
// We're done, return the final noise value.
return n_xyz;
}
float2 coordRot(in float2 tc, in float angle)
{
float rotX = ((tc.x * 2.0 - 1.0) * BUFFER_ASPECT_RATIO * cos(angle)) - ((tc.y * 2.0 - 1.0) * sin(angle));
float rotY = ((tc.y * 2.0 - 1.0) * cos(angle)) + ((tc.x * 2.0 - 1.0) * BUFFER_ASPECT_RATIO * sin(angle));
rotX = ((rotX / BUFFER_ASPECT_RATIO) * 0.5 + 0.5);
rotY = rotY * 0.5 + 0.5;
return float2(rotX, rotY);
}
float4 main(float4 vpos : SV_Position, float2 texCoord : TexCoord) : SV_Target
{
float3 rotOffset = float3(1.425, 3.892, 5.835); // Rotation offset values
float2 rotCoordsR = coordRot(texCoord, timer + rotOffset.x);
float3 noise = pnoise3D(float3(rotCoordsR * BUFFER_SCREEN_SIZE / grainsize, 0.0)).xxx;
if (coloramount > 0)
{
float2 rotCoordsG = coordRot(texCoord, timer + rotOffset.y);
float2 rotCoordsB = coordRot(texCoord, timer + rotOffset.z);
noise.g = lerp(noise.r, pnoise3D(float3(rotCoordsG * BUFFER_SCREEN_SIZE / grainsize, 1.0)), coloramount);
noise.b = lerp(noise.r, pnoise3D(float3(rotCoordsB * BUFFER_SCREEN_SIZE / grainsize, 2.0)), coloramount);
}
float3 col = tex2D(ReShade::BackBuffer, texCoord).rgb;
const float3 lumcoeff = float3(0.299, 0.587, 0.114);
float luminance = lerp(0.0, dot(col, lumcoeff), lumamount);
float lum = smoothstep(0.2, 0.0, luminance);
lum += luminance;
noise = lerp(noise, 0.0, pow(lum, 4.0));
col = col + noise * grainamount;
return float4(col, 1.0);
}
technique FilmGrain2
{
pass
{
VertexShader = PostProcessVS;
PixelShader = main;
}
}

View file

@ -0,0 +1,77 @@
/*
Scanlines Sine Absolute Value
An ultra light scanline shader
by RiskyJumps
license: public domain
*/
#include "ReShade.fxh"
uniform float texture_sizeY <
ui_type = "drag";
ui_min = 1.0;
ui_max = BUFFER_HEIGHT;
ui_label = "Scanlines Height [Scanlines-Absolute]";
> = 240.0;
uniform float amp <
ui_type = "drag";
ui_min = 0.0;
ui_max = 2.0;
ui_step = 0.05;
ui_label = "Amplitude [Scanlines-Absolute]";
> = 1.25;
uniform float phase <
ui_type = "drag";
ui_min = 0.0;
ui_max = 2.0;
ui_step = 0.05;
ui_label = "Phase [Scanlines-Absolute]";
> = 0.0;
uniform float lines_black <
ui_type = "drag";
ui_min = 0.0;
ui_max = 1.0;
ui_step = 0.05;
ui_label = "Lines Blacks [Scanlines-Absolute]";
> = 0.0;
uniform float lines_white <
ui_type = "drag";
ui_min = 0.0;
ui_max = 2.0;
ui_step = 0.05;
ui_label = "Lines Whites [Scanlines-Absolute]";
> = 1.0;
#define freq 0.500000
#define offset 0.000000
#define pi 3.141592654
float4 PS_ScanlinesAbs(float4 pos : SV_POSITION, float2 tex : TEXCOORD0) : SV_TARGET
{
float3 color = tex2D(ReShade::BackBuffer, tex).xyz;
float grid;
float lines;
float omega = 2.0 * pi * freq; // Angular frequency
float angle = tex.y * omega * texture_sizeY + phase;
lines = sin(angle);
lines *= amp;
lines += offset;
lines = abs(lines) * (lines_white - lines_black) + lines_black;
color *= lines;
return color.xyzz;
}
technique ScanlinesAbs {
pass ScanlinesAbsolute{
VertexShader = PostProcessVS;
PixelShader = PS_ScanlinesAbs;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

View file

@ -1 +1,2 @@
https://github.com/crosire/reshade-shaders
https://github.com/crosire/reshade-shaders
https://github.com/Matsilagi/RSRetroArch/

View file

@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<h3>cubeb - <a href="https://github.com/mozilla/cubeb">https://github.com/mozilla/cubeb</a></h3>
<pre>
Copyright © 2011 Mozilla Foundation
Copyright 2011 Mozilla Foundation
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -1624,7 +1624,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The MIT License (MIT)
Copyright (c) 2014-2021 Florian Bernd
Copyright (c) 2014-2021 Joel Höner
Copyright (c) 2014-2021 Joel H ner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -1645,5 +1645,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</pre>
Some shaders provided with the application are sourced from <a href="https://github.com/Matsilagi/RSRetroArch/">https://github.com/Matsilagi/RSRetroArch/</a>.<br>
License details are included in the relevant shader source files, under resources\shaders\reshade.
</body>
</html>