From daa05111cf59ed2cec8c1a778e956021e733bc6d Mon Sep 17 00:00:00 2001 From: crashGG <80488411+crashGG@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:05:00 +0300 Subject: [PATCH] Update tex_mmpx_adv.csh --- assets/shaders/tex_mmpx_adv.csh | 761 +++++++++++++++++--------------- 1 file changed, 400 insertions(+), 361 deletions(-) diff --git a/assets/shaders/tex_mmpx_adv.csh b/assets/shaders/tex_mmpx_adv.csh index 8b86ca27a2..4a7aa8270a 100644 --- a/assets/shaders/tex_mmpx_adv.csh +++ b/assets/shaders/tex_mmpx_adv.csh @@ -17,156 +17,160 @@ uint src(int x, int y) { - // Legacy clamp approach: return center pixel consistently when coordinates out of bounds + // Old clamp method: always return center pixel when coordinates are out of bounds //return readColoru(uvec2(clamp(x, 0, params.width - 1), clamp(y, 0, params.height - 1))); - // Improved out-of-bounds detection: check if coordinates are within valid range first. - // Return transparent color immediately if out of bounds. + // Better out-of-bounds check: test if coordinates are valid first. Return transparent if out of bounds. return (x >= 0 && x < params.width && y >= 0 && y < params.height) ? readColoru(uvec2(x, y)) : 0u; } -// RGB perceptual weight + alpha segmentation +// RGB perceptual weight + alpha tiered segmentation float luma(vec4 col) { - // BT.601 standard (CRT era) - result divided by 10, range [0.0 - 0.1] + // Use CRT-era BT.601 standard. Result divided by 10, range [0.0 - 0.1] float rgbsum =dot(col.rgb, vec3(0.0299, 0.0587, 0.0114)); - // Subsequent fractional extraction *10 removes alpha weighting + // Remove alpha weighting by taking fractional part and *10 later float alphafactor = - (col.a > 0.854102) ? 1.0 : // 2x short golden ratio (larger segment) - (col.a > 0.618034) ? 2.0 : // 1x golden ratio - (col.a > 0.381966) ? 3.0 : // 1x short golden ratio - (col.a > 0.145898) ? 4.0 : // 2x short golden ratio + (col.a > 0.854102) ? 1.0 : // Upper segment of two short golden ratio splits + (col.a > 0.618034) ? 2.0 : // One golden ratio split + (col.a > 0.381966) ? 3.0 : // One short golden ratio split + (col.a > 0.145898) ? 4.0 : // Two short golden ratio splits (col.a > 0.002) ? 5.0 : 8.0; // Fully transparent return rgbsum + alphafactor; } -/* Constant explanations: -0.145898 : 2x short golden ratio of 1.0 -0.0638587 : Squared value after 2x short golden ratio on RGB Euclidean distance -0.024391856 : Squared value after 2x short golden ratio + 1x golden ratio on RGB Euclidean distance -0.00931686 : Squared value after 3x short golden ratio on RGB Euclidean distance -0.001359312 : Squared value after 4x short golden ratio on RGB Euclidean distance -0.4377 : Squared value after 1x short golden ratio on RGB Euclidean distance -0.75 : Squared value after halving RGB Euclidean distance +/* Constant definitions: +0.145898 : Two short golden ratio splits of 1.0 +0.0638587 : Squared Euclidean RGB distance after two short golden ratio splits +0.024391856 : Squared Euclidean RGB distance after two short + one golden ratio split +0.00931686 : Squared Euclidean RGB distance after three short golden ratio splits +0.001359312 : Squared Euclidean RGB distance after four short golden ratio splits +0.4377 : Squared Euclidean RGB distance after one short golden ratio split +0.75 : Squared half Euclidean RGB distance */ -// Pixel similarity check LV1 +// Pixel similarity check - Level 1 +// pin zz bool sim1(vec4 col1, vec4 col2) { vec4 diff = col1 - col2; vec4 absdiff = abs(diff); // 1. Fast component difference check - if ( absdiff.r > 0.1 || absdiff.g > 0.1 || absdiff.b > 0.1 || absdiff.a > 0.145898 ) return false; // xxx.alpha + if ( absdiff.r > 0.1 || absdiff.g > 0.1 || absdiff.b > 0.1 || absdiff.a > 0.145898 ) return false; // 2. Fast squared distance check - float dot_diff = dot(diff.rgb, diff.rgb); // xxx.alpha + float dot_diff = dot(diff.rgb, diff.rgb); if (dot_diff < 0.001359312) return true; - // 3. Gradual pixel check + // 3. Gradient pixel check float min_diff = min(diff.r, min(diff.g, diff.b)); float max_diff = max(diff.r, max(diff.g, diff.b)); - if ( max_diff-min_diff>0.096 ) return false; // Exit if difference exceeds int24 - if ( max_diff-min_diff<0.024 && dot_diff<0.024391856) return true; // Consider gradual pixel if difference ≤ int6. Relax threshold by one level. + if ( max_diff-min_diff>0.096 ) return false; // Reject if difference exceeds int24 + if ( max_diff-min_diff<0.024 && dot_diff<0.024391856) return true; // Treat as gradient if difference <= int6, wider threshold // 4. Grayscale pixel check - float sum1 = dot(col1.rgb, vec3(1.0)); // Sum of RGB channels //xxx.alpha - float sum2 = dot(col2.rgb, vec3(1.0)); //xxx.alpha + float sum1 = dot(col1.rgb, vec3(1.0)); // Sum RGB channels + float sum2 = dot(col2.rgb, vec3(1.0)); float avg1 = sum1 * 0.3333333; float avg2 = sum2 * 0.3333333; - vec3 graydiff1 = col1.rgb - vec3(avg1); //xxx.alpha - vec3 graydiff2 = col2.rgb - vec3(avg2); //xxx.alpha + vec3 graydiff1 = col1.rgb - vec3(avg1); + vec3 graydiff2 = col2.rgb - vec3(avg2); float dotgray1 = dot(graydiff1,graydiff1); float dotgray2 = dot(graydiff2,graydiff2); - // 0.002: Max single-channel difference allowed is int13 when avg=20. - // 0.0004: Max single-channel difference allowed is int6, or int3+4 for dual channels + // 0.002: Allow single-channel diff up to int13 when avg=20. 0.0004: Allow single-channel diff up to int6, dual-channel int3+4 float tolerance1 = avg1<0.08 ? 0.002 : 0.0004; float tolerance2 = avg2<0.08 ? 0.002 : 0.0004; - // 0.078 limits max green channel value to 19 (perceptible threshold to human eye) + // 0.078: Max green channel = 19, perceptible limit to human eye bool Col1isGray = sum1<0.078||dotgray10.381966) return false; - - // 1. Clamp RGB dark areas - vec3 clampCol1 = max(col1.rgb, vec3(0.078)); //xxx.alpha - vec3 clampCol2 = max(col2.rgb, vec3(0.078)); //xxx.alpha + // 1. Clamp dark regions + vec3 clampCol1 = max(col1, vec3(0.078)); + vec3 clampCol2 = max(col2, vec3(0.078)); vec3 clampdiff = clampCol1 - clampCol2; - // 2x short + 1x, 2x short golden ratio of RGB Euclidean distance between two points - float dotdist = Lv==2 ? 0.024391856 : 0.0638587; - - return dot(clampdiff, clampdiff) < dotdist; + return dot(clampdiff, clampdiff); } -bool sim2(vec4 colC1, uint C1, uint C2) { +// Pixel similarity check - Level 2 / Level 3 +bool vi_sim2(vec4 colC1, uint C1, uint C2) { if (C1==C2) return true; - return sim2n3(colC1, unpackUnorm4x8(C2), 2); + vec4 colC2 = unpackUnorm4x8(C2); + // Ignore RGB if both pixels are near-transparent + if ( colC1.a < 0.381966 && colC2.a < 0.381966 ) return true; + // Alpha difference must not exceed 0.382 + if ( abs(colC1.a-colC2.a)>0.381966) return false; + + return rgbDist(colC1.rgb, colC2.rgb) < 0.024391856; +} + +bool sim2(vec4 col1, vec4 col2) { + // Ignore RGB if both pixels are near-transparent + if ( col1.a < 0.381966 && col2.a < 0.381966 ) return true; + // Alpha difference must not exceed 0.382 + if ( abs(col1.a-col2.a)>0.381966) return false; + return rgbDist(col1.rgb, col2.rgb) < 0.024391856; } bool sim3(vec4 col1, vec4 col2) { - return sim2n3(col1, col2, 3); + // Ignore RGB if both pixels are near-transparent + if ( col1.a < 0.145898 && col2.a < 0.145898 ) return true; + // Alpha difference must not exceed 0.382 + if ( abs(col1.a-col2.a)>0.381966) return false; + return rgbDist(col1.rgb, col2.rgb) < 0.0638587; } bool mixcheck(vec4 col1, vec4 col2) { - // Do not mix if either is transparent //xxx.alpha - bool col1alpha0 = col1.a < 0.003; - bool col2alpha0 = col2.a < 0.003; - if (col1alpha0!=col2alpha0) return false; + // Transparent pixels filtered out externally + vec4 diff = col1 - col2; + // Reject mixing if alpha difference exceeds half range + if ( abs(diff.a) > 0.5 ) return false; - // Cannot mix if transparency difference exceeds 50% //xxx.alpha - if (abs(col1.a - col2.a)>0.5) return false; - - vec3 diff = col1.rgb - col2.rgb; - - // Gradual pixel check + // Gradient pixel check float min_diff = min(diff.r, min(diff.g, diff.b)); float max_diff = max(diff.r, max(diff.g, diff.b)); if ( max_diff-min_diff>0.618034 ) return false; - float dot_diff = dot(diff, diff); - if( max_diff-min_diff<0.024 && dot_diff<0.75) return true; // 0.020 ≤ int5 0.024 ≤ int6 + float dot_diff = dot(diff.rgb, diff.rgb); + if( max_diff-min_diff<0.024 && dot_diff<0.75) return true; // 0.020 <= int5, 0.024 <= int6 - // Accumulate positive/negative values separately using max/min - float team_pos = abs(dot(max(diff, 0.0), vec3(1.0))); - float team_neg = abs(dot(min(diff, 0.0), vec3(1.0))); - // Find opposing channels and add to squared distance for judgment + // Accumulate positive/negative values using max/min + float team_pos = abs(dot(max(diff.rgb, 0.0), vec3(1.0))); + float team_neg = abs(dot(min(diff.rgb, 0.0), vec3(1.0))); + // Add opposing channel to squared distance before final check float team_rebel = min(team_pos, team_neg); - // Empirical: At least 3x opposing channel value needs to be added. (+1x to break even, +2x to form increasing trend) + // Empirically requires at least 3x opposing channel value (1x neutralizes, 2x creates upward trend) return dot_diff + team_rebel*team_rebel*3.0 < 0.4377; } -// RGB must be identical, small alpha channel difference allowed +// RGB must match, minor alpha differences allowed bool eq(uint C1, uint C2){ if (C1 == C2) return true; @@ -178,10 +182,10 @@ bool eq(uint C1, uint C2){ uint alphaC1 = C1 >> 24; uint alphaC2 = C2 >> 24; - // Note: abs(alphaC1-alphaC2) cannot be used with uint! + // Note: uint cannot use abs(alphaC1-alphaC2)! uint alphaDiff = (alphaC1 > alphaC2) ? (alphaC1 - alphaC2) : (alphaC2 - alphaC1); - return alphaDiff < 38u; //2x short golden ratio of 255u + return alphaDiff < 38u; // Two short golden ratio splits of 255u } @@ -189,7 +193,7 @@ bool eq(uint C1, uint C2){ bool vec_noteq(vec4 col1, vec4 col2) { vec4 diff = abs(col1 - col2); - // Allow total RGB channel difference of int2, alpha channel difference of int5 + // Allow total RGB diff <= int2, alpha diff <= int5 return dot(diff.rgb, vec3(1.0)) > 0.008 || diff.a > 0.021286; } @@ -231,9 +235,9 @@ bool none_eq2(uint B, uint A0, uint A1) { #define writeJKLM writeColorf(destXY,J);writeColorf(destXY+ivec2(1,0),K);writeColorf(destXY+ivec2(0,1),L);writeColorf(destXY+ivec2(1,1),M) //pin zz -// Concave + Cross shape - weak blending (weak/none) +// Concave + Cross pattern - Weak blending (weak/none) vec4 admixC(vec4 colX, vec4 colE) { - // Transparent pixels already filtered in main line + // Transparent pixels filtered out in main logic bool mixok = mixcheck(colX, colE); @@ -241,9 +245,9 @@ vec4 admixC(vec4 colX, vec4 colE) { } -// K shape - forced weak blending (weak/weaker) +// K-pattern - Forced weak blending (weaker) vec4 admixK(vec4 colX, vec4 colE) { - // Transparent pixels already filtered in main line + // Transparent pixels filtered out in main logic bool mixok = mixcheck(colX, colE); @@ -251,14 +255,13 @@ vec4 admixK(vec4 colX, vec4 colE) { } -// L shape 2:1 slope - extension of main corner -// Note: This rule requires all 4 pixels on the slope to be identical. Otherwise, various visual artifacts will appear! +// L-pattern - 2:1 slope - Main corner extension +// Practical rule: This requires 4 pixels on strict slope to be identical, otherwise severe aliasing occurs! vec4 admixL(vec4 colX, vec4 colE, vec4 colS) { - // Check eqX,E: originally captured large number of duplicate pixels, now filtered via slopeok in main line. + // Original eq(X,E) check caught many duplicate pixels; now filtered by slopeok in main logic - // If target X differs from reference S (sample), it means blending has already occurred once. - // Copy directly without re-blending + // Copy directly if target X differs from sample S (already blended once), no re-blend if (vec_noteq(colX, colS)) return colX; bool mixok = mixcheck(colX, colE); @@ -266,40 +269,36 @@ vec4 admixL(vec4 colX, vec4 colE, vec4 colS) { return mixok ? Mix382 : colX; } -/******************************************************************************************************************************************** - * main slope + X cross-processing mechanism * - *******************************************************************************************************************************************/ -vec4 admixX(uint A, uint B, uint C, uint D, uint E, uint F, uint G, uint H, uint I, uint P, uint PA, uint PC, uint Q, uint QA, uint QG, uint R, uint RC, uint RI, uint S, uint SG, uint SI, uint AA, uint CC, uint GG, float El, float Bl, float Dl, float Fl, float Hl, vec4 colE, vec4 colB, vec4 colD) { +/************************************************************************************************************************************** + * main slope + X cross-processing mechanism * + ******************************************************************************************************************************** zz */ +vec4 admixX(uint A, uint B, uint C, uint D, uint E, uint F, uint G, uint H, uint I, + uint P, uint PA, uint PC, uint Q, uint QA, uint QG, uint R, uint RC, uint RI, uint S, uint SG, uint SI, uint AA, uint CC, uint GG, + float El, float Bl, float Dl, float Fl, float Hl, + vec4 colE, vec4 colB, vec4 colD, vec4 colC, vec4 colG, + bool eq_B_D, bool eq_F_H, bool eq_E_A, bool eq_E_C, bool eq_E_G, bool eq_E_I, bool eq_E_F, bool eq_E_H) { - // xxx.alpha - // 1. Normal rule: center E has higher luma - transparency in BD is illogical - // 2. B/D may be transparent when E-A are identical, but using transparent B/D to cut solid crossed E-A violates design - if (colB.a<0.002||colD.a<0.002) return slopeBAD; bool eq_B_C = eq(B, C); bool eq_D_G = eq(D, G); - // Exit if surrounded by straight walls on both sides + // Exit if enclosed by dual straight walls if (eq_B_C && eq_D_G) return slopeBAD; - //Pre-declare - bool eq_A_B; bool eq_A_D; bool eq_A_P; bool eq_A_Q; + // Pre-declare variables + bool eq_A_B; bool eq_A_D; bool eq_A_P; bool eq_A_Q; bool eq_B_P; bool eq_B_PA; bool eq_B_PC; bool eq_D_Q; bool eq_D_QA; bool eq_D_QG; - bool eq_E_F; bool eq_E_H; bool eq_E_I; bool En3; bool B_slope; bool B_tower; bool B_wall; bool D_slope; bool D_tower; bool D_wall; vec4 colX; bool Xisblack; bool mixok; - - bool eq_B_D = eq(B,D); - bool eq_E_A = eq(E,A); + bool comboA3; bool En3; - #define comboA3 eq_A_P && eq_A_Q #define En4square En3 && eq_E_I - // E is nearly transparent but not fully transparent - mostly edges //xxx.alpha - bool EalphaL = colE.a <0.381966 && colE.a >0.002; + // E is near-transparent (not fully) - essentially an edge pixel + bool EalphaL = colE.a >0.002 && colE.a <0.381966; // Remove alpha channel weighting Bl = fract(Bl) *10.0; @@ -313,91 +312,102 @@ vec4 admixX(uint A, uint B, uint C, uint D, uint E, uint F, uint G, uint H, uint ==================================== zz */ if (!eq_B_D){ - // Exit if E-A equality violates preset logic + // Exit if E == A (violates expected logic) if (eq_E_A) return slopeBAD; - // Exit if B/D differ significantly (greater than E's difference with either side) + // Exit if B and D differ more than either differs from center E float diffBD = abs(Bl-Dl); if (diffBD > diffEB || diffBD > diffED) return slopeBAD; - // Avoid single-pixel font edges being squeezed by black background on both sides - // (Brightness difference between font and background usually exceeds 0.5) - // Note: If BD are not equal, cannot use average for judgment - both must meet black condition + // Prevent single-pixel font edges from being crushed by black background (luminance diff > 0.5) + // Note: If B != D, use both black checks, not average Xisblack = checkblack(colB) && checkblack(colD); if ( Xisblack && El >0.5 && (Fl<0.078 || Hl<0.078) ) return theEXIT; -// Exclusion rule before original logic (triangle vertices cannot protrude) + // Exclusion rule before original logic (triangular vertices cannot protrude) eq_A_B = eq(A,B); if ( !Xisblack && eq_A_B && eq_D_G && eq(B,P) ) return slopeBAD; eq_A_D = eq(A,D); if ( !Xisblack && eq_A_D && eq_B_C && eq(D,Q) ) return slopeBAD; - // B/D unconnected to any? Not applicable here (eliminates some artifacts but loses shapes, - // especially non-native pixel art like Double Dragon attract mode character sprites) + // B and D are isolated? Not applicable here (fixes some artifacts but loses shapes, e.g. Double Dragon attract mode character art) - // X is blend of B/D + // X is B/D 50/50 blend colX = mix(colB, colD, 0.5); - colX.a = min(colB.a, colD.a); // xxx.alpha + colX.a = min(colB.a, colD.a); - mixok = mixcheck(colX,colE); + mixok = E!=0u && mixcheck(colX,colE); eq_A_P = eq(A,P); eq_A_Q = eq(A,Q); - // A-side triple consecutive (eq_A_P && eq_A_Q) - high priority + comboA3 = eq_A_P && eq_A_Q; + // High priority: 3-in-a-row on A side if (comboA3) return mixok ? Mix382off : Xoff; - // Official original rule - if ( eq(E,C) || eq(E,G) ) return mixok ? Mix382off : Xoff; + // Original official rule + if ( eq_E_C || eq_E_G ) return mixok ? Mix382off : Xoff; - // Enhanced original rule 1 - good at capturing trends, but enhanced 2 cannot be used (wall bypass issue) - if ( !eq_D_G&&eq(E,QG)&&sim2(colE,E,G) || !eq_B_C&&eq(E,PC)&&sim2(colE,E,C) ) return mixok ? Mix382off : Xoff; + // Original rule enhancement 1 - Catches trends well, enhancement 2 disabled (wall bypass issue) + if ( !eq_D_G&&eq(E,QG)&&sim2(colE,colG) || !eq_B_C&&eq(E,PC)&&sim2(colE,colC) ) return mixok ? Mix382off : Xoff; - // Exclude "3-pixel single-side wall" case + // Exclude 3-pixel single-side wall cases if (!Xisblack){ if ( eq_A_B&&eq_B_C || eq_A_D&&eq_D_G ) return slopeBAD; } - //xxx.alpha if (EalphaL) return mixok ? Mix382off : Xoff; - // F-H inline trend (includes En3) - placed after wall rules since blocked by 3-pixel wall rule - if ( eq(F,H) ) return mixok ? Mix382off : Xoff; + // F-H inline trend (includes En3), blocked by 3-pixel wall rule so placed after + if ( eq_F_H ) return mixok ? Mix382off : Xoff; - // Remaining "2-pixel single-side wall" and unlogical single pixels - abandon + // Abort remaining 2-pixel walls and random single pixels return slopeBAD; } // B != D /******* B == D prepare *******/ - // Avoid single-pixel font edges being squeezed by black background on both sides + // Prevent font edges from being crushed on 3 sides by black background Xisblack = checkblack(colB); if ( Xisblack && El >0.5 && (Fl<0.078 || Hl<0.078) ) return theEXIT; colX = colB; colX.a = min(colB.a , colD.a); - bool eq_E_C = eq(E,C); - bool eq_E_G = eq(E,G); - bool sim_EC = eq_E_C || sim2n3(colE,unpackUnorm4x8(C),2); - bool sim_EG = eq_E_G || sim2n3(colE,unpackUnorm4x8(G),2); + float distEC = float(!eq_E_C); + float distEG = float(!eq_E_G); + if (!eq_E_C) { + if ( colE.a<0.381966 && colC.a<0.381966 ) { // Ignore RGB if both near-transparent + distEC = 0.0; + } else if (abs(colE.a-colC.a)<0.381966) distEC = rgbDist(colE.rgb, colC.rgb); + } + if (!eq_E_G) { + if ( colE.a<0.381966 && colG.a<0.381966 ) { // Ignore RGB if both near-transparent + distEC = 0.0; + } else if (abs(colE.a-colG.a)<0.381966) distEG = rgbDist(colE.rgb, colG.rgb); + } + + bool sim_EC = distEC < 0.024391856; + bool sim_EG = distEG < 0.024391856; + + bool comboE3 = eq_E_C && eq_E_G; bool ThickBorder; /*=============================================== - Original main rule (sim2 enhanced) + Original main rules sim2 enhanced ========================================== zz */ if ( (sim_EC || sim_EG) && !eq_E_A ){ /* Logic: - 1. Handle non-blending for continuous border shapes + 1. Skip blending for continuous border shapes 2. Special handling for long slopes 3. Original rules - 4. Handle E-area inline (En4, En3, F-H etc.), remaining single strip and single pixel - 5. Handle L-shaped inner single strip and outer single strip - 5. Default fallback return + 4. Handle En4/En3/F-H inline patterns, remaining lines and single pixels + 5. Remove L-notch inner lines and outer lines + 6. Default fallback return */ eq_A_B = eq(B,A); @@ -413,208 +423,206 @@ if ( (sim_EC || sim_EG) && !eq_E_A ){ D_tower = eq_D_Q && !eq_D_QG && !eq_D_G && !eq_D_QA; - // B+ D+ each extend shape (strong shape) - no blending, return Xoff + // Strong shape: B/D both extend patterns if ( (B_slope||B_tower) && (D_slope||D_tower) && !eq_A_B) return Xoff; + mixok = E!=0u && mixcheck(colX,colE); eq_A_P = eq(A, P); eq_A_Q = eq(A, Q); - mixok = mixcheck(colX,colE); + comboA3 = eq_A_P && eq_A_Q; + ThickBorder = eq_A_B && (eq_A_P||eq_A_Q|| eq(A,AA)&&(eq_B_PA||eq_D_QA)); + if (ThickBorder && !Xisblack) mixok=false; - // A-side triple consecutive (eq_A_P && eq_A_Q) + // 3-in-a-row on A side if (comboA3) { - if (!eq_A_B) return Xoff; - else mixok=false; + if (!eq_A_B) return Xoff; // Hollow: return strong shape + else mixok=false; // Solid: disable blending } - // XE_messL B-D-E L-shape with sim2 high similarity WIP - // bool XE_messL = (eq_B_C && !sim_EG || eq_D_G && !sim_EC) ; + // 3-in-a-row on E side + if (comboE3) return mixok ? Mix382off : Xoff; + - eq_E_F = eq(E, F); B_wall = eq_B_C && !eq_B_PC && !eq_B_P; + D_wall = eq_D_G && !eq_D_QG && !eq_D_Q; - // Long slope (clear, non-thick solid edge - strong trend!) + // Clear long slope (non-thick border edge - strong trend!) // Special condition for long slopes if ( B_wall && D_tower ) { - if (eq_E_G || sim_EG&&eq(E,QG) ) { // Original rule + enhanced original + if (eq_E_G || sim_EG&&eq(E,QG) ) { // Original + enhanced rule if (eq_A_B) return mixok ? Mix382 : colX; // Has thickness return colX; // Hollow } - // Clear Z-shaped snake - exclude eq_A_B + XE_messL ??? - //if (eq_A_B && !XE_messL) return ; // Poor effect if (eq_A_B) return slopeBAD; - // 2-pixel with subsequent long slope + // 2-pixel with long slope continuation if (eq_E_F ) return colX; - // 1-pixel without subsequent long slope + // 1-pixel without long slope return Xoff; } - eq_E_H = eq(E, H); - D_wall = eq_D_G && !eq_D_QG && !eq_D_Q; - if ( B_tower && D_wall ) { - if (eq_E_C || sim_EC&&eq(E,PC) ) { // Original rule + enhanced original + if (eq_E_C || sim_EC&&eq(E,PC) ) { // Original + enhanced rule if (eq_A_B) return mixok ? Mix382 : colX; // Has thickness return colX; // Hollow } - // Clear Z-shaped snake - exclude eq_A_B + XE_messL ??? - //if (eq_A_B && !XE_messL) return ; // Poor effect if (eq_A_B) return slopeBAD; - // 2-pixel with subsequent long slope + // 2-pixel with long slope continuation if (eq_E_H ) return colX; - // 1-pixel without subsequent long slope + // 1-pixel without long slope return Xoff; } - // Official original rule (placed after special shapes - special shapes have designated no-blending!) - if (eq_E_C || eq_E_G) return mixok ? Mix382 : colX; + // Official original rules (placed after special shapes - they specify no blending!) + // Fixes for original rules + if (eq_E_C ) { + if (eq_A_B && eq_B_PA && !eq_B_PC && eq_E_F && eq(E,P)) return theEXIT; + return mixok ? Mix382 : colX; + } - // Enhanced original rule 1 + if (eq_E_G) { + if (eq_A_B && eq_D_QA && !eq_D_QG && eq_E_H && eq(E,Q)) return theEXIT; + return mixok ? Mix382 : colX; + } + + // Original rule enhancement 1 if (sim_EG&&!eq_D_G&&eq(E,QG) || sim_EC&&!eq_B_C&&eq(E,PC)) return mixok ? Mix382off : Xoff; - // Enhanced original rule 2 + // Original rule enhancement 2 if (sim_EC && sim_EG) return mixok ? Mix382off : Xoff; - // F-H inline trend (skip En4, En3) - if ( eq(F,H) ) return mixok ? Mix382off : Xoff; + // F-H inline trend (skip En4/En3) + if ( eq_F_H ) return mixok ? Mix382off : Xoff; - // Relaxed rule for final long slope cleanup (non-clear shapes) - // Empirical: This block handles different slopes than F-H. Default to break-even unless cube shape. + // Cleanup final long slopes (non-clear shapes) + // Practical: This section cleans slopes differently than F-H - default neutral unless cube if (eq_B_C && eq_D_Q) { - // Exit for double cube + // Double cube: exit if (eq_B_P && eq_B_PC && eq_A_B && eq_D_QA && !eq_D_QG && eq_E_F && eq(H,I) ) return theEXIT; return mixok ? Mix382off : Xoff; } if ( eq_D_G && eq_B_P) { - // Exit for double cube + // Double cube: exit if (eq_D_Q && eq_D_QG && eq_A_B && eq_B_PA && !eq_B_PC && eq_E_H && eq(F,I) ) return theEXIT; return mixok ? Mix382off : Xoff; } - eq_E_I = eq(E, I); - // Exit for clear L-shaped corner with inner parallel single strip + // Exit for clear L-notch inner parallel line if (eq_A_B && !ThickBorder && !eq_E_I ) { if (B_wall && eq_E_F) return theEXIT; if (D_wall && eq_E_H) return theEXIT; } - // Early return if colors are similar (skip next step) + // Early return if colors are similar if (mixok) return Mix382off; - if (EalphaL) return mixok ? Mix382off : Xoff; //xxx.alpha + if (EalphaL) return mixok ? Mix382off : Xoff; - // Exit for hollow L-shaped corner with outer single strip (any direction) - fixes font edge issues + // Exit for hollow L-corner outer line (fixes font edge artifacts) if ( !eq_A_B && (eq_E_F||eq_E_H) && !eq_E_I) { if (B_tower && !eq_D_Q && !eq_D_QG) return theEXIT; if (D_tower && !eq_B_P && !eq_B_PC) return theEXIT; } - // Fallback handling + // Fallback handler return mixok ? Mix382off : Xoff; } // sim2 base /*=================================================== - E - A cross + E - A Cross ============================================== zz */ if (eq_E_A) { - // Cross ✕ judgment requires "region" and "trend" concepts - tighter conditions for different regions + // Cross checks need "region" and "trend" concepts - tighter conditions per region - // No need to exit for unconnected B/D! ! ! + // B/D isolated exit? Not needed here!!! - eq_E_F = eq(E, F); - eq_E_H = eq(E, H); - eq_E_I = eq(E, I); En3 = eq_E_F&&eq_E_H; - // Special shape: square (En3 && eq_E_I) + // Special shape: Square (En4square) if ( En4square ) { - if( noteq(G,H) && noteq(C,F) // Independent clear 4-pixel square / 6-pixel rectangle (both sides meet) + if( noteq(G,H) && noteq(C,F) // Independent clear 4-pixel square / 6-pixel rectangle (both sides valid) && (eq(H,S) == eq(I,SI) && eq(F,R) == eq(I,RI)) ) return theEXIT; - //else return mixok ? mix(X,E,0.381966) : X; Note: Do not return directly. Need to enter chessboard scoring rule, - // as adjacent B/D areas may also form bubbles with squares + //else return mixok ? mix(X,E,0.381966) : X; Do NOT return directly - enter checkerboard rule (adjacent B/D may form bubbles) } - // Special shape: dot pattern - // Empirical 1: !eq_E_F, !eq_E_H - do not use !sim (loses some shapes) - // Empirical 2: Force blending (otherwise lose shapes - Horse from Gouketsuji Ichizoku, Saturday Night Slam Masters 2) + // Special shape: Dithering pattern + // Practical 1: Use !eq_E_F / !eq_E_H (not !sim) to preserve shapes + // Practical 2: Force blending to preserve shapes (Karnov's Revenge, Muscle Bomber 2) bool Eisblack = checkblack(colE); - mixok = mixcheck(colX,colE); + mixok = E!=0u && mixcheck(colX,colE); - // 1. Dot pattern center - if ( eq_E_C && eq_E_G && eq_E_I && !eq_E_F && !eq_E_H ) { + // 1. Dithering center + if ( comboE3 && eq_E_I && !eq_E_F && !eq_E_H ) { - // Exit if center E is black (KOF '96 power bar, Punisher's belt) - avoid over-blending with high contrast + // Exit if center E is black (KOF '96 power gauge, Punisher belt) - avoid high-contrast blending if (Eisblack) return theEXIT; - // Empirical 1: Do not capture black B points (normal logic entry) - // Empirical 2: No need to check eq_F_H separately (95%+ probability) + layered gradient in power bar, 0.5 fallback blending + // Practical 1: Skip black B checks (normal logic entry) + // Practical 2: No need for eq_F_H check (>95% chance) + gradient blending inside gauge, 0.5 fallback return mixok ? Mix382off : Mix618off; } + eq_B_PA = eq(B,PA); eq_A_P = eq(A,P); eq_A_Q = eq(A,Q); - eq_B_PA = eq(B,PA); + comboA3 = eq_A_P && eq_A_Q; - // 2. Dot pattern edge - if ( eq_A_P && eq_A_Q && eq(A,AA) && noteq(A,PA) && noteq(A,QA) ) { + // 2. Dithering edge + if ( comboA3 && eq(A,AA) && noteq(A,PA) && noteq(A,QA) ) { if (Eisblack) return theEXIT; - // Layered gradient edge - use strong blending + // Strong blend for gradient edges if ( !eq_B_PA && eq(PA,QA) ) return mixok ? Mix382off : Mix618off; - // Remaining perfect cross - definitely dot pattern edge, use weak blending - // Fallback weak blending - no need to specify power bar border case separately + // Remainder: perfect cross = dithering edge, weak blend + // Default weak blend - no explicit gauge border handling needed return mixok ? Mix618off : Mix854off; } - // xxx.alpha - if (colE.a<0.002) return colX; + // Early return X if center fully transparent + if (E==0u) return colX; eq_D_QA = eq(D,QA); eq_D_QG = eq(D,QG); eq_B_PC = eq(B,PC); - // 3. Half dot pattern - usually shadow expression on outline edges, use weak blending - if ( eq_E_C && eq_E_G && eq_A_P && eq_A_Q && - (eq_B_PC || eq_D_QG) && - eq_D_QA && eq_B_PA) { - //if (Eisblack) return ; Unnecessary + // 3. Half-dithering (usually silhouette shading) - weak blend + if ( comboE3 && comboA3 && + (eq_B_PC || eq_D_QG) && eq_D_QA && eq_B_PA) { return mixok ? Mix618off : Mix854off; - } + } - // 4. Quarter dot pattern - prone to ugly "pinkie effect" (Guile's Sonic Boom in SF2, Dino Crisis select screen) + // 4. Quarter-dithering (prevents ugly "finger" artifacts - SF2 Guile plane, Cadillacs and Dinosaurs character select) - if ( eq_E_C && eq_E_G && eq_A_P + if ( comboE3 && eq_A_P && eq_B_PA &&eq_D_QA && eq_D_QG && eq_E_H ) return mixok ? Mix618off : Mix854off; - if ( eq_E_C && eq_E_G && eq_A_Q + if ( comboE3 && eq_A_Q && eq_B_PA &&eq_D_QA && eq_B_PC && eq_E_F ) return mixok ? Mix618off : Mix854off; + // High priority: A-side 3-in-a-row (after dithering rules) + if (comboA3) return Xoff; - // E-side triple consecutive (must come after dot pattern) - if ( eq_E_C && eq_E_G ) return Xoff; - - // A-side triple consecutive (eq_A_P && eq_A_Q) - must come after dot pattern. - // Prefer blending over direct copy since E-A are identical - if (comboA3) return mixok ? Mix382off : Xoff; + // E-side 3-in-a-row (after comboA3) + if (comboE3) return mixok ? Mix382off : Xoff; - // B-D part of long slope + // B-D long slope components eq_B_P = eq(B,P); eq_D_Q = eq(D,Q); B_wall = eq_B_C && !eq_B_P; @@ -625,7 +633,7 @@ if (eq_E_A) { int scoreE = 0; int scoreB = 0; int scoreD = 0; int scoreZ = 0; -// E B D area chessboard scoring rule +// E/B/D Zone Checkerboard Scoring Rules // E Zone if (En3) { @@ -645,11 +653,11 @@ if (eq_E_A) { } if (scoreE==0) { - // Single strip + // Single line if (eq_E_F ||eq_E_H) return theEXIT; } - if ( eq(F,H) ) { + if ( eq_F_H ) { scoreE += 1; if ( scoreZ==0 && B_wall && (eq(F,R) || eq(G,H) || eq(F,I)) ) scoreZ = 1; if ( scoreZ==0 && D_wall && (eq(C,F) || eq(H,S) || eq(F,I)) ) scoreZ = 1; @@ -666,7 +674,7 @@ if (eq_E_A) { if (eq_B_PA) { scoreB -= 1; - scoreB -= int(eq_B_P); //Replace eq(P,PA) + scoreB -= int(eq_B_P); // Replace eq(P,PA) } // D Zone @@ -676,7 +684,7 @@ if (eq_E_A) { if (eq_D_QA) { scoreD -= 1; - scoreD -= int(eq_D_Q); //Replace eq(Q,QA) + scoreD -= int(eq_D_Q); // Replace eq(Q,QA) } int scoreFinal = scoreE + scoreB + scoreD + scoreZ ; @@ -687,7 +695,7 @@ if (eq_E_A) { if (scoreFinal == 1) return mixok ? Mix382 : colX; - // Final supplement: total score 0, no deductions in B/D areas - forms long slope shape + // Final: Zero score, no B/D penalties = long slope if (scoreB >= 0 && scoreD >=0) { if (B_wall&&D_tower) return colX; if (B_tower&&D_wall) return colX; @@ -699,28 +707,27 @@ if (eq_E_A) { /*========================================================= - F - H / B+ D+ extension new rule + F - H / B+ D+ Extension Rules ==================================================== zz */ -// This block differs from sim block - center point and related En4square/BD are naturally isolated by a wall -// Therefore judgment rules differ from sim side +// This section is logically walled off from sim section by center E/en4square/BD +// So detection rules differ from sim side eq_B_P = eq(B, P); eq_B_PC = eq(B, PC); eq_D_Q = eq(D, Q); eq_D_QG = eq(D, QG); - // Exit if B/D unconnected to any (Empirical: required for this branch block) + // Exit if B/D fully isolated (practical: required for this section) if ( !eq_B_C && !eq_B_P && !eq_B_PC && !eq_D_G && !eq_D_Q && !eq_D_QG ) return slopeBAD; - mixok = mixcheck(colX,colE); - eq_E_I = eq(E, I); + mixok = E!=0u && mixcheck(colX,colE); - // Exit if center E is single high-contrast pixel - // Tighten threshold if E is highlight + // Exit if center E is isolated high-contrast pixel + // Tighten threshold if E is bright float E_lumDiff = El > 0.92 ? 0.145898 : 0.381966; - // Large difference with surroundings - if ( !mixok && !eq_E_I && !EalphaL && abs(El-Fl)>E_lumDiff && abs(El-Hl)>E_lumDiff ) return slopeBAD; //xxx.alpha + // Large difference from neighbors + if ( !mixok && !eq_E_I && !EalphaL && distEC>0.0638587 && distEG>0.0638587&& abs(El-Fl)>E_lumDiff && abs(El-Hl)>E_lumDiff ) return slopeBAD; eq_A_B = eq(A, B); @@ -728,7 +735,7 @@ if (eq_E_A) { eq_A_Q = eq(A, Q); eq_B_PA = eq(B,PA); eq_D_QA = eq(D,QA); - + comboA3 = eq_A_P && eq_A_Q; ThickBorder = eq_A_B && (eq_A_P||eq_A_Q|| eq(A,AA)&&(eq_B_PA||eq_D_QA)); if (ThickBorder && !Xisblack) mixok=false; @@ -739,32 +746,31 @@ if (eq_E_A) { D_tower = eq_D_Q && !eq_D_QG && !eq_D_G && !eq_D_QA; if (!eq_A_B) { - // B + D + each extend shape - // Empirical 1: Looser conditions for one side if the other has clear shape - // Empirical 2: Outer side of "厂" shape break-even, inner side not break-even (can be tower but not wall) + // B + D + dual extension patterns + // Practical 1: Clear shape on one side = relaxed on other + // Practical 2: "厂" shape: flatten outer, not inner (tower allowed, wall not) if ( (B_slope||B_tower) && (eq_D_QG&&!eq_D_G||D_tower) ) return Xoff; if ( (D_slope||D_tower) && (eq_B_PC&&!eq_B_C||B_tower) ) return Xoff; - // A-side triple consecutive (eq_A_P && eq_A_Q) - high priority + // High priority: A-side 3-in-a-row + // Note: comboA3 only valid with !eq_A_B in this section if (comboA3) return Xoff; - // combo 2x2 as supplement to above + // 2x2 combo supplement if ( B_slope && eq_A_P ) return mixok ? Mix382off : Xoff; if ( D_slope && eq_A_Q ) return mixok ? Mix382off : Xoff; } - eq_E_F = eq(E, F); B_wall = eq_B_C && !eq_B_PC && !eq_B_P; - // Long slope (clear, non-solid edge - strong trend!) + // Clear long slope (non-solid edge - strong trend!) // Special condition for long slopes if ( B_wall && D_tower ) { if (eq_A_B ) return slopeBAD; - if (eq_E_F ) return colX; //wip: Test direct X no blending + if (eq_E_F ) return colX; // WIP: Test direct X no blend return mixok ? Mix382off : Xoff; } - eq_E_H = eq(E, H); D_wall = eq_D_G && !eq_D_QG&& !eq_D_Q; if ( B_tower && D_wall ) { @@ -773,7 +779,9 @@ if (eq_E_A) { return mixok ? Mix382off : Xoff; } - + // No need for hollow E processing beyond this point + if (E==0u) return theEXIT; + // sim3 has no fully transparent input bool sim_X_E = sim3(colX,colE); bool eq_G_H = eq(G, H); bool eq_C_F = eq(C, F); @@ -782,50 +790,49 @@ if (eq_E_A) { En3 = eq_E_F&&eq_E_H; - // 4-pixel rectangle inside wall (En3 && eq_E_I) - if ( En4square ) { // This square detection must come after previous rule + // Wall-enclosed 4-pixel rectangle (En4square) + if ( En4square ) { // Square check MUST come after previous rule if (sim_X_E) return mixok ? Mix382off : Xoff; - // Exit for solid L-shaped inner wrap (fixes font edge corners and non-rounded building corners (Mega Man 7)) + // Exit solid L-enclosure (fixes font corners & unrounded building edges - Mega Man 7) if ( (eq_B_C || eq_D_G) && eq_A_B ) return theEXIT; - //if (eq_H_S && eq_F_R) return theEXIT; // Extend both sides - // L-shaped inner wrap (hollow corner) / high-contrast independent clear 4-pixel square / 6-pixel rectangle (note rectangle edges) + // Independent clear 4/6-pixel rectangle (check rectangle edges) if ( ( eq_B_C&&!eq_G_H || eq_D_G&&!eq_C_F || !eq_G_H&&!eq_C_F&&diffEB>0.5) && (eq_H_S == eq(I, SI) && eq_F_R == eq(I, RI)) ) return theEXIT; return mixok ? Mix382off : Xoff; } - // Triangle inside wall + // Wall-enclosed triangle if ( En3 ) { if (sim_X_E) return mixok ? Mix382off : Xoff; - if (eq_H_S && eq_F_R) return theEXIT; // Extend both sides (building edges) - // Inner curve + if (eq_H_S && eq_F_R) return theEXIT; // Dual extension (building edges) + // Inner bend if (eq_B_C || eq_D_G) return mixok ? Mix382off : Xoff; - // Direct return if has thickness (Z-shaped snake can break-even outer curve below) + // Return directly if thick (Z-snake flattens below outer bends) if (eq_A_B) return mixok ? Mix382off : Xoff; - // Outer curve + // Outer bend if (eq_B_P || eq_D_Q) return theEXIT; return mixok ? Mix382off : Xoff; - // Final two rules based on experience - principle: connect inner L curve, not outer (Jimmy's eyebrows in Double Dragon) + // Empirical rules: connect inner L bends, not outer (Double Dragon Jimmy eyebrows) } // F - H - // Principle: connect inner L curve, not outer - if ( eq(F,H) ) { - if (sim_X_E||EalphaL) return mixok ? Mix382off : Xoff; //xxx.alpha - // Exit for solid L-shaped inner wrap - avoid single pixel squeezed by symmetric double wrap + // Rule: connect inner L bends, not outer + if ( eq_F_H ) { + if (sim_X_E||EalphaL) return mixok ? Mix382off : Xoff; + // Exit solid L-enclosure (prevents dual symmetric crushing of single pixels) if ( eq_B_C && eq_A_B && (eq_G_H||!eq_F_R) &&eq(F, I) ) return slopeBAD; if ( eq_D_G && eq_A_B && (eq_C_F||!eq_H_S) &&eq(F, I) ) return slopeBAD; - //Inner curve + // Inner bend if (eq_B_C && (eq_F_R||eq_G_H||eq(F, I))) return mixok ? Mix382off : Xoff; if (eq_D_G && (eq_C_F||eq_H_S||eq(F, I))) return mixok ? Mix382off : Xoff; - // E-I F-H cross breaks trend + // Break trend: E-I F-H cross if (eq_E_I) return slopeBAD; - // Outer Z-shape + // Z-shape outer if (eq_B_P && eq_A_B) return mixok ? Mix382off : Xoff; if (eq_D_Q && eq_A_B) return mixok ? Mix382off : Xoff; - // Outer curve - unless opposite side forms long L-shaped trend + // Outer bend unless opposite forms long L-trend if (eq_B_P && (eq_C_F&&eq_H_S)) return mixok ? Mix382off : Xoff; if (eq_D_Q && (eq_F_R&&eq_G_H)) return mixok ? Mix382off : Xoff; @@ -833,52 +840,47 @@ if (eq_E_A) { } - // Relaxed rule for final long slope cleanup (non-clear shapes) - // Note: This block handles different slopes than sim2 block - exit for solid corners + // Final long slope cleanup (non-clear shapes) + // Note: Different cleanup from sim2 section - exit solid corners if ( eq_B_C && eq_D_Q || eq_D_G && eq_B_P) { - // Note: Clear eq_A_B first - otherwise single edge pixels get "corner cut" (eternal secret) + // Critical: exit eq_A_B first (prevents corner pixel clipping - Eternal Secrets) if (eq_A_B) return theEXIT; return mixok ? Mix382off : Xoff; } - - // A-side triple consecutive - NEVER use without !eq_A_B ! ! ! ! ! ! ! ! - // if (comboA3) return X+slopeOFF; - - - // One more check for B + D bidirectional extension - higher priority than inner/outer L single strip below + // Final B+D dual extension catch (higher priority than L inner/outer lines) if ( (B_slope||B_tower) && (eq_D_QG&&!eq_D_G||D_tower) ) return Xoff; if ( (D_slope||D_tower) && (eq_B_PC&&!eq_B_C||B_tower) ) return Xoff; - // Exit for clear L-shaped corner with inner single strip (sim_X_E no exemption) + // Exit for clear L-notch inner line (not even sim_X_E exempt) if (eq_A_B && !ThickBorder && !eq_E_I ) { if (B_wall && eq_E_F) return theEXIT; if (D_wall && eq_E_H) return theEXIT; } -if (sim_X_E||EalphaL) return mixok ? Mix382off : Xoff; //xxx.alpha - // Exit for hollow L-shaped corner with outer single strip (connect inner corner, not outer) - // Empirical: Avoids font edge cutting (Captain Commando) +if (sim_X_E||EalphaL) return mixok ? Mix382off : Xoff; + // Exit for hollow L-corner outer line (connect inner, not outer) + // Practical: Prevents font edge clipping (Cadillacs and Dinosaurs) if ( (B_tower || D_tower) && (eq_E_F||eq_E_H) && !eq_A_B && !eq_E_I) return theEXIT; - // Final individual extension check for B or D + // Final B/D single extension checks - // Maximum distance usable for slope + // Max slope range if ( B_slope && !eq_A_B && eq(PC,CC) && noteq(PC,RC)) return mixok ? Mix382off : Xoff; if ( D_slope && !eq_A_B && eq(QG,GG) && noteq(QG,SG)) return mixok ? Mix382off : Xoff; - // Slope can use one less judgment point if X-E are close, with internal logic restrictions + // Relaxed slope check if X/E similar (with internal constraints) if ( mixok && !eq_A_B ) { if ( B_slope && (!eq_C_F||eq(F,RC)) ) return Mix382off; if ( D_slope && (!eq_G_H||eq(H,SG)) ) return Mix382off; } - // Exclude single strip for Z-shaped snake below (necessary) + // Exclude single lines before Z-snake (required) if ((eq_E_F||eq_E_H) && !eq_E_I ) return theEXIT; - // Z-shaped snake (eq_A_B has thickness, one side is tower (can be wall/slope) but other side cannot be tower/wall (naturally prohibited)) + // Z-snake (thick eq_A_B, one side tower/wall, other not) if ( eq_B_P && !eq_B_PA && !eq_D_Q && eq_A_B) return mixok ? Mix382off : Xoff; if ( eq_D_Q && !eq_D_QA && !eq_B_P && eq_A_B) return mixok ? Mix382off : Xoff; @@ -888,12 +890,12 @@ if (sim_X_E||EalphaL) return mixok ? Mix382off : Xoff; //xxx.alpha vec4 admixS(uint A, uint B, uint C, uint D, uint E, uint F, uint G, uint H, uint I, uint R, uint RC, uint RI, uint S, uint SG, uint SI, uint II, bool eq_B_D, bool eq_E_D, float El, float Bl, vec4 colE, vec4 colF) { - // ABC . - // QD🄴 🅵 🆁 Zone 4 - // 🅶 🅷 I + // A B C . + // Q D 🄴 🅵 🅁 Zone 4 + // 🅶 🅷 I // S - // Empirical 1: sim E B(C) conforms to original logic - E single pixel won't look abrupt when inserted by saw in practice - // Empirical 2: Can E equal I? Yes! + // Practical 1: sim E/B(C) follows original logic - no jarring saw insertion on single-pixel E + // Practical 2: E can equal I? YES! if (any_eq2(F,C,I)) return colE; //if (any_eq3(F,A,C,I)) return colE; @@ -907,7 +909,7 @@ vec4 admixS(uint A, uint B, uint C, uint D, uint E, uint F, uint G, uint H, uint Bl = fract(Bl) *10.0; El = fract(El) *10.0; - if ( ( eq_B_D&&eq(B,C)&&diffEB<0.381966 || eq_E_D&&sim2(colE,E,C) ) && + if ( ( eq_B_D&&eq(B,C)&&diffEB<0.381966 || eq_E_D&&vi_sim2(colE,E,C) ) && (any_eq3(I,H,S,RI) || eq(SI,RI)&¬eq(I,II)) ) return colF; return colE; @@ -935,15 +937,15 @@ void applyScaling(uvec2 xy) { bool eq_E_B = eq(E,B); bool eq_E_H = eq(E,H); -// Skip horizontal/vertical 3x1 +// Skip horizontal/vertical 3x1 lines if ( eq_E_D && eq_E_F || eq_E_B && eq_E_H) {writeJKLM;return;} bool eq_B_H = eq(B,H); bool eq_D_F = eq(D,F); -// Skip center surrounded by mirrored blocks +// Skip if center enclosed by mirror pixels if ( eq_B_H && eq_D_F ) {writeJKLM;return;} - // Capture 5x5 + // Fetch 5x5 neighborhood uint A = src(srcX-1, srcY-1); uint C = src(srcX+1, srcY-1); uint G = src(srcX-1, srcY+1); @@ -968,47 +970,73 @@ if ( eq_B_H && eq_D_F ) {writeJKLM;return;} uint II = src(srcX+2, srcY+2); // GG SG [S] SI II +// Unpack 8 neighbors + vec4 colA = unpackUnorm4x8(A); + vec4 colC = unpackUnorm4x8(C); + vec4 colG = unpackUnorm4x8(G); + vec4 colI = unpackUnorm4x8(I); vec4 colB = unpackUnorm4x8(B); vec4 colD = unpackUnorm4x8(D); vec4 colF = unpackUnorm4x8(F); vec4 colH = unpackUnorm4x8(H); - float Bl = luma(colB), Dl = luma(colD), El = luma(colE), Fl = luma(colF), Hl = luma(colH); +// Precompute luminance + float Bl = luma(colB); + float Dl = luma(colD); + float El = luma(colE); + float Fl = luma(colF); + float Hl = luma(colH); -// 1:1 slope rules (P95) +// Pre-calculate bool eq_B_D = eq(B,D); bool eq_B_F = eq(B,F); bool eq_D_H = eq(D,H); bool eq_F_H = eq(F,H); + bool eq_E_A = eq(E, A); + bool eq_E_C = eq(E, C); + bool eq_E_G = eq(E, G); + bool eq_E_I = eq(E, I); - // Center surrounded by any mirrored blocks + // Any mirror enclosure of center bool oppoPix = eq_B_H || eq_D_F; - // Flag for admixX entry via 1:1 slope rule + // Flags for 1:1 slope processing bool slope1 = false; bool slope2 = false; bool slope3 = false; bool slope4 = false; - // Standard pixel returned normally via 1:1 slope rule + // Valid standard pixel return from 1:1 slope bool slope1ok = false; bool slope2ok = false; bool slope3ok = false; bool slope4ok = false; - // slopeBAD: entered admixX but (at least one of JKLM) returns E point - // slopOFF: returned with OFF flag - no long slope calculation - bool slopeBAD_flag = false; + // slopeBAD: entered admixX but returned E (at least one of JKLM) + // slopOFF: returned with OFF flag - skip long slope processing // B - D - if ( (!eq_E_B&&!eq_E_D&&!oppoPix) && (!eq_D_H&&!eq_B_F) && (El>=Dl&&El>=Bl || eq(E,A)) && ( (El=Dl&&El>=Bl) && ( (El 1.0 ) { - if (J.b > 7.0 ) J=J-8.0; //slopOFF + if (J.b > 7.0 ) J=J-8.0; // slopOFF if (J.b == 4.0 ) { J=colE; writeJKLM; return; } - if (J.b == 2.0 ) J=colE; //slopeBAD + if (J.b == 2.0 ) J=colE; // slopeBAD } else slope1ok = true; } // B - F - if ( !slope1 && (!eq_E_B&&!eq_E_F&&!oppoPix) && (!eq_B_D&&!eq_F_H) && (El>=Bl&&El>=Fl || eq(E,C)) && ( (El=Bl&&El>=Fl) && ( (El 1.0 ) { if (K.b > 7.0 ) K=K-8.0; @@ -1021,8 +1049,15 @@ if ( eq_B_H && eq_D_F ) {writeJKLM;return;} } else {slope2ok = true;} } // D - H - if ( !slope1 && (!eq_E_D&&!eq_E_H&&!oppoPix) && (!eq_F_H&&!eq_B_D) && (El>=Hl&&El>=Dl || eq(E,G)) && ((El=Hl&&El>=Dl) && ((El 1.0 ) { if (L.b > 7.0 ) L=L-8.0; @@ -1035,8 +1070,15 @@ if ( eq_B_H && eq_D_F ) {writeJKLM;return;} } else {slope3ok = true;} } // F - H - if ( !slope2 && !slope3 && (!eq_E_F&&!eq_E_H&&!oppoPix) && (!eq_B_F&&!eq_D_H) && (El>=Fl&&El>=Hl || eq(E,I)) && ((El=Fl&&El>=Hl) && ((El 1.0 ) { if (M.b > 7.0 ) M=M-8.0; @@ -1050,59 +1092,59 @@ if ( eq_B_H && eq_D_F ) {writeJKLM;return;} } -// long gentle 2:1 slope (P100) +// Long gentle 2:1 slope (P100) bool longslope = false; - if (slope4ok && eq_F_H) { //zone4 long slope - // Extended original rule 1. Pass adjacent pixel to admixL third parameter to prevent double blending - // Extended original rule 2. No L-shape allowed in opposite two-pixel interval unless wall formed + if (slope4ok && eq_F_H) { // Zone 4 long slope + // Original rule ext 1: Pass adjacent pixel to admixL to prevent double-blend + // Original rule ext 2: No L-shape within opposite pixel gap unless wall formed if (eq(G,H) && eq(F,R) && noteq(R, RC) && (noteq(Q,G)||eq(Q, QA))) {L=admixL(M,L,colH); longslope = true;} - // vertical + // Vertical if (eq(C,F) && eq(H,S) && noteq(S, SG) && (noteq(P,C)||eq(P, PA))) {K=admixL(M,K,colF); longslope = true;} } - if (slope3ok && eq_D_H) { //zone3 long slope - // horizontal + if (slope3ok && eq_D_H) { // Zone 3 long slope + // Horizontal if (eq(D,Q) && eq(H,I) && noteq(Q, QA) && (noteq(R,I)||eq(R, RC))) {M=admixL(L,M,colH); longslope = true;} - // vertical + // Vertical if (eq(A,D) && eq(H,S) && noteq(S, SI) && (noteq(A,P)||eq(P, PC))) {J=admixL(L,J,colD); longslope = true;} } - if (slope2ok && eq_B_F) { //zone2 long slope - // horizontal + if (slope2ok && eq_B_F) { // Zone 2 long slope + // Horizontal if (eq(A,B) && eq(F,R) && noteq(R, RI) && (noteq(A,Q)||eq(Q, QG))) {J=admixL(K,J,colB); longslope = true;} - // vertical + // Vertical if (eq(F,I) && eq(B,P) && noteq(P, PA) && (noteq(I,S)||eq(S, SG))) {M=admixL(K,M,colF); longslope = true;} } - if (slope1ok && eq_B_D) { //zone1 long slope - // horizontal + if (slope1ok && eq_B_D) { // Zone 1 long slope + // Horizontal if (eq(B,C) && eq(D,Q) && noteq(Q, QG) && (noteq(C,R)||eq(R, RI))) {K=admixL(J,K,colB); longslope = true;} - // vertical + // Vertical if (eq(D,G) && eq(B,P) && noteq(P, PC) && (noteq(G,S)||eq(S, SI))) {L=admixL(J,L,colD); longslope = true;} } -// Exit after longslope formation - sawslope rarely forms on diagonal +// Long slope formed = exit (rare diagonal sawslope) bool skiprest = longslope; bool slopeok = slope1ok||slope2ok||slope3ok||slope4ok; -// Note: sawslope cannot exclude slopeOFF (few cases) and slopeBAD (very rare), but can exclude slopeok (strong shape) +// Note: sawslope cannot exclude slopeOFF (minor) / slopeBAD (rare), but CAN exclude slopeok (strong shapes) if (!skiprest && !oppoPix && !slopeok) { - // horizontal bottom + // Horizontal bottom if (!eq_E_H && none_eq2(H,A,C)) { // A B C ・ - // Q D 🄴 🅵 🆁 Zone 4 - // 🅶 🅷 I + // Q D 🄴 🅵 🅁 Zone 4 + // 🅶 🅷 I // S - // (!slope3 && !eq_D_H) clever combination - if ( (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_F_H && + // (!slope3 && !eq_D_H) chain is elegant + if ( (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_F_H && F!=0u && !eq_E_F && (eq_B_D || eq_E_D) && eq(R,H) && eq(F,G) ) { M = admixS(A,B,C,D,E,F,G,H,I,R,RC,RI,S,SG,SI,II,eq_B_D,eq_E_D,El,Bl,colE,colF); skiprest = true;} @@ -1111,20 +1153,20 @@ if (!skiprest && !oppoPix && !slopeok) { // 🆀 🅳 🄴 F R Zone 3 // G 🅷 🅸 // S - if ( !skiprest && (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_D_H && + if ( !skiprest && (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_D_H && D!=0u && !eq_E_D && (eq_B_F || eq_E_F) && eq(Q,H) && eq(D,I) ) { L = admixS(C,B,A,F,E,D,I,H,G,Q,QA,QG,S,SI,SG,GG,eq_B_F,eq_E_F,El,Bl,colE,colD); skiprest = true;} } - // horizontal up + // Horizontal up if ( !skiprest && !eq_E_B && none_eq2(B,G,I)) { // P // 🅐 🅑 C - // QD 🄴 🅵 🆁 Zone 2 + // QD 🄴 🅵 🅁 Zone 2 // G H I . - if ( (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_B_F && + if ( (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_B_F && F!=0u && !eq_E_F && (eq_D_H || eq_E_D) && eq(B,R) && eq(A,F) ) { K = admixS(G,H,I,D,E,F,A,B,C,R,RI,RC,P,PA,PC,CC,eq_D_H,eq_E_D,El,Hl,colE,colF); skiprest = true;} @@ -1133,21 +1175,21 @@ if (!skiprest && !oppoPix && !slopeok) { // A 🅑 🅲 // 🆀 🅳 🄴 F R Zone 1 // . G H I - if ( !skiprest && (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_B_D && + if ( !skiprest && (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_B_D && D!=0u && !eq_E_D && (eq_F_H || eq_E_F) && eq(B,Q) && eq(C,D) ) { J = admixS(I,H,G,F,E,D,C,B,A,Q,QG,QA,P,PC,PA,AA,eq_F_H,eq_E_F,El,Hl,colE,colD); skiprest = true;} } - // vertical left + // Vertical left if ( !skiprest && !eq_E_D && none_eq2(D,C,I) ) { // 🅐 B C // Q 🅳 🄴 F R // G 🅷 I Zone 3 // 🆂 ・ - if ( (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_D_H && + if ( (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_D_H && H!=0u && !eq_E_H && (eq_B_F || eq_E_B) && eq(D,S) && eq(A,H) ) { L = admixS(C,F,I,B,E,H,A,D,G,S,SI,SG,Q,QA,QG,GG,eq_B_F,eq_E_B,El,Fl,colE,colH); skiprest = true;} @@ -1156,21 +1198,21 @@ if (!skiprest && !oppoPix && !slopeok) { // A 🅑 C // Q 🅳 🄴 F R Zone 1 // 🅶 HI - if ( !skiprest && (!slope3 && !eq_D_H) && (!slope2 && !eq_B_F) && !eq_B_D && + if ( !skiprest && (!slope3 && !eq_D_H) && (!slope2 && !eq_B_F) && !eq_B_D && B!=0u && !eq_E_B && (eq_F_H || eq_E_H) && eq(P,D) && eq(B,G) ) { J = admixS(I,F,C,H,E,B,G,D,A,P,PC,PA,Q,QG,QA,AA,eq_F_H,eq_E_H,El,Fl,colE,colB); skiprest = true;} } - // vertical right + // Vertical right if ( !skiprest && !eq_E_F && none_eq2(F,A,G) ) { // right // A B 🅲 // Q D 🄴 🅵 R // G 🅷 I Zone 4 // . 🆂 - if ( (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_F_H && + if ( (!slope2 && !eq_B_F) && (!slope3 && !eq_D_H) && !eq_F_H && H!=0u && !eq_E_H && (eq_B_D || eq_E_B) && eq(S,F) && eq(H,C) ) { M = admixS(A,D,G,B,E,H,C,F,I,S,SG,SI,R,RC,RI,II,eq_B_D,eq_E_B,El,Dl,colE,colH); skiprest = true;} @@ -1179,7 +1221,7 @@ if (!skiprest && !oppoPix && !slopeok) { // A 🅑 C // Q D 🄴 🅵 R Zone 2 // G H 🅸 - if ( !skiprest && (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_B_F && + if ( !skiprest && (!slope1 && !eq_B_D) && (!slope4 && !eq_F_H) && !eq_B_F && B!=0u && !eq_E_B && (eq_D_H || eq_E_H) && eq(P,F) && eq(B,I) ) { K = admixS(G,D,A,H,E,B,I,F,C,P,PA,PC,R,RI,RC,CC,eq_D_H,eq_E_H,El,Dl,colE,colB); skiprest = true;} @@ -1187,19 +1229,19 @@ if (!skiprest && !oppoPix && !slopeok) { } // vertical right } // sawslope -// Exit after sawslope formation - legacy approach: skiprest||slopeBAD (also uses slopeOFF (weak) and slopok (strong) but poor effect) -skiprest = skiprest||slope1||slope2||slope3||slope4||El>7.0||Bl>7.0||Dl>7.0||Fl>7.0||Hl>7.0; +// sawslope formed = exit; legacy: skiprest||slopeBAD (uses slopeOFF/ok with weak effect) +skiprest = skiprest||slope1||slope2||slope3||slope4||E==0u||B==0u||D==0u||F==0u||H==0u; /************************************************** - Concave + Cross shape (P100) + Concave + Cross pattern (P100) *************************************************/ -// Use approximate pixels for cross star far end - useful for horizontal line + sawtooth and layered gradient shapes. -// E.g. glowing text in SFIII: New Generation intro, Japanese houses in SFZ3 Mix, Fatal Fury: Wild Ambition intro +// Cross distant uses similar pixels - useful for horizontal lines + aliasing / gradient text +// e.g. SF2III intro glowing text, SFZ3mix Japanese houses, Garou intro - vec4 colX; //Define temp X + vec4 colX; // Temporary X if (!skiprest && - Bl7.0||Bl>7.0||Dl>7.0||Fl> } if (!skiprest && - Hl7.0||Bl>7.0||Dl>7.0||Fl> } if (!skiprest && - Fl7.0||Bl>7.0||Dl>7.0||Fl> } if (!skiprest && - Dl7.0||Bl>7.0||Dl>7.0||Fl> } /* - ✕О + ✕О ООО✕ - ✕О Scorpion Type (P99). It looks a lot like the tracking bug from The Matrix. - Can match some regularly interleaved pixels. + ✕О Scorpion pattern (P99). Resembles Matrix tracker bugs. Flattens regular dithered pixels. */ -// Practice Notes: 1. Using approximations for the scorpion's pincers? -// This is prone to causing graphical glitches. -// Practice Notes: 2. Removing one grid cell from the scorpion's tail captures more patterns. -// Among the four patterns, only the scorpion type is exclusive — -// once a previous rule has captured it (i.e., it has been matched), this pattern will not appear. +// Practical: 1. Scorpion claws use similarity? Causes graphical artifacts +// Practical: 2. Shorten scorpion tail by 1 pixel to catch more shapes +// Scorpion is exclusive - won't trigger if any prior rule ran - if (!skiprest && !eq_E_F &&eq_E_D&&eq_B_F&&eq_F_H && all_eq2(E,C,I) && noteq(F,src(srcX+3, srcY)) ) {K=admixK(colF,K); M=K;J=mix(K,J, 0.61804); L=J;skiprest=true;} // RIGHT - if (!skiprest && !eq_E_D &&eq_E_F&&eq_B_D&&eq_D_H && all_eq2(E,A,G) && noteq(D,src(srcX-3, srcY)) ) {J=admixK(colD,J); L=J;K=mix(J,K, 0.61804); M=K;skiprest=true;} // LEFT - if (!skiprest && !eq_E_H &&eq_E_B&&eq_D_H&&eq_F_H && all_eq2(E,G,I) && noteq(H,src(srcX, srcY+3)) ) {L=admixK(colH,L); M=L;J=mix(L,J, 0.61804); K=J;skiprest=true;} // BOTTOM - if (!skiprest && !eq_E_B &&eq_E_H&&eq_B_D&&eq_B_F && all_eq2(E,A,C) && noteq(B,src(srcX, srcY-3)) ) {J=admixK(colB,J); K=J;L=mix(J,L, 0.61804); M=L;} // TOP + if (!skiprest && !eq_E_F &&eq_E_D&&eq_B_F&&eq_F_H && eq_E_C && eq_E_I && noteq(F,src(srcX+3, srcY)) ) {K=admixK(colF,K); M=K;J=mix(K,J, 0.61804); L=J;skiprest=true;} // RIGHT + if (!skiprest && !eq_E_D &&eq_E_F&&eq_B_D&&eq_D_H && eq_E_A && eq_E_G && noteq(D,src(srcX-3, srcY)) ) {J=admixK(colD,J); L=J;K=mix(J,K, 0.61804); M=K;skiprest=true;} // LEFT + if (!skiprest && !eq_E_H &&eq_E_B&&eq_D_H&&eq_F_H && eq_E_G && eq_E_I && noteq(H,src(srcX, srcY+3)) ) {L=admixK(colH,L); M=L;J=mix(L,J, 0.61804); K=J;skiprest=true;} // BOTTOM + if (!skiprest && !eq_E_B &&eq_E_H&&eq_B_D&&eq_B_F && eq_E_A && eq_E_C && noteq(B,src(srcX, srcY-3)) ) {J=admixK(colB,J); K=J;L=mix(J,L, 0.61804); M=L;} // TOP - // final Exit + // Final Exit writeJKLM; }