comparison shaders/xBRZ.f.glsl @ 2660:9a5e627c1b1f

Make xBRZ shader be WebGL compatible
author Michael Pavone <pavone@retrodev.com>
date Tue, 04 Mar 2025 00:42:14 -0800
parents d437b8e8ba62
children
comparison
equal deleted inserted replaced
2659:e8d37b8fa532 2660:9a5e627c1b1f
58 #define DOMINANT_DIRECTION_THRESHOLD 3.6 58 #define DOMINANT_DIRECTION_THRESHOLD 3.6
59 59
60 // this is usually handled automatically but blastem doesn't expose output size? 60 // this is usually handled automatically but blastem doesn't expose output size?
61 #define scale vec2(10.0, 10.0) 61 #define scale vec2(10.0, 10.0)
62 62
63 mediump float DistYCbCr(vec3 pixA, vec3 pixB) 63 mediump float DistYCbCr(mediump vec3 pixA, mediump vec3 pixB)
64 { 64 {
65 const vec3 w = vec3(0.2627, 0.6780, 0.0593); 65 const mediump vec3 w = vec3(0.2627, 0.6780, 0.0593);
66 const float scaleB = 0.5 / (1.0 - w.b); 66 const mediump float scaleB = 0.5 / (1.0 - w.b);
67 const float scaleR = 0.5 / (1.0 - w.r); 67 const mediump float scaleR = 0.5 / (1.0 - w.r);
68 vec3 diff = pixA - pixB; 68 mediump vec3 diff = pixA - pixB;
69 float Y = dot(diff.rgb, w); 69 mediump float Y = dot(diff.rgb, w);
70 float Cb = scaleB * (diff.b - Y); 70 mediump float Cb = scaleB * (diff.b - Y);
71 float Cr = scaleR * (diff.r - Y); 71 mediump float Cr = scaleR * (diff.r - Y);
72 72
73 return sqrt(((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr)); 73 return sqrt(((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr));
74 } 74 }
75 75
76 bool IsPixEqual(const vec3 pixA, const vec3 pixB) 76 bool IsPixEqual(const mediump vec3 pixA, const mediump vec3 pixB)
77 { 77 {
78 return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE); 78 return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE);
79 } 79 }
80 80
81 mediump float get_left_ratio(vec2 center, vec2 origin, vec2 direction, vec2 scale_) 81 mediump float get_left_ratio(mediump vec2 center, mediump vec2 origin, mediump vec2 direction, mediump vec2 scale_)
82 { 82 {
83 vec2 P0 = center - origin; 83 mediump vec2 P0 = center - origin;
84 vec2 proj = direction * (dot(P0, direction) / dot(direction, direction)); 84 mediump vec2 proj = direction * (dot(P0, direction) / dot(direction, direction));
85 vec2 distv = P0 - proj; 85 mediump vec2 distv = P0 - proj;
86 vec2 orth = vec2(-direction.y, direction.x); 86 mediump vec2 orth = vec2(-direction.y, direction.x);
87 float side = sign(dot(P0, orth)); 87 mediump float side = sign(dot(P0, orth));
88 float v = side * length(distv * scale_); 88 mediump float v = side * length(distv * scale_);
89 89
90 // return step(0, v); 90 // return step(0, v);
91 return smoothstep(-sqrt(2.0)/2.0, sqrt(2.0)/2.0, v); 91 return smoothstep(-sqrt(2.0)/2.0, sqrt(2.0)/2.0, v);
92 } 92 }
93 93
103 // x|A|B|C|x 103 // x|A|B|C|x
104 // x|D|E|F|x 104 // x|D|E|F|x
105 // x|G|H|I|x 105 // x|G|H|I|x
106 // -|x|x|x|- 106 // -|x|x|x|-
107 107
108 vec2 pos = fract(texcoord * texsize.xy) - vec2(0.5, 0.5); 108 mediump vec2 pos = fract(texcoord * texsize.xy) - vec2(0.5, 0.5);
109 vec2 coord = texcoord - pos * (1.0 / texsize.xy); 109 mediump vec2 coord = texcoord - pos * (1.0 / texsize.xy);
110 110
111 vec3 A = P(-1,-1); 111 mediump vec3 A = P(-1,-1);
112 vec3 B = P( 0,-1); 112 mediump vec3 B = P( 0,-1);
113 vec3 C = P( 1,-1); 113 mediump vec3 C = P( 1,-1);
114 vec3 D = P(-1, 0); 114 mediump vec3 D = P(-1, 0);
115 vec3 E = P( 0, 0); 115 mediump vec3 E = P( 0, 0);
116 vec3 F = P( 1, 0); 116 mediump vec3 F = P( 1, 0);
117 vec3 G = P(-1, 1); 117 mediump vec3 G = P(-1, 1);
118 vec3 H = P( 0, 1); 118 mediump vec3 H = P( 0, 1);
119 vec3 I = P( 1, 1); 119 mediump vec3 I = P( 1, 1);
120 120
121 // blendResult Mapping: x|y| 121 // blendResult Mapping: x|y|
122 // w|z| 122 // w|z|
123 ivec4 blendResult = ivec4(BLEND_NONE,BLEND_NONE,BLEND_NONE,BLEND_NONE); 123 ivec4 blendResult = ivec4(BLEND_NONE,BLEND_NONE,BLEND_NONE,BLEND_NONE);
124 124
128 // -|D|E|F|x 128 // -|D|E|F|x
129 // -|G|H|I|x 129 // -|G|H|I|x
130 // -|-|x|x|- 130 // -|-|x|x|-
131 if (!((eq(E,F) && eq(H,I)) || (eq(E,H) && eq(F,I)))) 131 if (!((eq(E,F) && eq(H,I)) || (eq(E,H) && eq(F,I))))
132 { 132 {
133 float dist_H_F = DistYCbCr(G, E) + DistYCbCr(E, C) + DistYCbCr(P(0,2), I) + DistYCbCr(I, P(2,0)) + (4.0 * DistYCbCr(H, F)); 133 mediump float dist_H_F = DistYCbCr(G, E) + DistYCbCr(E, C) + DistYCbCr(P(0,2), I) + DistYCbCr(I, P(2,0)) + (4.0 * DistYCbCr(H, F));
134 float dist_E_I = DistYCbCr(D, H) + DistYCbCr(H, P(1,2)) + DistYCbCr(B, F) + DistYCbCr(F, P(2,1)) + (4.0 * DistYCbCr(E, I)); 134 mediump float dist_E_I = DistYCbCr(D, H) + DistYCbCr(H, P(1,2)) + DistYCbCr(B, F) + DistYCbCr(F, P(2,1)) + (4.0 * DistYCbCr(E, I));
135 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_H_F) < dist_E_I; 135 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_H_F) < dist_E_I;
136 blendResult.z = ((dist_H_F < dist_E_I) && neq(E,F) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; 136 blendResult.z = ((dist_H_F < dist_E_I) && neq(E,F) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
137 } 137 }
138 138
139 139
142 // x|D|E|F|- 142 // x|D|E|F|-
143 // x|G|H|I|- 143 // x|G|H|I|-
144 // -|x|x|-|- 144 // -|x|x|-|-
145 if (!((eq(D,E) && eq(G,H)) || (eq(D,G) && eq(E,H)))) 145 if (!((eq(D,E) && eq(G,H)) || (eq(D,G) && eq(E,H))))
146 { 146 {
147 float dist_G_E = DistYCbCr(P(-2,1) , D) + DistYCbCr(D, B) + DistYCbCr(P(-1,2), H) + DistYCbCr(H, F) + (4.0 * DistYCbCr(G, E)); 147 mediump float dist_G_E = DistYCbCr(P(-2,1) , D) + DistYCbCr(D, B) + DistYCbCr(P(-1,2), H) + DistYCbCr(H, F) + (4.0 * DistYCbCr(G, E));
148 float dist_D_H = DistYCbCr(P(-2,0) , G) + DistYCbCr(G, P(0,2)) + DistYCbCr(A, E) + DistYCbCr(E, I) + (4.0 * DistYCbCr(D, H)); 148 mediump float dist_D_H = DistYCbCr(P(-2,0) , G) + DistYCbCr(G, P(0,2)) + DistYCbCr(A, E) + DistYCbCr(E, I) + (4.0 * DistYCbCr(D, H));
149 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_H) < dist_G_E; 149 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_H) < dist_G_E;
150 blendResult.w = ((dist_G_E > dist_D_H) && neq(E,D) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; 150 blendResult.w = ((dist_G_E > dist_D_H) && neq(E,D) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
151 } 151 }
152 152
153 // Pixel Tap Mapping: -|-|x|x|- 153 // Pixel Tap Mapping: -|-|x|x|-
155 // -|D|E|F|x 155 // -|D|E|F|x
156 // -|-|H|I|- 156 // -|-|H|I|-
157 // -|-|-|-|- 157 // -|-|-|-|-
158 if (!((eq(B,C) && eq(E,F)) || (eq(B,E) && eq(C,F)))) 158 if (!((eq(B,C) && eq(E,F)) || (eq(B,E) && eq(C,F))))
159 { 159 {
160 float dist_E_C = DistYCbCr(D, B) + DistYCbCr(B, P(1,-2)) + DistYCbCr(H, F) + DistYCbCr(F, P(2,-1)) + (4.0 * DistYCbCr(E, C)); 160 mediump float dist_E_C = DistYCbCr(D, B) + DistYCbCr(B, P(1,-2)) + DistYCbCr(H, F) + DistYCbCr(F, P(2,-1)) + (4.0 * DistYCbCr(E, C));
161 float dist_B_F = DistYCbCr(A, E) + DistYCbCr(E, I) + DistYCbCr(P(0,-2), C) + DistYCbCr(C, P(2,0)) + (4.0 * DistYCbCr(B, F)); 161 mediump float dist_B_F = DistYCbCr(A, E) + DistYCbCr(E, I) + DistYCbCr(P(0,-2), C) + DistYCbCr(C, P(2,0)) + (4.0 * DistYCbCr(B, F));
162 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_B_F) < dist_E_C; 162 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_B_F) < dist_E_C;
163 blendResult.y = ((dist_E_C > dist_B_F) && neq(E,B) && neq(E,F)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; 163 blendResult.y = ((dist_E_C > dist_B_F) && neq(E,B) && neq(E,F)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
164 } 164 }
165 165
166 // Pixel Tap Mapping: -|x|x|-|- 166 // Pixel Tap Mapping: -|x|x|-|-
168 // x|D|E|F|- 168 // x|D|E|F|-
169 // -|G|H|-|- 169 // -|G|H|-|-
170 // -|-|-|-|- 170 // -|-|-|-|-
171 if (!((eq(A,B) && eq(D,E)) || (eq(A,D) && eq(B,E)))) 171 if (!((eq(A,B) && eq(D,E)) || (eq(A,D) && eq(B,E))))
172 { 172 {
173 float dist_D_B = DistYCbCr(P(-2,0), A) + DistYCbCr(A, P(0,-2)) + DistYCbCr(G, E) + DistYCbCr(E, C) + (4.0 * DistYCbCr(D, B)); 173 mediump float dist_D_B = DistYCbCr(P(-2,0), A) + DistYCbCr(A, P(0,-2)) + DistYCbCr(G, E) + DistYCbCr(E, C) + (4.0 * DistYCbCr(D, B));
174 float dist_A_E = DistYCbCr(P(-2,-1), D) + DistYCbCr(D, H) + DistYCbCr(P(-1,-2), B) + DistYCbCr(B, F) + (4.0 * DistYCbCr(A, E)); 174 mediump float dist_A_E = DistYCbCr(P(-2,-1), D) + DistYCbCr(D, H) + DistYCbCr(P(-1,-2), B) + DistYCbCr(B, F) + (4.0 * DistYCbCr(A, E));
175 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_B) < dist_A_E; 175 bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_D_B) < dist_A_E;
176 blendResult.x = ((dist_D_B < dist_A_E) && neq(E,D) && neq(E,B)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; 176 blendResult.x = ((dist_D_B < dist_A_E) && neq(E,D) && neq(E,B)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
177 } 177 }
178 178
179 vec3 res = E; 179 mediump vec3 res = E;
180 180
181 // Pixel Tap Mapping: -|-|-|-|- 181 // Pixel Tap Mapping: -|-|-|-|-
182 // -|-|B|C|- 182 // -|-|B|C|-
183 // -|D|E|F|x 183 // -|D|E|F|x
184 // -|G|H|I|x 184 // -|G|H|I|x
185 // -|-|x|x|- 185 // -|-|x|x|-
186 if(blendResult.z != BLEND_NONE) 186 if(blendResult.z != BLEND_NONE)
187 { 187 {
188 float dist_F_G = DistYCbCr(F, G); 188 mediump float dist_F_G = DistYCbCr(F, G);
189 float dist_H_C = DistYCbCr(H, C); 189 mediump float dist_H_C = DistYCbCr(H, C);
190 bool doLineBlend = (blendResult.z == BLEND_DOMINANT || 190 bool doLineBlend = (blendResult.z == BLEND_DOMINANT ||
191 !((blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || (blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || 191 !((blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || (blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) ||
192 (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && IsPixEqual(F, C) && !IsPixEqual(E, I)))); 192 (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && IsPixEqual(F, C) && !IsPixEqual(E, I))));
193 193
194 vec2 origin = vec2(0.0, 1.0 / sqrt(2.0)); 194 mediump vec2 origin = vec2(0.0, 1.0 / sqrt(2.0));
195 vec2 direction = vec2(1.0, -1.0); 195 mediump vec2 direction = vec2(1.0, -1.0);
196 if(doLineBlend) 196 if(doLineBlend)
197 { 197 {
198 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && neq(E,G) && neq(D,G); 198 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && neq(E,G) && neq(D,G);
199 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && neq(E,C) && neq(B,C); 199 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && neq(E,C) && neq(B,C);
200 origin = haveShallowLine? vec2(0.0, 0.25) : vec2(0.0, 0.5); 200 origin = haveShallowLine? vec2(0.0, 0.25) : vec2(0.0, 0.5);
201 direction.x += haveShallowLine? 1.0: 0.0; 201 direction.x += haveShallowLine? 1.0: 0.0;
202 direction.y -= haveSteepLine? 1.0: 0.0; 202 direction.y -= haveSteepLine? 1.0: 0.0;
203 } 203 }
204 204
205 vec3 blendPix = mix(H,F, step(DistYCbCr(E, F), DistYCbCr(E, H))); 205 mediump vec3 blendPix = mix(H,F, step(DistYCbCr(E, F), DistYCbCr(E, H)));
206 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale)); 206 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
207 } 207 }
208 208
209 // Pixel Tap Mapping: -|-|-|-|- 209 // Pixel Tap Mapping: -|-|-|-|-
210 // -|A|B|-|- 210 // -|A|B|-|-
211 // x|D|E|F|- 211 // x|D|E|F|-
212 // x|G|H|I|- 212 // x|G|H|I|-
213 // -|x|x|-|- 213 // -|x|x|-|-
214 if(blendResult.w != BLEND_NONE) 214 if(blendResult.w != BLEND_NONE)
215 { 215 {
216 float dist_H_A = DistYCbCr(H, A); 216 mediump float dist_H_A = DistYCbCr(H, A);
217 float dist_D_I = DistYCbCr(D, I); 217 mediump float dist_D_I = DistYCbCr(D, I);
218 bool doLineBlend = (blendResult.w == BLEND_DOMINANT || 218 bool doLineBlend = (blendResult.w == BLEND_DOMINANT ||
219 !((blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || (blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || 219 !((blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || (blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) ||
220 (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && IsPixEqual(H, I) && !IsPixEqual(E, G)))); 220 (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && IsPixEqual(H, I) && !IsPixEqual(E, G))));
221 221
222 vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0); 222 mediump vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0);
223 vec2 direction = vec2(1.0, 1.0); 223 mediump vec2 direction = vec2(1.0, 1.0);
224 if(doLineBlend) 224 if(doLineBlend)
225 { 225 {
226 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && neq(E,A) && neq(B,A); 226 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && neq(E,A) && neq(B,A);
227 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && neq(E,I) && neq(F,I); 227 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && neq(E,I) && neq(F,I);
228 origin = haveShallowLine? vec2(-0.25, 0.0) : vec2(-0.5, 0.0); 228 origin = haveShallowLine? vec2(-0.25, 0.0) : vec2(-0.5, 0.0);
230 direction.x += haveSteepLine? 1.0: 0.0; 230 direction.x += haveSteepLine? 1.0: 0.0;
231 } 231 }
232 origin = origin; 232 origin = origin;
233 direction = direction; 233 direction = direction;
234 234
235 vec3 blendPix = mix(H,D, step(DistYCbCr(E, D), DistYCbCr(E, H))); 235 mediump vec3 blendPix = mix(H,D, step(DistYCbCr(E, D), DistYCbCr(E, H)));
236 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale)); 236 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
237 } 237 }
238 238
239 // Pixel Tap Mapping: -|-|x|x|- 239 // Pixel Tap Mapping: -|-|x|x|-
240 // -|A|B|C|x 240 // -|A|B|C|x
241 // -|D|E|F|x 241 // -|D|E|F|x
242 // -|-|H|I|- 242 // -|-|H|I|-
243 // -|-|-|-|- 243 // -|-|-|-|-
244 if(blendResult.y != BLEND_NONE) 244 if(blendResult.y != BLEND_NONE)
245 { 245 {
246 float dist_B_I = DistYCbCr(B, I); 246 mediump float dist_B_I = DistYCbCr(B, I);
247 float dist_F_A = DistYCbCr(F, A); 247 mediump float dist_F_A = DistYCbCr(F, A);
248 bool doLineBlend = (blendResult.y == BLEND_DOMINANT || 248 bool doLineBlend = (blendResult.y == BLEND_DOMINANT ||
249 !((blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || (blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || 249 !((blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || (blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) ||
250 (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && IsPixEqual(B, A) && !IsPixEqual(E, C)))); 250 (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && IsPixEqual(B, A) && !IsPixEqual(E, C))));
251 251
252 vec2 origin = vec2(1.0 / sqrt(2.0), 0.0); 252 mediump vec2 origin = vec2(1.0 / sqrt(2.0), 0.0);
253 vec2 direction = vec2(-1.0, -1.0); 253 mediump vec2 direction = vec2(-1.0, -1.0);
254 254
255 if(doLineBlend) 255 if(doLineBlend)
256 { 256 {
257 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && neq(E,I) && neq(H,I); 257 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && neq(E,I) && neq(H,I);
258 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && neq(E,A) && neq(D,A); 258 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && neq(E,A) && neq(D,A);
259 origin = haveShallowLine? vec2(0.25, 0.0) : vec2(0.5, 0.0); 259 origin = haveShallowLine? vec2(0.25, 0.0) : vec2(0.5, 0.0);
260 direction.y -= haveShallowLine? 1.0: 0.0; 260 direction.y -= haveShallowLine? 1.0: 0.0;
261 direction.x -= haveSteepLine? 1.0: 0.0; 261 direction.x -= haveSteepLine? 1.0: 0.0;
262 } 262 }
263 263
264 vec3 blendPix = mix(F,B, step(DistYCbCr(E, B), DistYCbCr(E, F))); 264 mediump vec3 blendPix = mix(F,B, step(DistYCbCr(E, B), DistYCbCr(E, F)));
265 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale)); 265 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
266 } 266 }
267 267
268 // Pixel Tap Mapping: -|x|x|-|- 268 // Pixel Tap Mapping: -|x|x|-|-
269 // x|A|B|C|- 269 // x|A|B|C|-
270 // x|D|E|F|- 270 // x|D|E|F|-
271 // -|G|H|-|- 271 // -|G|H|-|-
272 // -|-|-|-|- 272 // -|-|-|-|-
273 if(blendResult.x != BLEND_NONE) 273 if(blendResult.x != BLEND_NONE)
274 { 274 {
275 float dist_D_C = DistYCbCr(D, C); 275 mediump float dist_D_C = DistYCbCr(D, C);
276 float dist_B_G = DistYCbCr(B, G); 276 mediump float dist_B_G = DistYCbCr(B, G);
277 bool doLineBlend = (blendResult.x == BLEND_DOMINANT || 277 bool doLineBlend = (blendResult.x == BLEND_DOMINANT ||
278 !((blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || (blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || 278 !((blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || (blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) ||
279 (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && IsPixEqual(D, G) && !IsPixEqual(E, A)))); 279 (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && IsPixEqual(D, G) && !IsPixEqual(E, A))));
280 280
281 vec2 origin = vec2(0.0, -1.0 / sqrt(2.0)); 281 mediump vec2 origin = vec2(0.0, -1.0 / sqrt(2.0));
282 vec2 direction = vec2(-1.0, 1.0); 282 mediump vec2 direction = vec2(-1.0, 1.0);
283 if(doLineBlend) 283 if(doLineBlend)
284 { 284 {
285 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && neq(E,C) && neq(F,C); 285 bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && neq(E,C) && neq(F,C);
286 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && neq(E,G) && neq(H,G); 286 bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && neq(E,G) && neq(H,G);
287 origin = haveShallowLine? vec2(0.0, -0.25) : vec2(0.0, -0.5); 287 origin = haveShallowLine? vec2(0.0, -0.25) : vec2(0.0, -0.5);
288 direction.x -= haveShallowLine? 1.0: 0.0; 288 direction.x -= haveShallowLine? 1.0: 0.0;
289 direction.y += haveSteepLine? 1.0: 0.0; 289 direction.y += haveSteepLine? 1.0: 0.0;
290 } 290 }
291 291
292 vec3 blendPix = mix(D,B, step(DistYCbCr(E, B), DistYCbCr(E, D))); 292 mediump vec3 blendPix = mix(D,B, step(DistYCbCr(E, B), DistYCbCr(E, D)));
293 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale)); 293 res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
294 } 294 }
295 295
296 gl_FragColor = vec4(res, 1.0); 296 gl_FragColor = vec4(res, 1.0);
297 } 297 }