1#version 150
2
3/*
4   NEDI Shader  -  pass1
5
6// This file is a part of MPDN Extensions.
7// https://github.com/zachsaw/MPDN_Extensions
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 3.0 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library.
21//
22
23   Sources ported from this discussion thread:
24
25      http://forum.doom9.org/showthread.php?t=170727
26
27   Ported by Hyllian - 2015.
28*/
29
30#define saturate(c) clamp(c, 0.0, 1.0)
31#define lerp(c) mix(c)
32#define mul(a,b) (b*a)
33#define fmod(c) mod(c)
34#define frac(c) fract(c)
35#define tex2D(a,b) COMPAT_TEXTURE(a,b)
36#define float2 vec2
37#define float3 vec3
38#define float4 vec4
39#define int2 ivec2
40#define int3 ivec3
41#define int4 ivec4
42#define bool2 bvec2
43#define bool3 bvec3
44#define bool4 bvec4
45#define float2x2 mat2x2
46#define float2x3 mat2x3
47#define float3x3 mat3x3
48#define float4x4 mat4x4
49#define float4x2 mat4x2
50
51#define s0 Source
52#define FIX(c) (c * 1.00001)
53
54#define NEDI_WEIGHT2 4.0
55#define NEDI_N2 24.0
56#define NEDI_E2 0.0
57#define NEDI_OFFSET2 0.0
58
59#define ITERATIONS  3
60#define WGT   2.
61
62#define width  (SourceSize.x)
63#define height (SourceSize.y)
64
65#define px (1.0 * (SourceSize.z))
66#define py (0.4999 * (SourceSize.w))
67
68#define offset NEDI_OFFSET2
69
70#define Value(xy) (tex2D(s0,tex+float2(px,py)*(xy)).rgb)//-float4(0,0.4999,0.4999,0))
71
72#define Get(xy) (dot(Value(xy),float3(.2126, .7152, .0722))+offset)
73#define Get4(xy) (float2(Get(xy+WGT*dir[0])+Get(xy+WGT*dir[1]),Get(xy+WGT*dir[2])+Get(xy+WGT*dir[3])))
74
75#define sqr(x) (dot(x,x))
76#define I (float2x2(1.,0.,0.,1.))
77
78#if defined(VERTEX)
79
80#if __VERSION__ >= 130
81#define COMPAT_VARYING out
82#define COMPAT_ATTRIBUTE in
83#define COMPAT_TEXTURE texture
84#else
85#define COMPAT_VARYING varying
86#define COMPAT_ATTRIBUTE attribute
87#define COMPAT_TEXTURE texture2D
88#endif
89
90#ifdef GL_ES
91#define COMPAT_PRECISION mediump
92#else
93#define COMPAT_PRECISION
94#endif
95
96COMPAT_ATTRIBUTE vec4 VertexCoord;
97COMPAT_ATTRIBUTE vec4 COLOR;
98COMPAT_ATTRIBUTE vec4 TexCoord;
99COMPAT_VARYING vec4 COL0;
100COMPAT_VARYING vec4 TEX0;
101
102vec4 _oPosition1;
103uniform mat4 MVPMatrix;
104uniform COMPAT_PRECISION int FrameDirection;
105uniform COMPAT_PRECISION int FrameCount;
106uniform COMPAT_PRECISION vec2 OutputSize;
107uniform COMPAT_PRECISION vec2 TextureSize;
108uniform COMPAT_PRECISION vec2 InputSize;
109
110// compatibility #defines
111#define vTexCoord TEX0.xy
112#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
113#define OutSize vec4(OutputSize, 1.0 / OutputSize)
114
115void main()
116{
117    gl_Position = MVPMatrix * VertexCoord;
118    TEX0.xy = TexCoord.xy * 1.0001;
119}
120
121#elif defined(FRAGMENT)
122
123#ifdef GL_ES
124#ifdef GL_FRAGMENT_PRECISION_HIGH
125precision highp float;
126#else
127precision mediump float;
128#endif
129#define COMPAT_PRECISION mediump
130#else
131#define COMPAT_PRECISION
132#endif
133
134#if __VERSION__ >= 130
135#define COMPAT_VARYING in
136#define COMPAT_TEXTURE texture
137out COMPAT_PRECISION vec4 FragColor;
138#else
139#define COMPAT_VARYING varying
140#define FragColor gl_FragColor
141#define COMPAT_TEXTURE texture2D
142#endif
143
144uniform COMPAT_PRECISION int FrameDirection;
145uniform COMPAT_PRECISION int FrameCount;
146uniform COMPAT_PRECISION vec2 OutputSize;
147uniform COMPAT_PRECISION vec2 TextureSize;
148uniform COMPAT_PRECISION vec2 InputSize;
149uniform sampler2D Texture;
150COMPAT_VARYING vec4 TEX0;
151
152// compatibility #defines
153#define Source Texture
154#define vTexCoord TEX0.xy
155
156#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
157#define OutSize vec4(OutputSize, 1.0 / OutputSize)
158
159//Cramer's method
160float2 solve(float2x2 A,float2 b)
161{
162	return float2(determinant(float2x2(b,A[1])),determinant(float2x2(A[0],b)))/determinant(A);
163}
164
165void main()
166{
167	float2 tex = vTexCoord;
168
169	float4 c0 = tex2D(s0,tex);
170
171	//Skip pixels on wrong grid
172	if ((frac(tex.x*width/2.0)<0.5)&&(frac(tex.y*height)<0.5) || (frac(tex.x*width/2.0)>0.5)&&(frac(tex.y*height)>0.5))
173	{
174		FragColor = c0;
175	}
176	else
177	{
178
179	//Define window and directions
180	vec2 dir1 = vec2(-1., 0.);
181	vec2 dir2 = vec2( 1., 0.);
182	vec2 dir3 = vec2( 0., 1.);
183	vec2 dir4 = vec2( 0.,-1.);
184  	float2 dir[4] =  vec2[](dir1, dir2, dir3, dir4);
185
186	mat4x2 wind1 = mat4x2(-1.,0.,1.,0.,0.,1.,0.,-1.);
187	mat4x2 wind2 = mat4x2(-1.,0.,1.,0.,0.,1.,0.,-1.);
188	mat4x2 wind3 = mat4x2(-2.,-1.,2.,1.,-1.,2.,1.,-2.);
189	mat4x2 wind4 = mat4x2(-3.,-2.,3.,2.,-2.,3.,2.,-3.);
190	mat4x2 wind5 = mat4x2(-2.,1.,2.,-1.,1.,2.,-1.,-2.);
191	mat4x2 wind6 = mat4x2(-3.,2.,3.,-2.,2.,3.,-2.,-3.);
192	mat4x2 wind7 = mat4x2(-4.,-1.,4.,1.,-1.,4.,1.,-4.);
193	mat4x2 wind8 = mat4x2(-4.,1.,4.,-1.,1.,4.,-1.,-4.);
194  	float4x2 wind[7] = mat4x2[](wind1, wind2, wind3, wind4, wind5, wind6, wind7);
195
196/*
197                                         wind[1]              wind[2]
198-3
199-2             dir        wind[0]            2                 1
200-1              4           4          4                             4
201 0            1   2       1   2
202 1              3           3                   3           3
203 2                                        1                       2
204 3
205*/
206
207/*
208                                         wind[1]              wind[2]
209-3                                            3                1
210-2             dir        wind[0]
211-1            1   4        1   3      1                                3
212 0
213 1            3   2        2   4                  4        2
214 2
215 3                                        2                        4
216*/
217
218	//Initialization
219	float2x2 R = float2x2(0.0);
220	float2 r = float2(0.0);
221
222        float m[7] = float[](NEDI_WEIGHT2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
223
224	//Calculate (local) autocorrelation coefficients
225	for (int k = 0; k<ITERATIONS; k+= 1){
226		float4 y = float4(Get(wind[k][0]),Get(wind[k][1]),Get(wind[k][2]),Get(wind[k][3]));
227		float4x2 C = float4x2(Get4(wind[k][0]),Get4(wind[k][1]),Get4(wind[k][2]),Get4(wind[k][3]));
228		R += mul(transpose(C),m[k]*C);
229		r += mul(y,m[k]*C);
230	}
231
232	//Normalize
233	float n = NEDI_N2;
234	R /= n; r /= n;
235
236	//Calculate a =  R^-1 . r
237	float e = NEDI_E2;
238	float2 a = solve(R+e*e*I,r+e*e/2.0);
239
240	//Nomalize 'a' (prevents overshoot)
241	a = .25 + float2(.4999,-.4999)*clamp(a[0]-a[1],-1.0,1.0);
242
243	//Calculate result
244	float2x3 x = float2x3(Value(dir[0])+Value(dir[1]),Value(dir[2])+Value(dir[3])) * float2x2(a,a);
245	float3 c = float3(x[0].xyz);
246
247	FragColor = float4(c, 1.0);//+float4(0,0.49999,0.49999,0);
248	}
249}
250#endif
251