ProjectArcade

Форк
0
334 строки · 8.9 Кб
1
/*
2
    CRT Shader by EasyMode
3
    License: GPL
4

5
    A flat CRT shader ideally for 1080p or higher displays.
6

7
    Recommended Settings:
8

9
    Video
10
    - Aspect Ratio: 4:3
11
    - Integer Scale: Off
12

13
    Shader
14
    - Filter: Nearest
15
    - Scale: Don't Care
16

17
    Example RGB Mask Parameter Settings:
18

19
    Aperture Grille (Default)
20
    - Dot Width: 1
21
    - Dot Height: 1
22
    - Stagger: 0
23

24
    Lottes' Shadow Mask
25
    - Dot Width: 2
26
    - Dot Height: 1
27
    - Stagger: 3
28
*/
29

30
#include "ReShade.fxh"
31

32
uniform float texture_sizeX <
33
	ui_type = "drag";
34
	ui_min = 1.0;
35
	ui_max = BUFFER_WIDTH;
36
	ui_label = "Screen Width [CRT-Easymode]";
37
> = 320.0;
38

39
uniform float texture_sizeY <
40
	ui_type = "drag";
41
	ui_min = 1.0;
42
	ui_max = BUFFER_HEIGHT;
43
	ui_label = "Screen Height [CRT-Easymode]";
44
> = 240.0;
45

46
uniform float video_sizeX <
47
	ui_type = "drag";
48
	ui_min = 1.0;
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.)";
52
> = 320.0;
53

54
uniform float video_sizeY <
55
	ui_type = "drag";
56
	ui_min = 1.0;
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.)";
60
> = 240.0;
61

62
uniform float SHARPNESS_H <
63
	ui_type = "drag";
64
	ui_min = 0.0;
65
	ui_max = 1.0;
66
	ui_step = 0.05;
67
	ui_label = "Sharpness Horizontal [CRT-Easymode]";
68
> = 0.5;
69

70
uniform float SHARPNESS_V <
71
	ui_type = "drag";
72
	ui_min = 0.0;
73
	ui_max = 1.0;
74
	ui_step = 0.05;
75
	ui_label = "Sharpness Vertical [CRT-Easymode]";
76
> = 1.0;
77

78
uniform float MASK_STRENGTH <
79
	ui_type = "drag";
80
	ui_min = 0.0;
81
	ui_max = 1.0;
82
	ui_step = 0.01;
83
	ui_label = "Mask Strength [CRT-Easymode]";
84
> = 0.3;
85

86
uniform float MASK_DOT_WIDTH <
87
	ui_type = "drag";
88
	ui_min = 1.0;
89
	ui_max = 100.0;
90
	ui_step = 1.0;
91
	ui_label = "Mask Dot Width [CRT-Easymode]";
92
> = 1.0;
93

94
uniform float MASK_DOT_HEIGHT <
95
	ui_type = "drag";
96
	ui_min = 1.0;
97
	ui_max = 100.0;
98
	ui_step = 1.0;
99
	ui_label = "Mask Dot Height [CRT-Easymode]";
100
> = 1.0;
101

102
uniform float MASK_STAGGER <
103
	ui_type = "drag";
104
	ui_min = 0.0;
105
	ui_max = 100.0;
106
	ui_step = 1.0;
107
	ui_label = "Mask Stagger [CRT-Easymode]"; 
108
> = 0.0;
109

110
uniform float MASK_SIZE <
111
	ui_type = "drag";
112
	ui_min = 1.0;
113
	ui_max = 100.0;
114
	ui_step = 1.0;
115
	ui_label = "Mask Size [CRT-Easymode]";
116
> = 1.0;
117

118
uniform float SCANLINE_STRENGTH <
119
	ui_type = "drag";
120
	ui_min = 0.0;
121
	ui_max = 1.0;
122
	ui_step = 0.05;
123
	ui_label = "Scanline Strength [CRT-Easymode]";
124
> = 1.0;
125

126
uniform float SCANLINE_BEAM_WIDTH_MIN <
127
	ui_type = "drag";
128
	ui_min = 0.5;
129
	ui_max = 5.0;
130
	ui_step = 0.5;
131
	ui_label = "Scanline Beam Width M [CRT-Easymode]";
132
> = 1.5;
133

134
uniform float SCANLINE_BEAM_WIDTH_MAX <
135
	ui_type = "drag";
136
	ui_min = 0.5;
137
	ui_max = 5.0;
138
	ui_step = 0.5;
139
	ui_label = "Scanline Beam Width Max. [CRT-Easymode]";
140
> = 1.5;
141

142
uniform float SCANLINE_BRIGHT_MIN <
143
	ui_type = "drag";
