-
Notifications
You must be signed in to change notification settings - Fork 257
/
Copy pathcrt-easymode.cg
220 lines (182 loc) · 6.8 KB
/
crt-easymode.cg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
CRT Shader by EasyMode
License: GPL
A flat CRT shader ideally for 1080p or higher displays.
Recommended Settings:
Video
- Aspect Ratio: 4:3
- Integer Scale: Off
Shader
- Filter: Nearest
- Scale: Don't Care
Example RGB Mask Parameter Settings:
Aperture Grille (Default)
- Dot Width: 1
- Dot Height: 1
- Stagger: 0
Lottes' Shadow Mask
- Dot Width: 2
- Dot Height: 1
- Stagger: 3
*/
#pragma parameter SHARPNESS_H "Sharpness Horizontal" 0.5 0.0 1.0 0.05
#pragma parameter SHARPNESS_V "Sharpness Vertical" 1.0 0.0 1.0 0.05
#pragma parameter MASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.01
#pragma parameter MASK_DOT_WIDTH "Mask Dot Width" 1.0 1.0 100.0 1.0
#pragma parameter MASK_DOT_HEIGHT "Mask Dot Height" 1.0 1.0 100.0 1.0
#pragma parameter MASK_STAGGER "Mask Stagger" 0.0 0.0 100.0 1.0
#pragma parameter MASK_SIZE "Mask Size" 1.0 1.0 100.0 1.0
#pragma parameter SCANLINE_STRENGTH "Scanline Strength" 1.0 0.0 1.0 0.05
#pragma parameter SCANLINE_BEAM_WIDTH_MIN "Scanline Beam Width Min." 1.5 0.5 5.0 0.5
#pragma parameter SCANLINE_BEAM_WIDTH_MAX "Scanline Beam Width Max." 1.5 0.5 5.0 0.5
#pragma parameter SCANLINE_BRIGHT_MIN "Scanline Brightness Min." 0.35 0.0 1.0 0.05
#pragma parameter SCANLINE_BRIGHT_MAX "Scanline Brightness Max." 0.65 0.0 1.0 0.05
#pragma parameter SCANLINE_CUTOFF "Scanline Cutoff" 400.0 1.0 1000.0 1.0
#pragma parameter GAMMA_INPUT "Gamma Input" 2.0 0.1 5.0 0.1
#pragma parameter GAMMA_OUTPUT "Gamma Output" 1.8 0.1 5.0 0.1
#pragma parameter BRIGHT_BOOST "Brightness Boost" 1.2 1.0 2.0 0.01
#pragma parameter DILATION "Dilation" 1.0 0.0 1.0 1.0
#ifdef PARAMETER_UNIFORM
uniform float BRIGHT_BOOST;
uniform float DILATION;
uniform float GAMMA_INPUT;
uniform float GAMMA_OUTPUT;
uniform float MASK_SIZE;
uniform float MASK_STAGGER;
uniform float MASK_STRENGTH;
uniform float MASK_DOT_HEIGHT;
uniform float MASK_DOT_WIDTH;
uniform float SCANLINE_CUTOFF;
uniform float SCANLINE_BEAM_WIDTH_MAX;
uniform float SCANLINE_BEAM_WIDTH_MIN;
uniform float SCANLINE_BRIGHT_MAX;
uniform float SCANLINE_BRIGHT_MIN;
uniform float SCANLINE_STRENGTH;
uniform float SHARPNESS_H;
uniform float SHARPNESS_V;
#else
#define BRIGHT_BOOST 1.2
#define DILATION 1.0
#define GAMMA_INPUT 2.0
#define GAMMA_OUTPUT 1.8
#define MASK_SIZE 1.0
#define MASK_STAGGER 0.0
#define MASK_STRENGTH 0.3
#define MASK_DOT_HEIGHT 1.0
#define MASK_DOT_WIDTH 1.0
#define SCANLINE_BEAM_WIDTH_MAX 1.5
#define SCANLINE_BEAM_WIDTH_MIN 1.5
#define SCANLINE_BRIGHT_MAX 0.65
#define SCANLINE_BRIGHT_MIN 0.35
#define SCANLINE_CUTOFF 400.0
#define SCANLINE_STRENGTH 1.0
#define SHARPNESS_H 0.5
#define SHARPNESS_V 1.0
#endif
#include "../../compat_includes.inc"
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;
#define FIX(c) max(abs(c), 1e-5)
#define PI 3.141592653589
#define TEX2D(c) dilate(COMPAT_SamplePoint(tex, c))
#define mod(x,y) (x - y * trunc(x/y))
// Set to 0 to use linear filter and gain speed
#define ENABLE_LANCZOS 1
struct out_vertex
{
float4 position : COMPAT_POS;
float2 texCoord : TEXCOORD0;
#ifndef HLSL_4
float4 Color : COLOR;
#endif
};
out_vertex main_vertex(COMPAT_IN_VERTEX)
{
out_vertex OUT;
#ifdef HLSL_4
float4 position = VIN.position;
float2 texCoord = VIN.texCoord;
#else
OUT.Color = color;
#endif
OUT.position = mul(modelViewProj, position);
OUT.texCoord = texCoord;
return OUT;
}
float4 dilate(float4 col)
{
float4 x = lerp(float4(1.0), col, DILATION);
return col * x;
}
float curve_distance(float x, float sharp)
{
/*
apply half-circle s-curve to distance for sharper (more pixelated) interpolation
single line formula for Graph Toy:
0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x)
*/
float x_step = step(0.5, x);
float curve = 0.5 - sqrt(0.25 - (x - x_step) * (x - x_step)) * sign(0.5 - x);
return lerp(x, curve, sharp);
}
float4x4 get_color_matrix(sampler2D tex, float2 co, float2 dx)
{
return float4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx));
}
float3 filter_lanczos(float4 coeffs, float4x4 color_matrix)
{
float4 col = mul(coeffs, color_matrix);
float4 sample_min = min(color_matrix[1], color_matrix[2]);
float4 sample_max = max(color_matrix[1], color_matrix[2]);
col = clamp(col, sample_min, sample_max);
return col.rgb;
}
float4 crt_easymode(float2 texture_size, float2 video_size, float2 output_size, float2 coords, COMPAT_Texture2D(tex))
{
float2 dx = float2(1.0 / texture_size.x, 0.0);
float2 dy = float2(0.0, 1.0 / texture_size.y);
float2 pix_co = coords * texture_size - float2(0.5, 0.5);
float2 tex_co = (floor(pix_co) + float2(0.5, 0.5)) / texture_size;
float2 dist = frac(pix_co);
float curve_x;
float3 col, col2;
#if ENABLE_LANCZOS
curve_x = curve_distance(dist.x, SHARPNESS_H * SHARPNESS_H);
float4 coeffs = PI * float4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x);
coeffs = FIX(coeffs);
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
coeffs /= dot(coeffs, float4(1.0));
col = filter_lanczos(coeffs, get_color_matrix(tex, tex_co, dx));
col2 = filter_lanczos(coeffs, get_color_matrix(tex, tex_co + dy, dx));
#else
curve_x = curve_distance(dist.x, SHARPNESS_H);
col = lerp(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x);
col2 = lerp(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x);
#endif
col = lerp(col, col2, curve_distance(dist.y, SHARPNESS_V));
col = pow(col, float3(GAMMA_INPUT / (DILATION + 1.0)));
float luma = dot(float3(0.2126, 0.7152, 0.0722), col);
float bright = (max(col.r, max(col.g, col.b)) + luma) / 2.0;
float scan_bright = clamp(bright, SCANLINE_BRIGHT_MIN, SCANLINE_BRIGHT_MAX);
float scan_beam = clamp(bright * SCANLINE_BEAM_WIDTH_MAX, SCANLINE_BEAM_WIDTH_MIN, SCANLINE_BEAM_WIDTH_MAX);
float scan_weight = 1.0 - pow(cos(coords.y * 2.0 * PI * texture_size.y) * 0.5 + 0.5, scan_beam) * SCANLINE_STRENGTH;
float mask = 1.0 - MASK_STRENGTH;
float2 mod_fac = floor(coords * output_size * texture_size / (video_size * float2(MASK_SIZE, MASK_DOT_HEIGHT * MASK_SIZE)));
int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * MASK_STAGGER) / MASK_DOT_WIDTH, 3.0));
float3 mask_weight;
if (dot_no == 0) mask_weight = float3(1.0, mask, mask);
else if (dot_no == 1) mask_weight = float3(mask, 1.0, mask);
else mask_weight = float3(mask, mask, 1.0);
if (video_size.y >= SCANLINE_CUTOFF) scan_weight = 1.0;
col2 = col.rgb;
col *= float3(scan_weight);
col = lerp(col, col2, scan_bright);
col *= mask_weight;
col = pow(col, float3(1.0 / GAMMA_OUTPUT));
return float4(col * BRIGHT_BOOST, 1.0);
}
float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
return crt_easymode(COMPAT_texture_size, COMPAT_video_size, COMPAT_output_size, VOUT.texCoord, decal);
}
COMPAT_END