-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter-240p-resize.effect.hlsl
164 lines (149 loc) · 5.35 KB
/
filter-240p-resize.effect.hlsl
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
// Size of the source picture
uniform int source_width;
uniform int source_height;
uniform int target_width;
uniform int target_height;
// OBS-specific syntax adaptation to HLSL standard to avoid errors reported by the code editor
#define SamplerState sampler_state
#define Texture2D texture2d
// Uniform variables set by OBS (required)
uniform float4x4 ViewProj; // View-projection matrix used in the vertex shader
uniform Texture2D image; // Texture containing the source picture
// Data type of the input of the vertex shader
struct vertex_data
{
float4 pos : POSITION; // Homogeneous space coordinates XYZW
float2 uv : TEXCOORD0; // UV coordinates in the source picture
};
// Data type of the output returned by the vertex shader, and used as input
// for the pixel shader after interpolation for each pixel
struct pixel_data
{
float4 pos : POSITION; // Homogeneous screen coordinates XYZW
float2 uv : TEXCOORD0; // UV coordinates in the source picture
};
// Vertex shader used to compute position of rendered pixels and pass UV
pixel_data vertex_shader_240p_resize(vertex_data vertex)
{
pixel_data pixel;
pixel.pos = mul(float4(vertex.pos.xyz, 1.0), ViewProj);
pixel.uv = vertex.uv;
return pixel;
}
// Get the coefficients for this mapped X or Y value
int4 get_coeffs(float mapped)
{
static const int COEFFS_LENGTH = 64;
// Scaling coefficients from 'Interpolation (Sharp).txt' in https://github.com/MiSTer-devel/Filters_MiSTer
static const int4 coeffs[COEFFS_LENGTH] = {
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 128, 0, 0),
int4(0, 127, 1, 0),
int4(0, 127, 1, 0),
int4(0, 127, 1, 0),
int4(0, 127, 1, 0),
int4(0, 126, 2, 0),
int4(0, 125, 3, 0),
int4(0, 124, 4, 0),
int4(0, 123, 5, 0),
int4(0, 121, 7, 0),
int4(0, 119, 9, 0),
int4(0, 116, 12, 0),
int4(0, 112, 16, 0),
int4(0, 107, 21, 0),
int4(0, 100, 28, 0),
int4(0, 93, 35, 0),
int4(0, 84, 44, 0),
int4(0, 74, 54, 0),
int4(0, 64, 64, 0),
int4(0, 54, 74, 0),
int4(0, 44, 84, 0),
int4(0, 35, 93, 0),
int4(0, 28, 100, 0),
int4(0, 21, 107, 0),
int4(0, 16, 112, 0),
int4(0, 12, 116, 0),
int4(0, 9, 119, 0),
int4(0, 7, 121, 0),
int4(0, 5, 123, 0),
int4(0, 4, 124, 0),
int4(0, 3, 125, 0),
int4(0, 2, 126, 0),
int4(0, 1, 127, 0),
int4(0, 1, 127, 0),
int4(0, 1, 127, 0),
int4(0, 1, 127, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0),
int4(0, 0, 128, 0)
};
float phase = COEFFS_LENGTH * ((mapped + 0.5) % 1);
int4 coeff = coeffs[int(phase)];
return coeff;
}
// Pixel shader used to compute an RGBA color at a given pixel position
float4 pixel_shader_240p_resize(pixel_data pixel) : TARGET
{
// Swap width/height/x/y if scaling vertically
bool vertical = target_width == source_width;
int width = vertical ? source_height : source_width;
int height = vertical ? target_width : source_height;
float x = vertical ? pixel.uv.y : pixel.uv.x;
float y = vertical ? pixel.uv.x : pixel.uv.y;
// The output UV position mapped onto the original source image
float mapped_x = x * width;
int mapped_y = y * height;
// Get scaling coefficients for this pixel
int4 coeffs = get_coeffs(mapped_x);
// 2 taps per phase, 64 phases
int taps[2] = {
mapped_x - 0.5,
mapped_x + 0.5
};
// Clamp the tap values to be within the source dimensions
if (taps[0] < 0) taps[0] = 0;
if (taps[1] >= width) taps[1] = width - 1;
// Grab the pixel for each tap from the source image
float4 pixels[2] = {
image.Load(vertical ? int3(mapped_y, taps[0], 0) : int3(taps[0], mapped_y, 0)),
image.Load(vertical ? int3(mapped_y, taps[1], 0) : int3(taps[1], mapped_y, 0))
};
// Weigh the colours from each source pixel based on the coefficients for this phase to generate the result colour for this rendered pixel
float r = (pixels[0].r * coeffs.y + pixels[1].r * coeffs.z) / 128;
float g = (pixels[0].g * coeffs.y + pixels[1].g * coeffs.z) / 128;
float b = (pixels[0].b * coeffs.y + pixels[1].b * coeffs.z) / 128;
// Return result colour for this pixel
return float4(r, g, b, 1);
}
technique Draw
{
pass
{
vertex_shader = vertex_shader_240p_resize(vertex);
pixel_shader = pixel_shader_240p_resize(pixel);
}
}