5
A flat CRT shader ideally for 1080p or higher displays.
17
Example RGB Mask Parameter Settings:
19
Aperture Grille (Default)
32
uniform float texture_sizeX <
35
ui_max = BUFFER_WIDTH;
36
ui_label = "Screen Width [CRT-Easymode]";
39
uniform float texture_sizeY <
42
ui_max = BUFFER_HEIGHT;
43
ui_label = "Screen Height [CRT-Easymode]";
46
uniform float video_sizeX <
49
ui_max = BUFFER_WIDTH;
50
ui_label = "Frame Width [CRT-cgwg]";
51
ui_tooltip = "This should be sized according to the video data in the texture (If you're using emulators, set this to the Emu video frame size, otherwise, keep it the same as Screen Width/Height or Fullscreen res.)";
54
uniform float video_sizeY <
57
ui_max = BUFFER_HEIGHT;
58
ui_label = "Frame Height [CRT-cgwg]";
59
ui_tooltip = "This should be sized according to the video data in the texture (If you're using emulators, set this to the Emu video frame size, otherwise, keep it the same as Screen Width/Height or Fullscreen res.)";
62
uniform float SHARPNESS_H <
67
ui_label = "Sharpness Horizontal [CRT-Easymode]";
70
uniform float SHARPNESS_V <
75
ui_label = "Sharpness Vertical [CRT-Easymode]";
78
uniform float MASK_STRENGTH <
83
ui_label = "Mask Strength [CRT-Easymode]";
86
uniform float MASK_DOT_WIDTH <
91
ui_label = "Mask Dot Width [CRT-Easymode]";
94
uniform float MASK_DOT_HEIGHT <
99
ui_label = "Mask Dot Height [CRT-Easymode]";
102
uniform float MASK_STAGGER <
107
ui_label = "Mask Stagger [CRT-Easymode]";
110
uniform float MASK_SIZE <
115
ui_label = "Mask Size [CRT-Easymode]";
118
uniform float SCANLINE_STRENGTH <
123
ui_label = "Scanline Strength [CRT-Easymode]";
126
uniform float SCANLINE_BEAM_WIDTH_MIN <
131
ui_label = "Scanline Beam Width M [CRT-Easymode]";
134
uniform float SCANLINE_BEAM_WIDTH_MAX <
139
ui_label = "Scanline Beam Width Max. [CRT-Easymode]";
142
uniform float SCANLINE_BRIGHT_MIN <
147
ui_label = "Scanline Brightness M [CRT-Easymode]";
150
uniform float SCANLINE_BRIGHT_MAX <
155
ui_label = "Scanline Brightness Max. [CRT-Easymode]";
158
uniform float SCANLINE_CUTOFF <
163
ui_label = "Scanline Cutoff [CRT-Easymode]";
166
uniform float GAMMA_INPUT <
171
ui_label = "Gamma Input [CRT-Easymode]";
174
uniform float GAMMA_OUTPUT <
179
ui_label = "Gamma Output [CRT-Easymode]";
182
uniform float BRIGHT_BOOST <
187
ui_label = "Brightness Boost [CRT-Easymode]";
190
uniform int DILATION <
195
ui_label = "Dilation [CRT-Easymode]";
198
#define mod(x,y) (x-y*floor(x/y))
200
#define FIX(c) max(abs(c), 1e-5)
201
#define PI 3.141592653589
202
#define TEX2D(c) dilate(tex2D(ReShade::BackBuffer, c))
203
#define TEX2D_OGL(c) pow(dilate(tex2D(tex, c)).rgb, 1.0)
204
#define texture_size float2(texture_sizeX, texture_sizeY)
205
#define video_size float2(video_sizeX, video_sizeY)
207
uniform bool ENABLE_LANCZOS <
209
ui_label = "Enable Lanczos [CRT-Easymode]";
212
float4 dilate(float4 col)
214
float4 x = lerp(float4(1.0,1.0,1.0,1.0), col, DILATION);
219
float curve_distance(float x, float sharp)
223
apply half-circle s-curve to distance for sharper (more pixelated) interpolation
224
single line formula for Graph Toy:
225
0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x)
228
float x_step = step(0.5, x);
229
float curve = 0.5 - sqrt(0.25 - (x - x_step) * (x - x_step)) * sign(0.5 - x);
231
return lerp(x, curve, sharp);
234
float4x4 get_color_matrix(sampler2D tex, float2 co, float2 dx)
236
return float4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
239
float3 filter_lanczos(float4 coeffs, float4x4 color_matrix)
241
float4 col = mul(coeffs, color_matrix);
242
float4 sample_min = min(color_matrix[1], color_matrix[2]);
243
float4 sample_max = max(color_matrix[1], color_matrix[2]);
245
col = clamp(col, sample_min, sample_max);
250
float3 filter_lanczos_ogl(sampler2D tex, float2 co, float2 tex_size)
252
float2 dx = float2(1.0 / tex_size.x, 0.0);
253
float2 pix_co = co * tex_size - float2(0.5, 0.0);
254
float2 tex_co = (floor(pix_co) + float2(0.5, 0.0)) / tex_size;
255
float2 dist = frac(pix_co);
256
float4 coef = PI * float4(dist.x + 1.0, dist.x, dist.x - 1.0, dist.x - 2.0);
259
coef = 2.0 * sin(coef) * sin(coef / 2.0) / (coef * coef);
260
coef /= dot(coef, float4(1.0,1.0,1.0,1.0));
262
float4 col1 = float4(TEX2D_OGL(tex_co), 1.0);
263
float4 col2 = float4(TEX2D_OGL(tex_co + dx), 1.0);
265
return mul(coef, float4x4(col1, col1, col2, col2)).rgb;
268
float4 PS_CRTEasymode(float4 vpos : SV_Position, float2 coords : TexCoord) : SV_Target
270
float2 dx = float2(1.0 / texture_size.x, 0.0);
271
float2 dy = float2(0.0, 1.0 / texture_size.y);
272
float2 pix_co = coords * texture_size - float2(0.5, 0.5);
273
float2 tex_co = (floor(pix_co) + float2(0.5, 0.5)) / texture_size;
274
float2 dist = frac(pix_co);
279
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
281
float4 coeffs = PI * float4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
283
coeffs = FIX(coeffs);
284
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
285
coeffs /= dot(coeffs, float4(1.0,1.0,1.0,1.0));
286
if (__RENDERER__ >= 0x10000 || __RENDERER__ == 0x0B100 || __RENDERER__ == 0x0A100){ //OGL and DX10/11 fix
287
col = filter_lanczos_ogl(ReShade::BackBuffer, coords, texture_size).rgb;
288
col2 = filter_lanczos_ogl(ReShade::BackBuffer, coords, texture_size).rgb;
290
col = filter_lanczos(coeffs, get_color_matrix(ReShade::BackBuffer, tex_co, dx));
291
col2 = filter_lanczos(coeffs, get_color_matrix(ReShade::BackBuffer, tex_co + dy, dx));
294
curve_x = curve_distance(dist.x, SHARPNESS_H);
296
col = lerp(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
297
col2 = lerp(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
300
col = lerp(col, col2, curve_distance(dist.y, SHARPNESS_V));
301
col = pow(col, float3(GAMMA_INPUT / (DILATION + 1.0),GAMMA_INPUT / (DILATION + 1.0),GAMMA_INPUT / (DILATION + 1.0)));
303
float luma = dot(float3(0.2126, 0.7152, 0.0722), col);
304
float bright = (max(col.r, max(col.g, col.b)) + luma) / 2.0;
305
float scan_bright = clamp(bright, SCANLINE_BRIGHT_MIN, SCANLINE_BRIGHT_MAX);
306
float scan_beam = clamp(bright * SCANLINE_BEAM_WIDTH_MAX, SCANLINE_BEAM_WIDTH_MIN, SCANLINE_BEAM_WIDTH_MAX);
307
float scan_weight = 1.0 - pow(cos(coords.y * 2.0 * PI * texture_size.y) * 0.5 + 0.5, scan_beam) * SCANLINE_STRENGTH;
309
float mask = 1.0 - MASK_STRENGTH;
310
float2 mod_fac = floor(coords * ReShade::ScreenSize * texture_size / (video_size * float2(MASK_SIZE, MASK_DOT_HEIGHT * MASK_SIZE)));
311
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * MASK_STAGGER) / MASK_DOT_WIDTH, 3.0));
314
if (dot_no == 0) mask_weight = float3(1.0, mask, mask);
315
else if (dot_no == 1) mask_weight = float3(mask, 1.0, mask);
316
else mask_weight = float3(mask, mask, 1.0);
318
if (video_size.y >= SCANLINE_CUTOFF) scan_weight = 1.0;
321
col *= float3(scan_weight,scan_weight,scan_weight);
322
col = lerp(col, col2, scan_bright);
324
col = pow(col, float3(1.0 / GAMMA_OUTPUT,1.0 / GAMMA_OUTPUT,1.0 / GAMMA_OUTPUT));
326
return float4(col * BRIGHT_BOOST, 1.0);
329
technique EasymodeCRT {
331
VertexShader=PostProcessVS;
332
PixelShader=PS_CRTEasymode;