Advertisement
Guest User

Untitled

a guest
Feb 19th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.52 KB | None | 0 0
  1. // This file is part of the supplementary material for the paper
  2. // "GPU-Centered Font Rendering Directly from Glyph Outlines",
  3. // by Eric Lengyel. It is licensed under the Creative Commons
  4. // BY-NC-ND 4.0 license available here:
  5. //
  6. // https://creativecommons.org/licenses/by-nc-nd/4.0/
  7. //
  8. // Commercial use of this software requires a separate license
  9. // from the author. Copyright and additional IP protections apply.
  10.  
  11.  
  12. in vresult
  13. {
  14. vec4 vcolor; // Vertex color.
  15. vec2 texcoord; // Em-space glyph coordinates for pixel.
  16. flat uvec2 glyphParam; // Constant data for current glyph.
  17. flat vec3 bandParam; // Scale and offset for band indexes.
  18. };
  19.  
  20. uniform sampler2DRect curveTex; // Control point texture.
  21. uniform usampler2DRect bandTex; // Band data texture.
  22.  
  23. out vec4 fcolor;
  24.  
  25. const float kQuadraticEpsilon = 0.0001;
  26.  
  27. void main()
  28. {
  29. float coverage = 0.0;
  30.  
  31. // The effective pixel dimensions of the em square are computed
  32. // independently for x and y directions with texcoord derivatives.
  33.  
  34. vec2 pixelsPerEm = vec2(1.0 / fwidth(texcoord.x),
  35. 1.0 / fwidth(texcoord.y));
  36.  
  37. // The low 12 bits of each component of glyphParam give the coordinates
  38. // at which the glyph data begins in the index texture. Bits 12-15 give
  39. // one less than the number of bands in the x and y directions.
  40.  
  41. uvec2 glyphLoc = glyphParam & 0x0FFFU;
  42. uvec2 bandMax = glyphParam >> 12U;
  43.  
  44. // Determine what bands the current pixel lies in by applying a scale
  45. // and offset to the texture coordinates. The scale given by bandParam.z
  46. // is the same for both directions, but there are different offsets given
  47. // by bandParam.xy. Band indexes are clamped to [0, bandMax.xy].
  48.  
  49. uvec2 bandIndex = uvec2(clamp(ivec2(texcoord * bandParam.z
  50. + bandParam.xy), ivec2(0U, 0U), ivec2(bandMax)));
  51.  
  52. // Fetch data for the horizontal band from the index texture. The number
  53. // of curves intersecting the band is in the x component, and the offset
  54. // to the list of locations for those curves is in the y component.
  55.  
  56. uvec2 hbandData = texelFetch(bandTex,
  57. ivec2(glyphLoc.x + bandIndex.y, glyphLoc.y)).xy;
  58. uvec2 hbandLoc = uvec2(glyphLoc.x + hbandData.y, glyphLoc.y);
  59.  
  60. // If the offset caused the x coordinate to exceed 4096 (texture width),
  61. // then wrap to the next line.
  62.  
  63. hbandLoc.y += hbandLoc.x >> 12U;
  64. hbandLoc.x &= 0x0FFFU;
  65.  
  66. // Loop over all curves in the horizontal band.
  67.  
  68. for (uint curve = 0U; curve < hbandData.x; curve++)
  69. {
  70. // Fetch the location of the current curve from the index texture.
  71.  
  72. ivec2 curveLoc = ivec2(texelFetch(bandTex,
  73. ivec2(hbandLoc.x + curve, hbandLoc.y)).xy);
  74.  
  75. // Fetch the three 2D control points for the current curve from the
  76. // curve texture. The first texel contains both p1 and p2 in the
  77. // (x,y) and (z,w) components, respectively, and the the second texel
  78. // contains p3 in the (x,y) components. The quadratic Bézier curve
  79. // C(t) is given by
  80. //
  81. // C(t) = (1 - t)^2 p1 + 2t(1 - t) p2 + t^2 p3
  82.  
  83. vec4 p12 = texelFetch(curveTex, curveLoc) - vec4(texcoord, texcoord);
  84. vec2 p3 = texelFetch(curveTex, ivec2(curveLoc.x + 1, curveLoc.y)).xy
  85. - texcoord;
  86.  
  87. // If the largest x coordinate among all three control points falls
  88. // left of the current pixel, then there are no more curves in the
  89. // horizontal band that can influence the result, so exit the loop.
  90. // (The curves are sorted in descending order by max x coordinate.)
  91.  
  92. if (max(max(p12.x, p12.z), p3.x) * pixelsPerEm.x < -0.5) break;
  93.  
  94. // Generate the root contribution code based on the signs of the
  95. // y coordinates of the three control points.
  96.  
  97. uint code = (0x2E74U >> (((p12.y > 0.0) ? 2U : 0U) +
  98. ((p12.w > 0.0) ? 4U : 0U) + ((p3.y > 0.0) ? 8U : 0U))) & 3U;
  99.  
  100. if (code != 0U)
  101. {
  102. // At least one root makes a contribution, so solve for the
  103. // values of t where the curve crosses y = 0. The quadratic
  104. // polynomial in t is given by
  105. //
  106. // a t^2 - 2b t + c,
  107. //
  108. // where a = p1.y - 2 p2.y + p3.y, b = p1.y - p2.y, and c = p1.y.
  109. // The discriminant b^2 - ac is clamped to zero, and imaginary
  110. // roots are treated as a double root at the global minimum
  111. // where t = b / a.
  112.  
  113. float ax = p12.x - p12.z * 2.0 + p3.x;
  114. float ay = p12.y - p12.w * 2.0 + p3.y;
  115. float bx = p12.x - p12.z;
  116. float by = p12.y - p12.w;
  117. float ra = 1.0 / ay;
  118.  
  119. float d = sqrt(max(by * by - ay * p12.y, 0.0));
  120. float t1 = (by - d) * ra;
  121. float t2 = (by + d) * ra;
  122.  
  123. // If the polynomial is nearly linear, then solve -2b t + c = 0.
  124.  
  125. if (abs(ay) < kQuadraticEpsilon) t1 = t2 = p12.y * 0.5 / by;
  126.  
  127. // Calculate the x coordinates where C(t) = 0, and transform
  128. // them so that the current pixel corresponds to the range
  129. // [0,1]. Clamp the results and use them for root contributions.
  130.  
  131. float x1 = (ax * t1 - bx * 2.0) * t1 + p12.x;
  132. float x2 = (ax * t2 - bx * 2.0) * t2 + p12.x;
  133. x1 = clamp(x1 * pixelsPerEm.x + 0.5, 0.0, 1.0);
  134. x2 = clamp(x2 * pixelsPerEm.x + 0.5, 0.0, 1.0);
  135.  
  136. // Bits in code tell which roots make a contribution.
  137.  
  138. if ((code & 1U) != 0U) coverage += x1;
  139. if (code > 1U) coverage -= x2;
  140. }
  141. }
  142.  
  143. // Fetch data for the vertical band from the index texture. This follows
  144. // the data for all horizontal bands, so we have to add bandMax.y + 1.
  145.  
  146. uvec2 vbandData = texelFetch(bandTex,
  147. ivec2(glyphLoc.x + bandMax.y + 1U + bandIndex.x, glyphLoc.y)).xy;
  148. uvec2 vbandLoc = uvec2(glyphLoc.x + vbandData.y, glyphLoc.y);
  149.  
  150. // Wrap to the next line if necessary.
  151.  
  152. vbandLoc.y += vbandLoc.x >> 12U;
  153. vbandLoc.x &= 0x0FFFU;
  154.  
  155. // Loop over all curves in the vertical band.
  156.  
  157. for (uint curve = 0U; curve < vbandData.x; curve++)
  158. {
  159. ivec2 curveLoc = ivec2(texelFetch(bandTex,
  160. ivec2(vbandLoc.x + curve, vbandLoc.y)).xy);
  161.  
  162. vec4 p12 = texelFetch(curveTex, curveLoc) - vec4(texcoord, texcoord);
  163. vec2 p3 = texelFetch(curveTex, ivec2(curveLoc.x + 1, curveLoc.y)).xy
  164. - texcoord;
  165.  
  166. // If the largest y coordinate among all three control points falls
  167. // below the current pixel, then exit the loop.
  168.  
  169. if (max(max(p12.y, p12.w), p3.y) * pixelsPerEm.y < -0.5) break;
  170.  
  171. // Generate the root contribution code based on the signs of the
  172. // x coordinates of the three control points.
  173.  
  174. uint code = (0x2E74U >> (((p12.x > 0.0) ? 2U : 0U) +
  175. ((p12.z > 0.0) ? 4U : 0U) + ((p3.x > 0.0) ? 8U : 0U))) & 3U;
  176.  
  177. if (code != 0U)
  178. {
  179. // At least one root makes a contribution, so solve for the
  180. // values of t where the rotated curve crosses y = 0.
  181.  
  182. float ax = p12.y + p12.w * 2.0 + p3.y;
  183. float ay = p12.x - p12.z * 2.0 + p3.x;
  184. float bx = p12.y - p12.w;
  185. float by = p12.x - p12.z;
  186. float ra = 1.0 / ay;
  187.  
  188. float d = sqrt(max(by * by - ay * p12.x, 0.0));
  189. float t1 = (by - d) * ra;
  190. float t2 = (by + d) * ra;
  191.  
  192. if (abs(ay) < kQuadraticEpsilon) t1 = t2 = p12.x * 0.5 / by;
  193.  
  194. float x1 = (ax * t1 - bx * 2.0) * t1 + p12.y;
  195. float x2 = (ax * t2 - bx * 2.0) * t2 + p12.y;
  196. x1 = clamp(x1 * pixelsPerEm.y + 0.5, 0.0, 1.0);
  197. x2 = clamp(x2 * pixelsPerEm.y + 0.5, 0.0, 1.0);
  198.  
  199. if ((code & 1U) != 0U) coverage += x1;
  200. if (code > 1U) coverage -= x2;
  201. }
  202. }
  203.  
  204. // Take the average of the horizontal and vertical results. The absolute
  205. // value ensures that either winding convention works. The square root
  206. // approximates gamma correction.
  207.  
  208. coverage = sqrt(clamp(abs(coverage) * 0.5, 0.0, 1.0));
  209. float alpha = coverage * vcolor.w;
  210. fcolor = vec4(vcolor.xyz * alpha, alpha);
  211. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement