|
|
/*
|
Hyllian's 5xBR v3.5 Shader
|
|
Copyright (C) 2011 Hyllian/Jararaca - sergiogdb@gmail.com
|
|
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.
|
|
*/
|
|
// Messed up and ported to Pete's OGL2 GLSL, KrossX (2012-03-12)
|
|
#version 110
|
|
uniform sampler2D OGL2Texture;
|
uniform vec4 OGL2Param;
|
uniform vec4 OGL2Size;
|
|
const float coef = 2.0;
|
const vec3 dtt = vec3(65536,255,1);
|
const float y_weight = 48.0;
|
const float u_weight = 7.0;
|
const float v_weight = 6.0;
|
const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
|
const mat3 yuv_weighted = mat3(y_weight*yuv[0], u_weight*yuv[1], v_weight*yuv[2]);
|
//const mat3x3 yuv_weighted = mat3x3(14.352, 28.176, 5.472, -1.183, -2.317, 3.5, 3.0, -2.514, -0.486);
|
|
|
bvec4 and(vec4 a, vec4 b)
|
{
|
return bvec4(a.x != 0.0 && b.x != 0.0, a.y != 0.0 && b.y != 0.0, a.z != 0.0 && b.z != 0.0, a.w != 0.0 && b.w != 0.0);
|
}
|
|
vec4 RGBtoYUV(mat4 mat_color)
|
{
|
vec3 a = abs(yuv_weighted * mat_color[0].xyz);
|
vec3 b = abs(yuv_weighted * mat_color[1].xyz);
|
vec3 c = abs(yuv_weighted * mat_color[2].xyz);
|
vec3 d = abs(yuv_weighted * mat_color[3].xyz);
|
|
return vec4(length(a), length(b), length(c), length(d));
|
}
|
|
vec4 df(vec4 A, vec4 B)
|
{
|
return vec4(abs(A-B));
|
}
|
|
vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
{
|
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
}
|
|
void main(void)
|
{
|
bvec4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
|
bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;
|
|
vec2 fp = fract(gl_TexCoord[0].xy * OGL2Size.xy); // Texture size
|
|
vec2 dx = gl_TexCoord[1].xy;
|
vec2 dy = gl_TexCoord[1].zw;
|
|
vec4 A = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dx -dy).xyz, 0.0);
|
vec4 B = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dy).xyz, 0.0);
|
vec4 C = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dx -dy).xyz, 0.0);
|
vec4 D = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dx ).xyz, 0.0);
|
vec4 E = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy ).xyz, 0.0);
|
vec4 F = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dx ).xyz, 0.0);
|
vec4 G = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dx +dy).xyz, 0.0);
|
vec4 H = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dy).xyz, 0.0);
|
vec4 I = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dx +dy).xyz, 0.0);
|
|
vec4 A1 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dx -2.0*dy).xyz, 0.0);
|
vec4 C1 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dx -2.0*dy).xyz, 0.0);
|
vec4 A0 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -2.0*dx -dy).xyz, 0.0);
|
vec4 G0 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -2.0*dx +dy).xyz, 0.0);
|
vec4 C4 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +2.0*dx -dy).xyz, 0.0);
|
vec4 I4 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +2.0*dx +dy).xyz, 0.0);
|
vec4 G5 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -dx +2.0*dy).xyz, 0.0);
|
vec4 I5 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +dx +2.0*dy).xyz, 0.0);
|
vec4 B1 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -2.0*dy).xyz, 0.0);
|
vec4 D0 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy -2.0*dx ).xyz, 0.0);
|
vec4 H5 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +2.0*dy).xyz, 0.0);
|
vec4 F4 = vec4(texture2D(OGL2Texture, gl_TexCoord[0].xy +2.0*dx ).xyz, 0.0);
|
|
//vec4 a = RGBtoYUV( mat4(A, G, I, C) );
|
vec4 b = RGBtoYUV( mat4(B, D, H, F) );
|
vec4 c = RGBtoYUV( mat4(C, A, G, I) );
|
vec4 d = RGBtoYUV( mat4(D, H, F, B) );
|
vec4 e = RGBtoYUV( mat4(E, E, E, E) );
|
vec4 f = RGBtoYUV( mat4(F, B, D, H) );
|
vec4 g = RGBtoYUV( mat4(G, I, C, A) );
|
vec4 h = RGBtoYUV( mat4(H, F, B, D) );
|
vec4 i = RGBtoYUV( mat4(I, C, A, G) );
|
|
//vec4 a1 = RGBtoYUV( mat4(A1, G0, I5, C4) );
|
//vec4 c1 = RGBtoYUV( mat4(C1, A0, G5, I4) );
|
//vec4 a0 = RGBtoYUV( mat4(A0, G5, I4, C1) );
|
//vec4 g0 = RGBtoYUV( mat4(G0, I5, C4, A1) );
|
//vec4 c4 = RGBtoYUV( mat4(C4, A1, G0, I5) );
|
vec4 i4 = RGBtoYUV( mat4(I4, C1, A0, G5) );
|
//vec4 g5 = RGBtoYUV( mat4(G5, I4, C1, A0) );
|
vec4 i5 = RGBtoYUV( mat4(I5, C4, A1, G0) );
|
//vec4 b1 = RGBtoYUV( mat4(B1, D0, H5, F4) );
|
//vec4 d0 = RGBtoYUV( mat4(D0, H5, F4, B1) );
|
vec4 h5 = RGBtoYUV( mat4(H5, F4, B1, D0) );
|
vec4 f4 = RGBtoYUV( mat4(F4, B1, D0, H5) );
|
|
interp_restriction_lv1 = and(notEqual(e,f), notEqual(e,h));
|
interp_restriction_lv2_left = and(notEqual(e,g), notEqual(d,g));
|
interp_restriction_lv2_up = and(notEqual(e,c), notEqual(b,c));
|
|
edr = and(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)), interp_restriction_lv1);
|
edr_left = and(lessThanEqual(coef*df(f,g),df(h,c)), interp_restriction_lv2_left);
|
edr_up = and(greaterThanEqual(df(f,g), (coef*df(h,c))), interp_restriction_lv2_up);
|
|
vec3 E0 = E.xyz;
|
vec3 E1 = E.xyz;
|
vec3 E2 = E.xyz;
|
vec3 E3 = E.xyz;
|
|
px = lessThanEqual(df(e,f), df(e,h));
|
|
vec3 P[4];
|
|
P[0] = px.x ? F.xyz : H.xyz;
|
P[1] = px.y ? B.xyz : F.xyz;
|
P[2] = px.z ? D.xyz : B.xyz;
|
P[3] = px.w ? H.xyz : D.xyz;
|
|
|
if (edr.x)
|
{
|
if (edr_left.x && edr_up.x)
|
{
|
E3 = mix(E3 , P[0], 0.833333);
|
E2 = mix(E2 , P[0], 0.25);
|
E1 = mix(E1 , P[0], 0.25);
|
}
|
else if (edr_left.x)
|
{
|
E3 = mix(E3 , P[0], 0.75);
|
E2 = mix(E2 , P[0], 0.25);
|
}
|
else if (edr_up.x)
|
{
|
E3 = mix(E3 , P[0], 0.75);
|
E1 = mix(E1 , P[0], 0.25);
|
}
|
else
|
{
|
E3 = mix(E3 , P[0], 0.5);
|
}
|
}
|
|
if (edr.y)
|
{
|
if (edr_left.y && edr_up.y)
|
{
|
E1 = mix(E1 , P[1], 0.833333);
|
E3 = mix(E3 , P[1], 0.25);
|
E0 = mix(E0 , P[1], 0.25);
|
}
|
else if (edr_left.y)
|
{
|
E1 = mix(E1 , P[1], 0.75);
|
E3 = mix(E3 , P[1], 0.25);
|
}
|
else if (edr_up.y)
|
{
|
E1 = mix(E1 , P[1], 0.75);
|
E0 = mix(E0 , P[1], 0.25);
|
}
|
else
|
{
|
E1 = mix(E1 , P[1], 0.5);
|
}
|
}
|
|
if (edr.z)
|
{
|
if (edr_left.z && edr_up.z)
|
{
|
E0 = mix(E0 , P[2], 0.833333);
|
E1 = mix(E1 , P[2], 0.25);
|
E2 = mix(E2 , P[2], 0.25);
|
}
|
else if (edr_left.z)
|
{
|
E0 = mix(E0 , P[2], 0.75);
|
E1 = mix(E1 , P[2], 0.25);
|
}
|
else if (edr_up.z)
|
{
|
E0 = mix(E0 , P[2], 0.75);
|
E2 = mix(E2 , P[2], 0.25);
|
}
|
else
|
{
|
E0 = mix(E0 , P[2], 0.5);
|
}
|
}
|
|
if (edr.w)
|
{
|
if (edr_left.w && edr_up.w)
|
{
|
E2 = mix(E2 , P[3], 0.833333);
|
E0 = mix(E0 , P[3], 0.25);
|
E3 = mix(E3 , P[3], 0.25);
|
}
|
else if (edr_left.w)
|
{
|
E2 = mix(E2 , P[3], 0.75);
|
E0 = mix(E0 , P[3], 0.25);
|
}
|
else if (edr_up.w)
|
{
|
E2 = mix(E2 , P[3], 0.75);
|
E3 = mix(E3 , P[3], 0.25);
|
}
|
else
|
{
|
E2 = mix(E2 , P[3], 0.5);
|
}
|
}
|
|
vec3 res = (fp.x < 0.50) ? (fp.y < 0.50 ? E0 : E2) : (fp.y < 0.50 ? E1: E3);
|
gl_FragColor = vec4(res, 1.0);
|
} |