1const int char_width = 8; 2const int char_height = 13; 3const int char_count = 95; 4const int char_pixels = char_width*char_height; 5const float2 char_dim = float2(char_width, char_height); 6const float2 font_scale = float2(1.0/float(char_width)/float(char_count), 1.0/float(char_height)); 7 8void main() 9{ 10 float2 char_pos = floor(GetCoordinates()*GetResolution()/char_dim); 11 float2 pixel_offset = floor(GetCoordinates()*GetResolution()) - char_pos*char_dim; 12 13 // just a big number 14 float mindiff = float(char_width*char_height) * 100.0; 15 16 float minc = 0.0; 17 float4 mina = float4(0.0, 0.0, 0.0, 0.0); 18 float4 minb = float4(0.0, 0.0, 0.0, 0.0); 19 20 for (int i=0; i<char_count; i++) 21 { 22 float4 ff = float4(0.0, 0.0, 0.0, 0.0); 23 float4 f = float4(0.0, 0.0, 0.0, 0.0); 24 float4 ft = float4(0.0, 0.0, 0.0, 0.0); 25 float4 t = float4(0.0, 0.0, 0.0, 0.0); 26 float4 tt = float4(0.0, 0.0, 0.0, 0.0); 27 28 for (int x=0; x<char_width; x++) 29 { 30 for (int y=0; y<char_height; y++) 31 { 32 float2 tex_pos = char_pos*char_dim + float2(x,y) + 0.5; 33 float4 tex = SampleLocation(tex_pos * GetInvResolution()); 34 35 float2 font_pos = float2(x+i*char_width, y) + 0.5; 36 float4 font = SampleFontLocation(font_pos * font_scale); 37 38 // generates sum of texture and font and their squares 39 ff += font*font; 40 f += font; 41 ft += font*tex; 42 t += tex; 43 tt += tex*tex; 44 } 45 } 46 47 // The next lines are a bit harder, hf :-) 48 49 // The idea is to find the perfect char with the perfect background color and the perfect font color. 50 // As this is an equation with three unknowns, we can't just try all chars and color combinations. 51 52 // As criterion how "perfect" the selection is, we compare the "mean squared error" of the resulted colors of all chars. 53 // So, now the big issue: how to calculate the MSE without knowing the two colors ... 54 55 // In the next steps, "a" is the font color, "b" is the background color, "f" is the font value at this pixel, "t" is the texture value 56 57 // So the square error of one pixel is: 58 // e = ( t - a⋅f - b⋅(1-f) ) ^ 2 59 60 // In longer: 61 // e = a^2⋅f^2 - 2⋅a⋅b⋅f^2 + 2⋅a⋅b⋅f - 2⋅a⋅f⋅t + b^2⋅f^2 - 2⋅b^2⋅f + b^2 + 2⋅b⋅f⋅t - 2⋅b⋅t + t^2 62 63 // The sum of all errors is: (as shortcut, ff,f,ft,t,tt are now the sums like declared above, sum(1) is the count of pixels) 64 // sum(e) = a^2⋅ff - 2⋅a^2⋅ff + 2⋅a⋅b⋅f - 2⋅a⋅ft + b^2⋅ff - 2⋅b^2⋅f + b^2⋅sum(1) + 2⋅b⋅ft - 2⋅b⋅t + tt 65 66 // To find the minimum, we have to derive this by "a" and "b": 67 // d/da sum(e) = 2⋅a⋅ff + 2⋅b⋅f - 2⋅b⋅ff - 2⋅ft 68 // d/db sum(e) = 2⋅a⋅f - 2⋅a⋅ff - 4⋅b⋅f + 2⋅b⋅ff + 2⋅b⋅sum(1) + 2⋅ft - 2⋅t 69 70 // So, both equations must be zero at minimum and there is only one solution. 71 72 float4 a = (f*ft - ff*t + f*t - ft*float(char_pixels)) / (f*f - ff*float(char_pixels)); 73 float4 b = (f*ft - ff*t) / (f*f - ff*float(char_pixels)); 74 75 float4 diff = a*a*ff + 2.0*a*b*f - 2.0*a*b*ff - 2.0*a*ft + b*b *(-2.0*f + ff + float(char_pixels)) + 2.0*b*ft - 2.0*b*t + tt; 76 float diff_f = dot(diff, float4(1.0, 1.0, 1.0, 1.0)); 77 78 if (diff_f < mindiff) 79 { 80 mindiff = diff_f; 81 minc = float(i); 82 mina = a; 83 minb = b; 84 } 85 } 86 87 float2 font_pos_res = float2(minc * float(char_width), 0.0) + pixel_offset + 0.5; 88 89 float4 col = SampleFontLocation(font_pos_res * font_scale); 90 SetOutput(mina * col + minb * (float4(1.0,1.0,1.0,1.0) - col)); 91} 92