144
	ui_min = 0.0;
145
	ui_max = 1.0;
146
	ui_step = 0.05;
147
	ui_label = "Scanline Brightness M [CRT-Easymode]"; 
148
> = 0.35;
149

150
uniform float SCANLINE_BRIGHT_MAX <
151
	ui_type = "drag";
152
	ui_min = 0.0;
153
	ui_max = 1.0;
154
	ui_step = 0.05;
155
	ui_label = "Scanline Brightness Max. [CRT-Easymode]";
156
> = 0.65;
157

158
uniform float SCANLINE_CUTOFF <
159
	ui_type = "drag";
160
	ui_min = 1.0;
161
	ui_max = 1000.0;
162
	ui_step = 1.0;
163
	ui_label = "Scanline Cutoff [CRT-Easymode]";
164
> = 400.0;
165

166
uniform float GAMMA_INPUT <
167
	ui_type = "drag";
168
	ui_min = 0.1;
169
	ui_max = 5.0;
170
	ui_step = 0.1;
171
	ui_label = "Gamma Input [CRT-Easymode]";
172
> = 2.0;
173

174
uniform float GAMMA_OUTPUT <
175
	ui_type = "drag";
176
	ui_min = 0.1;
177
	ui_max = 5.0;
178
	ui_step = 0.1;
179
	ui_label = "Gamma Output [CRT-Easymode]";
180
> = 1.8;
181

182
uniform float BRIGHT_BOOST <
183
	ui_type = "drag";
184
	ui_min = 1.0;
185
	ui_max = 2.0;
186
	ui_step = 0.01;
187
	ui_label = "Brightness Boost [CRT-Easymode]";
188
> = 1.2;
189

190
uniform int DILATION <
191
	ui_type = "drag";
192
	ui_min = 0.0;
193
	ui_max = 1.0;
194
	ui_step = 1.0;
195
	ui_label = "Dilation [CRT-Easymode]";
196
> = 1.0;
197

198
#define mod(x,y) (x-y*floor(x/y))
199

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)
206

207
uniform bool ENABLE_LANCZOS <
208
	ui_type = "combo";
209
	ui_label = "Enable Lanczos [CRT-Easymode]";
210
> = true;
211

212
float4 dilate(float4 col)
213
{
214
    float4 x = lerp(float4(1.0,1.0,1.0,1.0), col, DILATION);
215

216
    return col * x;
217
}
218

219
float curve_distance(float x, float sharp)
220
{
221

222
/*
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)
226
*/
227

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

231
    return lerp(x, curve, sharp);
232
}
233

234
float4x4 get_color_matrix(sampler2D tex, float2 co, float2 dx)
235
{
236
    return float4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
237
}
238

239
float3 filter_lanczos(float4 coeffs, float4x4 color_matrix)
240
{
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]);
244

245
    col = clamp(col, sample_min, sample_max);
246

247
    return col.rgb;
248
}
249

250
float3 filter_lanczos_ogl(sampler2D tex, float2 co, float2 tex_size)
251
{
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);
257

258
    coef = FIX(coef);
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));
261

262
    float4 col1 = float4(TEX2D_OGL(tex_co), 1.0);
263
    float4 col2 = float4(TEX2D_OGL(tex_co + dx), 1.0);
264

265
    return mul(coef, float4x4(col1, col1, col2, col2)).rgb;
266
}
267

268
float4 PS_CRTEasymode(float4 vpos : SV_Position, float2 coords : TexCoord) : SV_Target
269
{
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);
275
    float curve_x;
276
    float3 col, col2;
277

278
	if(ENABLE_LANCZOS){
279
		curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
280

281
		float4 coeffs = PI * float4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
282

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;
289
		} else {
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));
292
		}	
293
	} else {
294
		curve_x = curve_distance(dist.x, SHARPNESS_H);
295

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

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

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;
308

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));
312
    float3 mask_weight;
313

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

318
    if (video_size.y >= SCANLINE_CUTOFF) scan_weight = 1.0;
319

320
    col2 = col.rgb;
321
    col *= float3(scan_weight,scan_weight,scan_weight);
322
    col = lerp(col, col2, scan_bright);
323
    col *= mask_weight;
324
    col = pow(col, float3(1.0 / GAMMA_OUTPUT,1.0 / GAMMA_OUTPUT,1.0 / GAMMA_OUTPUT));
325

326
    return float4(col * BRIGHT_BOOST, 1.0);
327
}
328

329
technique EasymodeCRT {
330
	pass CRT_Easymode {
331
		VertexShader=PostProcessVS;
332
		PixelShader=PS_CRTEasymode;
333
	}
334
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.