Deinterlace_base.pShader
6.1 KB
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
/********************************************************************************
Copyright (C) 2013 Ruwen Hahn <palana@stunned.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
uniform Texture2D diffuseTexture;
uniform Texture2D prevTex;
uniform bool field_order;
#define WEAVE 0
#define YADIF 1
#define BLEND 2
#define BLEND2x 3
#define LINEAR 4
#define LINEAR2x 5
#define DISCARD 6
#define DISCARD2x 7
int3 select(int2 texel, int x, int y)
{
return int3(texel+int2(x, y), 0);
}
float4 load_at(int2 texel, int x, int y, int field)
{
if(field == 0)
return diffuseTexture.Load(int3(texel+int2(x, y), 0));
else
return prevTex.Load(int3(texel+int2(x, y), 0));
}
/*
Port of YADIF filter from MPlayer
YADIF filter Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
*/
#define YADIF_UPDATE(c, level)\
if(score.c < spatial_score.c)\
{\
spatial_score.c = score.c;\
spatial_pred.c = (load_at(texel, level, -1, field) + load_at(texel, -level, 1, field)).c/2;\
#define YADIF_CHECK_ONE(level, c)\
{\
float4 score = abs(load_at(texel, -1+level, 1, field) - load_at(texel, -1-level, -1, field))+\
abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field))+\
abs(load_at(texel, 1+level, 1, field) - load_at(texel, 1-level, -1, field));\
YADIF_UPDATE(c, level) }\
}
#define YADIF_CHECK(level)\
{\
float4 score = abs(load_at(texel, -1+level, 1, field) - load_at(texel, -1-level, -1, field))+\
abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field))+\
abs(load_at(texel, 1+level, 1, field) - load_at(texel, 1-level, -1, field));\
YADIF_UPDATE(r, level) YADIF_CHECK_ONE(level*2, r) }\
YADIF_UPDATE(g, level) YADIF_CHECK_ONE(level*2, g) }\
YADIF_UPDATE(b, level) YADIF_CHECK_ONE(level*2, b) }\
YADIF_UPDATE(a, level) YADIF_CHECK_ONE(level*2, a) }\
}
float4 texel_at_yadif(int2 texel, int field)
{
Texture2D tex = diffuseTexture;
if((texel.y%2) == field)
return load_at(texel, 0, 0, field);
float4 b = (prevTex.Load(select(texel, 0, 2)) + tex.Load(select(texel, 0, 2)))/2,
c = load_at(texel, 0, 1, field),
d = (prevTex.Load(select(texel, 0, 0)) + tex.Load(select(texel, 0, 0)))/2,
e = load_at(texel, 0, -1, field),
f = (prevTex.Load(select(texel, 0, -2)) + tex.Load(select(texel, 0, -2)))/2;
float4 temporal_diff0 = (abs(prevTex.Load(select(texel, 0, 0)) - tex.Load(select(texel, 0, 0))))/2,
temporal_diff1 = (abs(prevTex.Load(select(texel, 0, 1))-c) + abs(prevTex.Load(select(texel, 0, -1))-e))/2,
temporal_diff2 = (abs(tex.Load(select(texel, 0, 1))-c) + abs(tex.Load(select(texel, 0, -1))-e))/2,
diff = max(temporal_diff0, max(temporal_diff1, temporal_diff2));
float4 spatial_pred = (c+e)/2,
spatial_score = abs(load_at(texel, -1, 1, field)-load_at(texel, -1, -1, field))+
abs(c-e)+
abs(load_at(texel, 1, 1, field)-load_at(texel, 1, -1, field))-1;
YADIF_CHECK(-1)
YADIF_CHECK(1)
float4 max_ = max(d-e, max(d-c, min(b-c, f-e))),
min_ = min(d-e, min(d-c, max(b-c, f-e)));
diff = max(diff, max(min_, -max_));
#define YADIF_SPATIAL(c)\
{\
if(spatial_pred.c > d.c + diff.c)\
spatial_pred.c = d.c + diff.c;\
else if(spatial_pred.c < d.c - diff.c)\
spatial_pred.c = d.c - diff.c;\
}
YADIF_SPATIAL(r)
YADIF_SPATIAL(g)
YADIF_SPATIAL(b)
YADIF_SPATIAL(a)
return spatial_pred;
}
float4 texel_at_blend(int2 texel, int field)
{
return (diffuseTexture.Load(int3(texel, 0)) + diffuseTexture.Load(int3(texel.x, texel.y+1, 0)))/2;
}
float4 texel_at_blend_2x(int2 texel, int field)
{
if(field_order != field)
return (diffuseTexture.Load(int3(texel.x, texel.y, 0)) + prevTex.Load(int3(texel.x, texel.y+1, 0)))/2;
return (diffuseTexture.Load(int3(texel.x, texel.y, 0)) + diffuseTexture.Load(int3(texel.x, texel.y+1, 0)))/2;
}
float4 texel_at_linear(int2 texel, int field)
{
if(field == texel.y%2)
return diffuseTexture.Load(int3(texel, 0));
return (diffuseTexture.Load(int3(texel+int2(0, -1), 0))+diffuseTexture.Load(int3(texel+int2(0, 1), 0)))/2;
}
float4 texel_at_linear2x(int2 texel, int field)
{
return texel_at_linear(texel, 1-field);
}
float4 texel_at_discard(int2 texel, int field)
{
Texture2D tex = diffuseTexture;
return tex.Load(int3(texel.x, texel.y/2*2+field, 0));
}
float4 texel_at_discard2x(int2 texel, int field)
{
return texel_at_discard(texel, 1-field);
}
float4 texel_at_weave(int2 texel, int field)
{
if(field != 0)
return prevTex.Load(int3(texel, 0));
return diffuseTexture.Load(int3(texel, 0));
}
#define DISPATCH(name, func)\
case name: return func(coord, field); break;
float4 sample_texel(float2 coord, int field, int name)
{
switch(name)
{
DISPATCH(YADIF, texel_at_yadif)
DISPATCH(BLEND, texel_at_blend)
DISPATCH(BLEND2x, texel_at_blend_2x)
DISPATCH(LINEAR, texel_at_linear)
DISPATCH(LINEAR2x, texel_at_linear2x)
DISPATCH(DISCARD, texel_at_discard)
DISPATCH(DISCARD2x, texel_at_discard2x)
default: return texel_at_weave(coord, field); break;
}
}
#undef DISPATCH
float4 sample_pixel(float2 coord, bool field, int func)
{
Texture2D tex = diffuseTexture;
float2 size = 0;
float miplevels;
tex.GetDimensions(0, size.x, size.y, miplevels);
float2 uv = coord*size;
return sample_texel(uv, field, func);
}
float4 sample_pixel_2x(float2 coord, bool field, int func)
{
coord.x *= 2;
return sample_pixel(coord-floor(coord), field*(coord.x>1)+(1-field)*(coord.x<1), func);
}
struct VertData
{
float4 pos : SV_Position;
float2 texCoord : TexCoord0;
};