The Math Behind Font Rasterization | How it Works

แชร์
ฝัง
  • เผยแพร่เมื่อ 23 พ.ย. 2024

ความคิดเห็น • 275

  • @SimonBuchanNz
    @SimonBuchanNz 3 ปีที่แล้ว +240

    A few notes on what most actual implementations do (from what I've been able to read), just in case anyone thought this was simple:
    * Solving quadratics is (probably much) slower and harder than just subdividing until you're smaller than pixels then testing against the x coordinates of the points closest in y coordinates.
    * Generally the letters (or, more generally, glyphs) are only rendered once per font size when needed and then that copy is stamped at all the places it's needed.
    * It's common to use the fact that PC monitors layout their pixels in vertical RGB stripes to get more horizontal resolution.
    * At small sizes, avoiding blurring as lines cross through pixels is more important than exactly representing the outline. The solution is pretty crazy: TTF fonts include programs that execute to adjust the coordinates based on size... and potentially other things like weight and surrounding characters!
    * This doesn't work if you're animating, as you can see the outlines jumping around (and it's slow). In this and other situations, like very large text or 3d, signed distance fields (or SDF), which are basically fancier bitmaps that are quite good at approximating the outline but still very fast to render.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +35

      Hey Simon! Thanks for the great overview on some of the more technical details of font rendering :). I didn't know about the optimization you can use to avoid solving quadratics, and I'd be interested to try that out at some point. I also saw your comment about .bmp, and I do apologize for any inaccuracies there. I always forget to check some of the finer details when I make videos like this haha

    • @angeldude101
      @angeldude101 3 ปีที่แล้ว +5

      I thought something seemed fishy when a square root was being calculated for every pixel per curve. A prerendered cache would definitely help, but I'm not surprised that there was another possibility.

    • @groszak1
      @groszak1 3 ปีที่แล้ว

      @@GamesWithGabe I have a renderer called TD renderer. It is based on FreeType, however, it makes use of my own rasterizer.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +9

      @@angeldude101 actually square roots aren't nearly as much of a problem as they were 25 years ago. GPU's have special hardware to do square roots directly, and graphics developers typically do at least one (possibly multiple square roots) per pixel 60 times a second in games to calculate things like lighting. This article gives an interesting overview cuda-programming.blogspot.com/2013/01/performance-of-sqrt-in-cuda.html . But font rasterizers are still CPU-based (as far as I know), so it can still become a problem if you don't use some optimization techniques :)

    • @marshallsweatherhiking1820
      @marshallsweatherhiking1820 3 ปีที่แล้ว +3

      @@angeldude101 It would probably be faster to just directly rasterize the entire outline first and store it in memory. Then checking for horizontal crossings is just referencing a binary lookup. The problem is then reduced to that of efficiently drawing the outline. I recall that even drawing simple straight lines involves some tricky optimization tricks, so the best optimization for rasterizing a cubic Bezier might not be super simple. Your t-step has to be adjusted based on the size of the curve relative to the raster resolution so that you neither 1.) leave holes in your curve nor 2.) redundantly draw the same pixel multiple times. Is there an easy formula to calculate the optimal t-step given a cubic Bezier curve's 4 points and a specified resolution? That's what would really help.
      It's fun thinking about how I would go about the problem before looking up how it's actually done. I haven't really studied this stuff since the 90s when everything was much slower in terms of speed and everything had to be super optimized to be at all usable in real time.

  • @LookingGlassUniverse
    @LookingGlassUniverse 3 ปีที่แล้ว +277

    You have a great style of explaining things and making them feel friendly. I especially loved the two blob characters 🥰 I hope you make many more maths videos!

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +14

      Thanks @LookingGlassUniverse! I do plan on making more videos like this, they just take a lot of time haha. But I really appreciate the comment :D

    • @Robert-jy9jm
      @Robert-jy9jm 3 ปีที่แล้ว

      I couldn't agree more! When you have over 100 likes and no dislikes you know that you're doing it exceptionally well!

    • @black_TM333
      @black_TM333 2 ปีที่แล้ว

      @@GamesWithGabe 0

    • @oldmonk8895
      @oldmonk8895 2 ปีที่แล้ว +1

      @@black_TM333 uwu

    • @solofi6680
      @solofi6680 2 ปีที่แล้ว

      Those blob characters made me remember 3blue3brown

  • @krytharn
    @krytharn 3 ปีที่แล้ว +91

    Might be worth mentioning that there is an alternative solution for fast, real-time rendering of glyphs pioneered and patented by NVIDIA, which is based on using the stencil buffer to determine coverage per pixel.
    Basically, a pixel is subdivided into subpixels and a shader determines for each subpixel whether it is inside the glyph or not. This can be quickly determined if you are smart in how you create your geometry. Quadratic curves, for instance, can be evaluated by creating a triangle from points p0, p1 and p2 and using barycentric coordinates for the vertices. It then becomes trivial to determine whether the subpixel is inside or outside the curve.
    The "winding" path is then drawn first, adding values to the stencil buffer. Next, the "non-winding" paths are drawn, subtracting the values in the stencil buffer. You end up with a stencil buffer containing ones and zeroes for every subpixel.
    Finally, in the so-called coverage step, you calculate the coverage of each pixel by adding all subpixel values for that pixel; if 16 out of 16 subpixels are set to one, you have 100% coverage, but if only 8 pixels are set to one, you have 50% coverage and so on. The final color will be determined by using coverage as an alpha value, or by multiplying the red, green and blue colors by the coverage.
    Substantial research has gone into finding ways to generate optimized stencil and coverage meshes to render, as well as coming up with ways to efficiently store these mesh representations on the GPU. It's sad that this process has been patented, but on the other hand it's free to use if you own an NVIDIA GPU. See: developer.nvidia.com/nv-path-rendering

    • @diegoaugusto1561
      @diegoaugusto1561 2 ปีที่แล้ว +3

      Could you express that in pseudocode somehow? I know the basics of pixel manipulation (RGB as a byte each) but don't know much about actual graphics related stuff

    • @lumpytapioca5062
      @lumpytapioca5062 2 ปีที่แล้ว +7

      Other than implementing it with hardware assist, I'm surprised that Nvidia got such a general patent on the technique.
      These sampling methods were being done in the 1980s on devices that needed the resolution and had the memory,
      like the Quantel Paintbox and Truevision graphics card applications.

  • @elraviv
    @elraviv 3 ปีที่แล้ว +67

    2:14 just for comparison, I had a Commodore 64 back in the '80s.
    it used 8x8 pixels for each character and only 1 bit per pixel.
    so the WHOLE ASCII table of 256 characters took 256*8*8*1bits = 2KB
    well it only had 64KB of memory anyway.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +27

      That's insane. I have a lot of respect for the programmers in the '80s and '90s era when memory was so limited. It's so easy to just use 100's of MB in a simple program now :)

    • @elraviv
      @elraviv 3 ปีที่แล้ว +1

      @@GamesWithGabe thanks for this video. I learned a lot.

    • @nielsdegroot9138
      @nielsdegroot9138 2 ปีที่แล้ว +2

      In the C64 the characters were in ROM. Although you could supply a RAM location for custom fonts.

    • @erwinmulder1338
      @erwinmulder1338 2 ปีที่แล้ว +3

      I grew up programming in the '80s and '90s and when he went 'only 32 by 32 pixels' I was like ... BRO, ONLY?!
      I have handcrafted many 6x6 pixel fonts just to get some decent amount of text on a screen given de crappy amount of pixels (256x192 or 320x200) on screen.
      Fun fact: The standard 'high rez' VGA font is 9x14 pixels.

    • @elraviv
      @elraviv 2 ปีที่แล้ว

      @@GamesWithGabe you may want to read about a memory saving trick called Bloom filter. it is still used in modern systems. imagine creating a speller using only a bit for each word. (well not exactly achievable, but it was "good enough")

  • @nikki-deprecated
    @nikki-deprecated 3 ปีที่แล้ว +65

    I am seriously unable to comprehend why you have such a small following... Your content is amazing and super high effort! You should be in the millions!

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +9

      Thanks Blu3! I put a bit more effort into this video than I normally do because I was submitting it to the 3Blue1Brown SoME haha. But I hope the channel will one day be in the millions :D

    • @Kindlylisten3
      @Kindlylisten3 3 ปีที่แล้ว

      @@GamesWithGabe hey why don't make a 1 byte = to 1 bit? Why not use something different from english letters that take 1 letter = 8 bits?

  • @CarlSmithNZ
    @CarlSmithNZ 3 ปีที่แล้ว +66

    This is great. Would love to see you go to the next step and talk about anti-aliasing etc.

    • @groszak1
      @groszak1 3 ปีที่แล้ว

      Anti-aliasing is doing bilevel rendering at 4×4 times the size, then using a box filter

    • @nikkiofthevalley
      @nikkiofthevalley ปีที่แล้ว +2

      @@groszak1 That's one type of anti-aliasing, there are more. Plus, not everyone knows what that means.

  • @asherhaun2632
    @asherhaun2632 3 ปีที่แล้ว +41

    Very interesting... the more I learn about font rendering/rasterization, the less I take it for granted :D

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +5

      Haha yea, I think you and I both know what a pain font rendering can be. And I'm glad you liked the video Asher!

  • @TorMatthews
    @TorMatthews 3 ปีที่แล้ว +24

    Distance field fonts are worth a mention as well because of their awesome utility, though getting into distance fields is itself a whole other topic

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +8

      Absolutely! If I have some time in the future I would love to add a part 2 about distance fields :)

    • @ramoncf7
      @ramoncf7 3 ปีที่แล้ว +1

      Also the amount of text effects you can add almost for free, I think almost every videogame uses them this days.

  • @dorktales254
    @dorktales254 3 ปีที่แล้ว +2

    I just found a gem of a channel

  • @kosmiksausagezz8349
    @kosmiksausagezz8349 3 ปีที่แล้ว +13

    What an amazing video - great graphics, really informative and easy to understand. Props!

  • @HJfod
    @HJfod 3 ปีที่แล้ว +5

    This video is absolutely fantastic, such a clear and simple explanation for a thoroughly interesting topic!

  • @oliviers589
    @oliviers589 3 ปีที่แล้ว +1

    Just wow. I had to work with a small OLED display and hexfonts a while ago. Since then l have been wondering how more advanced responsive font systems work and this video was the perfect answer. Thank you for this bit of knowledge.

  • @kipchickensout
    @kipchickensout ปีที่แล้ว +1

    nice video, i kind of expected the part with the raster, like how it's turned into pixels, anti aliasing and stuff like that

  • @hiyata4694
    @hiyata4694 ปีที่แล้ว

    I'm looking for an interesting topic for my maths homework right now, and your way of explaining this concept made it tremendously easy! Thank you so much for the video and your beginner-friendly explanations!

  • @ASalfity
    @ASalfity 3 ปีที่แล้ว +3

    I think a video on anti-aliasing would be interesting as well. The idea behind anti-aliasing is that if the edges contrast too much with the background you get a jagged looking texture along the edges on a (low resolution) bitmap screen. So what you do is you fill in the background near the edges with shades that transition between the shades of the letter and the background so that shades transition between the letter and the background more gradually. This gives less jagged looking edges. Thank for this video.

  • @gokselkucuksahin
    @gokselkucuksahin 2 ปีที่แล้ว +1

    Future 3Brown1Blue channel.
    Keep going.

  • @Nikki-2981
    @Nikki-2981 3 ปีที่แล้ว +2

    Wow, that's a lot more complicated than I thought! Great video!

  • @meowzerus
    @meowzerus 3 ปีที่แล้ว

    This is a very simplified overview to get you started, it's very good! The real world of fonts and font engines is spicy. Two examples: Winding orders aren't actually used consistently to mark regions, so you should calculate the normal of the glyph instead to find out which direction it's facing first. Some font tools or glyph operations may flip your glyph for example (I.e. your font has data for b, but represents d as a mirror of b through an affine transform). As for rasterizing bezier curves, font engines will actually linearize first based on a variety of heuristics since the test math is faster. I maintain a fast open source font engine on the weekends and love this stuff

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +1

      Thanks for the comment Joe! Also, thanks for the extra info. When I started diving into the world of fontrasterization I had no idea how deep this rabbit hole goes, and I'm still very interested in how internet browsers are able to handle so many different fonts seemingly effortlessly. Do you have a link to your code if it's open source? If so I would love to take a look at it :)

  • @skii_mask_
    @skii_mask_ 3 ปีที่แล้ว

    this deserves so much more attention.

  • @ashfvt7712
    @ashfvt7712 3 ปีที่แล้ว +3

    This was very interesting. You did a great job. Hope to see more from you in future.

  • @wellisntthatnice
    @wellisntthatnice 2 ปีที่แล้ว +4

    I'm not up on my quadratic equations, but overall I enjoyed the video. I was a little distracted at the beginning, though, due to some errors. Not big things, but big enough to make the problem of raster fonts seem overwhelming.
    At 1:26 you introduce a 32 x 32 grid, but it's actually only 16 x16.
    At 2:10 you present the formulas for determining the size of a raster file for uppercase and lowercase English letters in a monospaced typeface. 1 pixel is certainly 8 bits of data for grayscale, but fonts weren't grayscale--they were bitmaps; thus, 1 pixel was 1 bit. 1 letter in your font would have occupied 16 x 16 bits. The final equation should have been 26 x 2 x 16 x 16, or 13,312 bits--not 425,000 bits. This font would take up about 1,664 bytes or 1.625 KB (K-bytes), not 53 Kb (K-bits).
    At 2:37 you bring in BMP files, but fonts weren't stored as BMPs. Also, Apple didn't invent TrueType to solve the problem. The problem was already being solved with Adobe Type 1 and Type 3 fonts, introduced in 1984, the same year as Macintosh. Apple made TrueType to avoid licensing fees for Type 1 fonts. Side-note: Too bad for consumers because TrueType fonts (quadratic B-spline) were inferior to Adobe Type 1 fonts (cubic B-spline). Anyway.
    At 3:23 you present a 12 px font at 53 KB, referring to the previous 32 x 32 px grid that was actually 16 x 16. The 512 px font is presented as being 13.3 MB. But using bits, not grayscale pixels, the 512 px font would only be 1.664 MB.
    Again, I really liked the description and animation of the Bézier splines--top notch work.

  • @kvetter
    @kvetter 3 ปีที่แล้ว +10

    Oh, the Font Wars of the 90's. Fond memories. There was a huge battle between Apple's TrueType fonts (1991) and Adobe's proprietary PostScript Type 1 fonts (1984). There was much debate over the merits of both, such as Apple had special "hints" to display better at low resolution. Adobe responded with Adobe Type Manager which was the de facto standard for a while but was expensive. Then Apple licensed TrueType to Microsoft for WIndows 3.1. But Apple wouldn't license Apple Advanced Typography, so Microsoft joined with Adobe to create OpenType (1996).

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +1

      I've always wondered why font rasterization was so difficult, and with a history like this I guess it should make sense why it's not that simple :). I read a bit about the Font Wars as I was researching for this video, but I'd be interested to look a bit deeper into the history at some point as well

    • @lumpytapioca5062
      @lumpytapioca5062 2 ปีที่แล้ว +3

      I was a developer charged with implementing fonts in a paint package way back in the 80s. I remember that black and white Adobe Type 1 Font book well, reading it over and over and over. Our implementation was all in assembly on a TI34010 graphics accelerator. Even for back then, it ran really fast. Decode the font files, calculate the cardinal splines, experiment with fill methods, fix the corner cases, implement kerning, test, test, test. Glorious when all the steps start to work together. People these days don't realize how you had to build everything up from scratch back then, without off the shelf libraries you could just download with working examples.

  • @roy04
    @roy04 3 ปีที่แล้ว

    the size of the channel isn't representative of the production quality of this video. subbed, really good video

  • @JxH
    @JxH 3 ปีที่แล้ว +90

    2:14 "~ 53 Kb" -> 53 KB. Typically, bytes are indicated with an uppercase 'B', and bits are indicated with a lowercase 'b'.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +36

      Yea, I had another person point this out as well. I must have overlooked it when I was finalizing the editing :)

    • @takix2007
      @takix2007 3 ปีที่แล้ว +14

      And the "kilo" multiplier is indicated with a lowercase "k", so "kB".

    • @UltraLuigi2401
      @UltraLuigi2401 3 ปีที่แล้ว +1

      Also this calculation is a lot easier if you notice that 1 pixel is 1 byte, and that 32*32 = 1024 = the number of bytes in a kilobyte, so each letter is exactly 1 kilobyte, and therefore the english alphabet with upper and lower cases is exactly 52 kilobytes.

    • @flyingsquirrel3271
      @flyingsquirrel3271 3 ปีที่แล้ว +8

      @@UltraLuigi2401 I know that basically everyone on this planet still uses this wrong, so you have to be aware of the fact that uninformed people (and operating systems) mean 1024 bytes when they say 1 kilobyte. Actually that's simply wrong though. The prefix "kilo" means 1000 just like "mega" means 1000000 and that is NOT different for bytes. 1 kilometer = 1000 meters and 1 kilobyte = 1000 bytes. To deal with the confusion, a standard has been published in 1998 (accepted and enforced by many organizations) which introduced binary prefixes. The correct one in this case would be "kibi". So 1 kibibyte = 1024 bytes. The abbreviation is KiB instead of kB.
      Here's some more info if you care: en.wikipedia.org/wiki/Binary_prefix

    • @UltraLuigi2401
      @UltraLuigi2401 3 ปีที่แล้ว +1

      @@flyingsquirrel3271 I'm already aware of the different binary prefixes, I just am also aware that the base 2 definition for the SI prefixes is acceptable in informal contexts (such as youtube comments), and so use them to avoid confusion for people who have never heard of the binary prefixes.

  • @spidernh
    @spidernh 3 ปีที่แล้ว +3

    Wow nice video, really explained the concept well (except for the quadratic algebra stuff, but I don't think anyone can explain it well to me), and the visuals definitely helped me understand it.

  • @RecOgMission
    @RecOgMission 3 ปีที่แล้ว

    I've been wondering how exactly fonts are represented, visualized and scaled for a long time. A few months ago I implemented Bezier curves for smoothing out path finding points in my game, so it was a nice surprise to find them here too! Thanks for a great video.

  • @Just_Moh_it
    @Just_Moh_it 3 ปีที่แล้ว +1

    This channel is underrated, and my day is r..... *made

  • @UpstreamNL
    @UpstreamNL 3 ปีที่แล้ว +2

    Looking forward to part 2!

  • @andrewchen861
    @andrewchen861 3 ปีที่แล้ว +2

    Awesome! This is so cool and interested me the whole way!

  • @aparrot4254
    @aparrot4254 3 ปีที่แล้ว +1

    Love this video. Always wondered how font was rendered

  • @a-ramenartist9734
    @a-ramenartist9734 3 ปีที่แล้ว

    when your math knowledge from school is seen outside of school that's the coolest feeling

  • @Psychopatz
    @Psychopatz 3 ปีที่แล้ว

    Jeez, I take for granted on how I can able to change zoom and increase text size on the fly nowadays. Thanks for these amazing insights.

  • @groug5770
    @groug5770 2 ปีที่แล้ว

    Amazing video. Really well explained and perfectly animated. Must watch all videos you have. Congratulations for your work, I'm going to share this to friends :)

  • @Azeal
    @Azeal 3 ปีที่แล้ว

    Fascinating stuff!

  • @rustybucket2248
    @rustybucket2248 ปีที่แล้ว +1

    While what you have described will allow one to render an outline, this will not render characters or strings of characters of high quality. Consider rendering outlines on a fix grid a progressively smaller and larger sizes. Consider the letter uppercase H, at large sizes the two vertical strokes are of equal width and height, buts as the size gets smaller one of the strokes will render 1 or more pixels narrower that the other (This is known as the picket fence problem) looking at the horizontal stroke as the outline gets smaller the stroke will render wider or narrower than the vertical strokes, it will also be displaced upward or downward from it’s desired location. This is the vertical variation of the picket fence problem. Now let’s consider Capital M with regard to the vertical strokes it has the same problem as Capital H, but now it has anew problem the diagonal strokes don’t have the same widths as the size gets smaller, but because of pixelization there weight becomes heavier ( fatter relative the the vertical strokes) this applies to all diagonal strokes as is most pronounced at 45%. The same artifacts apply to curves Consider the Character O, as it drops in size the left right top and bottom will not be the same width in pixels similarly the curve will render fatter and fatter as it approaches North east, south east south west and north west. Now lets consider a collection of characters. The horizontals are varying in width and move up and down in Y the Verticals are varying in width and moving Left and right of their entended position. The most obvious artifact is the bottom of the characters don’t share a common base line the is called baseline wander. There are solutions to all of these problems that involve looking at the morphology of each character individually and looking at strings as agrégate characters with features like common base lines inter character spacing and string widths as features that need to be preserved when they are rendered. As an exercise for the reader consider the case of a lowercase i it is clear that the size of the staff and dot need to be the same, but the relative position of the dot, size of white space and staff need to be treated holistically. When one moves away from Latin Alphabets to ideogram base writing systems like Kanji, Hangul, Nihongo, Cursive positional representations like that found in Arabic… al of the Latin problems exist as well as numerous features that need to be preserved that are not as simple as the examples that I gave above. Then there is a basic implementations philosophy issue to you codify the rendering rules in each character “smart characters, dumb rendering” or Dumb characters, smart rendering” The former requires more work per character/ideogram the latter requires more understanding of the underlying morphology issues. I think true type is a good rendering system (Smart Characters, dumb rendering) Adobe type 1 rendering is the first to market and mass adoption format is an example for (Dumb Characters, Smart Rendering). Good presentation of rendering outlines to pixels, but not really representative of what it takes to render high quality type. I am one of the creators of Adobe’s type technology and also had a hand in the reaction of TrueType. More please.

    • @GamesWithGabe
      @GamesWithGabe  ปีที่แล้ว +1

      Thanks for this extra insight! I was amazed at the complexity that goes into rendering a single character as I was researching for a project I worked on (which is one of the reasons I made this video). One of the parts that blew my mind was the TrueType font program table and learning that fonts can embed programs to adjust the pixel placement for letters. Not only that, but like you alluded to rendering strings of characters also requires complex layout algorithms and other font metrics like kerning information or ligature conversions. Font rendering is an insanely deep rabbit hole to fall into, and it's very cool to hear from somebody that got to work on the original technology :)
      I am curious, do you know how much these algorithms for tweaking pixels at small/large font sizes still holds true? I was under the assumption that since almost all devices now have high-dpi or lots of pixels (not counting embedded devices), the pixel adjustments were less of a concern? But I honestly have no idea how browsers and other text heavy applications render text (whether it's just cached textures or real-time rendering or a mixture of both).

    • @rustybucket2248
      @rustybucket2248 ปีที่แล้ว +1

      @@GamesWithGabe The tweaks are still needed. Higher pixel per inch monitors simply changes the magnitude of tweaks and the size at which artifacts start to dominate the rendering. The mathematics of the font descriptions is mostly a thing of beauty. Regarding string widths managing the inter character spacing and propagating the fractional errors that quantizing to a fixed pixel grid demands is one aspect of the problem. Serifs, descenders like g, y… add another dimension to the problem. Preserving white space within characters like a, 6, 9 all are madding I think of it as a foreground background problem where neither are allowed primacy. The first rookie mistake is quantizing the fonts. The earliest Macintoshes fonts had integer font widths and integer Inter-character spacing quantized at 144 to the inch. A direct artifact of the 144 dpi ImageWriters that shipped with the earliest machines. Not only did our team design the software architecture for the Laserwriter we invested precious resources in rewriting the rendering engines that were used within QuickDraw. Steve Jobs really got his moneys worth out of teaming up with Adobe to save the failing Macintosh launch. To build real WYSIWYG systems the rendering intent is only quantized when it is on the device on which it will be rendered.. Once you have something to display or print the rendering intent has to be bound to the limits of the physical devices not the other way around. This is why a Macintosh could generate camera ready copy off an image setter with 2470 dpi resolution or a 72 dpi display or a 300 dpi laser printer and the only thing that change is the output conformed more closely to the rendering intent. In the realm of maintaining caches at high resolutions and large point sizes we found that compression algorithms that worked at laser printer resolutions were horrible at even modest point sizes and had to create a unique algorithm the usual line by line xor encoding to bias the data towards long runs for run length coding performed poorly but we observed that to we were able to take advantage of the morphology of the characters and create a predictor that encoded characters that ran diagonally through the bitmap space with there own encoding and the compression ratios became much more tractable. There was talk up thread about anti aliasing real anti aliasing is dealt with by rendering the page in reverse paint order. The aliasing that comes with the trade offs of Color pixels being stacked side by side, top to bottom and several other less than ideal device dependent topologies is better dealt with by overlaying a field lens that brings all of the illuminants together geometrically . for my sins I dealt with all of the hardware vendors that came through our doors. Our brain and visual system is very forgiving of some things and really fussy about others. I knew it was going to be a bad day when I had to explain to yet another vendor why we couldn’t fix their broke assed hardware in software. It has been a long time since I thought about this stuff. Best

  • @patrikstaron
    @patrikstaron 3 ปีที่แล้ว +1

    Nicely explained. Sadly, I really wanted to see subpixel rendering techniques and hardware acceleration mechanisms, like single-instrucion-multiple-data.

  • @Banaannaa
    @Banaannaa 8 หลายเดือนก่อน

    Incredible, earned a sub

  • @jacobolus
    @jacobolus 3 ปีที่แล้ว +4

    Adobe Type 1 vector fonts are from 1984, and the concept of vector fonts is older than that. The biggest difference between Type 1 vs. TrueType fonts is that the former used cubic Bézier curves, while the latter switched to quadratic Bézier curves (I think to work around Adobe’s patents?).

    • @rustybucket2248
      @rustybucket2248 ปีที่แล้ว

      Adobe fonts were never vector fonts They were scalable outline fonts. There were no Patents. Later Products like Super ATM were Patented, but the font technology inside Postscript was not patented and the Type format and PostScript language were documented in books published by Addison Wesley. Super ATM allowed you to morph Fonts along a variety of axes Blending weights, Set widths, different typefaces together were just some of the dozens of ways that typefaces could be transformed. The best example I remember is taking text in two different languages and modifying the set width’s and character shapes so that the text matched up line for line. Apple and MicroSoft got it into their heads that they would be better off if they created their own implementation of PostScript. It was my responsibility to find a way to win Apple back as a customer. It was not an easy task, thanks to some of the more moderate business development folks at Apple we managed to resolve our differences and build a lot more great product together. Apple and Microsoft spent 100s of millions of dollars and ultimately abandoned the project. True type AKA type 42 fonts was meant to be a faster rendering implementation, in the end it was the same only different. The two type formats and underlying technology were merged together into Cleartype. Within 6 months of Apple and MicroSoft tell Adobe that they were going to put us out of business, Adobe Type Manager was released for the Mac and Windows “ATM” brought type one scaleable font technology to the desktop along with a Library of thousands of Fully Licensed type faces. ATM was installed on ~80% of Macs Apple grudging allowed as it probably wasn’t good for business if they broke all of their customers machines.

    • @jacobolus
      @jacobolus ปีที่แล้ว

      @@rustybucket2248 What is the difference between a "vector font" and a "scalable outline font"? To me those two terms are synonyms. When I say "vector font" what I mean is: “the outline is specified as a mathematical curve; the font is not a pixel-based raster image”. I didn’t mean to imply anything about the relationships between sub-categories of outline-based fonts.

  • @onur759
    @onur759 ปีที่แล้ว

    Hey, this video is incredible! Please, keep up your work!

  • @Roxor128
    @Roxor128 3 ปีที่แล้ว +1

    Possible way to optimise it: Use the points defining a character to make a bounding box, then divide the area to be rendered into small patches with pointers to the characters whose bounding boxes lie within each patch. The rendering shader then only needs concern itself with testing its fragment coordinate against the characters within a given patch. Putting the relevant data into a format a fragment shader can work with might be a bit complicated, though.
    Going below the level of a character seems like it might be possible, but I have no idea how you would go about it, given it seems like it would require splitting the lines and curves and adding new boundaries for patch edges that lie inside the character.

    • @awesomegamedev
      @awesomegamedev 3 ปีที่แล้ว +4

      What you describe should work, but text rendering in games actually works much easier and faster by using Signed Distance Fields.
      You generate (once) a Signed Distance Field texture from given vector representation,
      and then use it to render the text.
      Nice video about it: th-cam.com/video/1b5hIMqz_wM/w-d-xo.html

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว

      Yep this would definitely work, and as Awesome GameDev wrote you can use signed distance fields to do this as well. I experimented with GPU accelerated font rendering using the actual techniques described in this video, and I had to create a pretty monstrous shader for the rendering haha. It was also pretty slow, but I would be interested to see if I could speed it up using the bounding box ideas that you listed :)

  • @simexafrica5630
    @simexafrica5630 3 ปีที่แล้ว

    makes a video about font rasterisation and casually explains bezier lines better than any other tutorial I could find

  • @nahuelgareis8927
    @nahuelgareis8927 3 หลายเดือนก่อน

    I would have liked to (after doing the bezier curve stuff) explain the actual algorithm behind rasterization which is the DDA but nice work anyway!

  • @hilbert_curve3680
    @hilbert_curve3680 3 ปีที่แล้ว +5

    Nice work! I bet animating'll be easier with all the refactoring you've done.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +4

      Haha let's hope so! My plans are to also add a serialization system for the animations and a GUI, then it should be much easier to add new animations :D

  • @rahulsharma-gw7fc
    @rahulsharma-gw7fc 3 ปีที่แล้ว

    finally learnt how Bezier curve work after years.

  • @404statuscode
    @404statuscode 3 ปีที่แล้ว +4

    Amazing Video😃

  • @Eltaurus
    @Eltaurus 3 ปีที่แล้ว +1

    It would be nice to look at the rasterization of cubic bezier curves after that.
    The ones that are used in the .otf font format and in vector graphics in general.
    A completely new set of problems arises there. Such as looking for self-intersections, which cannot be done analytically because of the high order of polynomials.
    Anti-aliasing is another interesting issue worth discussing in relation to the whole topic of rasterization.

    • @marshallsweatherhiking1820
      @marshallsweatherhiking1820 3 ปีที่แล้ว

      He also didn't mention that getting the bounding rectangle of each bezier curve is the first step. The more involved calculation is only needed once you know you are inside the bounding rectangle. Only in the case of complex curlicues and other thin spaghetti-looking shapes will bounding boxes greatly overlap, requiring a lot more calculations. I think the only square root you need is in finding maxima and minima of cubic beziers (because the derivatives are quadratic). Otherwise you just draw the binary rasterized curves (wire frames) in memory ahead of time and then dig them up for cases of points inside bounding rectangles.
      The problem is reduced to finding the best t-step to draw the binary outlines of the curves. If the t-step is too big your curve will have gaps. If it is too small you will waste time drawing certain pixels multiple times. You need a formula to calculate the best t-step given the 4 weighting points of your curve and the given pixel resolution.

    • @marshallsweatherhiking1820
      @marshallsweatherhiking1820 3 ปีที่แล้ว

      Self-intersection doesn't seem like a problem for fonts as almost no font is going to use a looping bezier. If you have a deliberate loop in your glyph, you would always use two non-looping bezier curves to construct it. If you are allowing generalized shapes where the user can place weighting points anywhere they like, like in Adobe illustrator, then you do have to test for points possibly being inside the loop of a self-intersecting bezier. I think if you're doing graphics where speed is required you simply rule out loops ahead of time though. The loop is an ugly special case that only has to be dealt with when you can't rule it out ahead of time based on the location of the weighting points.

  • @hamedrahmati3129
    @hamedrahmati3129 2 ปีที่แล้ว

    overwhelmed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! the only thing i could say........

  • @nikkiofthevalley
    @nikkiofthevalley 3 ปีที่แล้ว

    Thanks for this! I was actually making a font renderer!

  • @erikawwad7653
    @erikawwad7653 2 ปีที่แล้ว

    stellar vid mate

  • @DaydreamStudios_Official
    @DaydreamStudios_Official ปีที่แล้ว +1

    10:26
    My Mans really just said P I N U S 💀

  • @cornelhanekom5689
    @cornelhanekom5689 3 ปีที่แล้ว

    Thanks, this video made my day

  • @ReBufff
    @ReBufff 3 ปีที่แล้ว +2

    Do computers have to calculate the root in the quadratic equation for every pixel, every frame? Isn't that really expensive computation?

  • @groszak1
    @groszak1 3 ปีที่แล้ว +1

    Font rasterization makes use of the quadratic formula, which in itself is not too difficult. The real difficulty is figuring out the specific version of the quadratic formula Microsoft used in their renderer.

  • @jamesking2439
    @jamesking2439 3 ปีที่แล้ว +4

    Would it be reasonable to rasterize the outline of the curve and then floodfill the rest to avoid having to test each pixel?

    • @lumpytapioca5062
      @lumpytapioca5062 2 ปีที่แล้ว

      Depends on the flood fill method, but filling large areas can end up reading memory way more often.

  • @janthummler3548
    @janthummler3548 3 ปีที่แล้ว

    this was super interesting, thanks!

  • @harriehausenman8623
    @harriehausenman8623 3 ปีที่แล้ว +7

    3b1b sent me

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +1

      Oh nice! I hope you enjoyed the video :)

    • @harriehausenman8623
      @harriehausenman8623 3 ปีที่แล้ว +1

      @@GamesWithGabe Yes I did very much. Thank you.

    • @miniwizard
      @miniwizard 3 ปีที่แล้ว +2

      Ditto, from his playlist which I'm working through.
      Makes you appreciate the amount of processing being done behind the scenes...

    • @MattRose30000
      @MattRose30000 3 ปีที่แล้ว +1

      Same! Also, this is the first video that let me truly understand bezier curves :)

  • @elliot_yoyo
    @elliot_yoyo 3 ปีที่แล้ว +1

    great video ! thanks

  • @P4INKiller
    @P4INKiller 3 ปีที่แล้ว +2

    I'll take code over math notation any day.

  • @ScriptGuider
    @ScriptGuider 3 ปีที่แล้ว

    Your explanation and visual representation of linear interpolation and Bezier curves is very similar to what I've posted on my channel! Almost scene-for-scene, haha. Well done though!

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว

      Thanks ScriptGuider! And I just checked out your video, that is funny haha. I drew inspiration from the wikipedia article on Bezier curves, and they basically had the same thing as well lol :)

  • @cmilkau
    @cmilkau 2 ปีที่แล้ว

    12:09 The formula can be simplified nicely:
    P(t) = (1-t)²P0 + 2t(1-t)P1 + t²P2

  • @rejophilipjose7763
    @rejophilipjose7763 3 ปีที่แล้ว +1

    Great video

  • @warny1978
    @warny1978 2 ปีที่แล้ว

    I found a way to render a path made of lines, bezier curves of any degree, arc of ellipse or any shape you can imagine.
    For each computed pixel, i keep trace of the vertical sign of the derivate of the curve (which i compute by simply substracting a pixel position from it's previous). If it's an edge, or two curves crossing each other, i keep trace of both values.
    Now, from the upper pixel to the lower, then form the more left pixel to the more right, i draw the filler pixel if the sum of the sign is more than 0. I can avoid drawing on line if i want.

  • @bob450v4
    @bob450v4 3 ปีที่แล้ว +1

    Amazing 🤩

  • @benshand6659
    @benshand6659 3 ปีที่แล้ว

    Great video man

  • @WashingtonFernandes
    @WashingtonFernandes 2 ปีที่แล้ว

    really good vid.

  • @BlitzkriegHD
    @BlitzkriegHD 2 ปีที่แล้ว

    10:26 “pinus” - I guess I should’ve paid more attention in my maths courses, never heard of that arithmetic operator before 🤣

  • @ZedaZ80
    @ZedaZ80 3 ปีที่แล้ว +2

    Hnnng, now I wanna see if I can go this on my graphing calculator

  • @hellfishii
    @hellfishii 2 ปีที่แล้ว

    This video is fire

  • @repeekyraidcero
    @repeekyraidcero 3 ปีที่แล้ว

    7:00 in:
    I got this !
    What ? More math ? 😂
    Still High School math suffices to get this.
    Good job.
    (When you started talking about pixels and filling, I had to stop myself from making an imagemagick joke hahah)

  • @Paul-kx7vg
    @Paul-kx7vg 3 ปีที่แล้ว

    What an amazing video.

  • @arivanhouten6343
    @arivanhouten6343 3 ปีที่แล้ว

    Wonderful!

  • @aaaaaa-rr8xm
    @aaaaaa-rr8xm 2 ปีที่แล้ว

    Can you please explain what is Q(t)? because I want to know what the function Q(t) for generating Bezier Curves is if you know it/them.

  • @Dr.RokiaAbdein
    @Dr.RokiaAbdein 9 หลายเดือนก่อน

    great great great !!!

  • @EquaTechnologies
    @EquaTechnologies ปีที่แล้ว

    Doesn't it also work, for example, if a pixel's X position is equal to the Y position (x = y), place the pixel there (rotated line)?

  • @briannem.6787
    @briannem.6787 3 ปีที่แล้ว

    Why is it that fonts on my windows XP computer look very blocky (more so than other non-text elements) at high resolutions? Did they just not use rasterisation?

  • @Zytron
    @Zytron 2 ปีที่แล้ว

    14:01 *mom walks in*
    finally she walks in when I can pose as doing my online math homework instead of the weird part of the TV show
    mom: "I thought you finished the quadradisc last year! Go do your weird TV show research already!"

  • @ZaItan1
    @ZaItan1 2 ปีที่แล้ว

    Most need not remember the quadratic formula -- only (visually) that degree 2 single-variable functions bend toward and then away from the x-axis, and (algebraically) `x * y = 0` where x and y are expressions, means either x = 0, y = 0, or both

  • @matthewrease2376
    @matthewrease2376 2 ปีที่แล้ว

    You can write documents in a terminal.
    You can build a website in a terminal.
    No guarantee that doing these things made someone encounter rasterized text :)

  • @xmorse
    @xmorse 2 ปีที่แล้ว

    One thing I don’t understand is how does the Bézier curve work on points (2 numbers), do you just apply the operations to vector2 elements?

    • @GamesWithGabe
      @GamesWithGabe  2 ปีที่แล้ว +1

      The mathematical notation actually extends to any arbitrarily sized vector. So if you just imagine that P consists of two components, , then you just use the same equation for x and y. Then you can extend it to 3 dimensions by using the same equation for z, etc. Let me know if that makes sense, it's kinda late and it's hard to type this on a phone haha

  • @spaceowl5957
    @spaceowl5957 3 ปีที่แล้ว

    Are you sure that TTF uses 3-point Bézier curves? Usually 4-point Bézier curves are used in vector programs and most other applications. That will give you 2 control points which lets you create more complex shapes, and importantly it lets you determine the slope in the start and the end points of the curve separately.
    I haven’t been thought about this too much but I feel like it would be really bad or even impossible to create smooth shapes but combining several Bézier curves without being able to control the slope in the start and end points

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +2

      Yea I'm like 90% sure haha. You can check out this section in Microsoft's overview of the TrueType specification docs.microsoft.com/en-us/typography/opentype/spec/ttch01#outlines . The second paragraph says "Curves are defined by a series of points that describe second order Bezier-spline", and when I wrote a simple ttf font parser I didn't encounter anything greater than a second order bezier curve. Those docs are really amazing too if you're interested in more of the technical details :)

  • @anfanger4
    @anfanger4 2 ปีที่แล้ว

    15:33 well, thats why i originally came for :D

  • @hichemchalouah5052
    @hichemchalouah5052 2 ปีที่แล้ว

    That's helpful thanks.

  • @bartat404
    @bartat404 3 ปีที่แล้ว

    Your P's drove my subwoofer through the floor. :P

  • @Banaannaa
    @Banaannaa 8 หลายเดือนก่อน

    amazing

  • @romajimamulo
    @romajimamulo 3 ปีที่แล้ว +1

    15:10 but don't you have to check that the crossings are to the right of the tested pixel?

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +1

      Yes, if you make sure to transform all the coordinates so that the pixel you are testing is the origin, then all you need to do is check if the x-coordinate of the root is less than 0 and that means it is to the left of the pixel :)

  • @anlcangulkaya6244
    @anlcangulkaya6244 3 ปีที่แล้ว +2

    awesome

  • @mikkicon
    @mikkicon 3 ปีที่แล้ว

    Very interesting

  • @SteinGauslaaStrindhaug
    @SteinGauslaaStrindhaug 3 ปีที่แล้ว +1

    10:24 so many P's in that equation so it even infected the "minus" and became "pinus"

  • @blargoner
    @blargoner 3 ปีที่แล้ว +3

    Nice video. Just gotta watch out for those French names.

    • @GamesWithGabe
      @GamesWithGabe  3 ปีที่แล้ว +2

      Thanks! And yea, French names are not my forte :)

    • @samuelwaller4924
      @samuelwaller4924 3 ปีที่แล้ว +1

      "blargonay"

  • @powerbanger69
    @powerbanger69 3 ปีที่แล้ว

    Not what I thought!

  • @dshoopy571
    @dshoopy571 3 ปีที่แล้ว

    SVG's are calculated with purely math, that is why there file size is so small but they can be scaled to any size on a screen.

  • @qxtr5853
    @qxtr5853 3 ปีที่แล้ว +6

    I'm sorry to leave a comment like that on a video with relatively few other comments, but: 10:25 lmao "pinus"

  • @bluekeybo
    @bluekeybo 2 ปีที่แล้ว

    14:45 why would it not intersect with our curve if it's greater than 1? Also at 14:17 the solutions should be shown as "t=" not "y=". Interesting video, thanks!

    • @GamesWithGabe
      @GamesWithGabe  2 ปีที่แล้ว +1

      If it's greater than 1, then that implies that the value would intersect after the endpoint of the bezier curve. So, technically it would still intersect with the curve, it just wouldn't hit it between the end points
      And you're right about the y should be t, I didn't even notice I had that messed up until now haha! Thanks for mentioning it though :)

  • @seneca983
    @seneca983 2 ปีที่แล้ว

    14:15 It should be noted that you shouldn't use that formula for the case where the two terms in numerator have opposite signs.

  • @thewhitefalcon8539
    @thewhitefalcon8539 3 ปีที่แล้ว

    At 1:40 you wrote 32x32 pixels but the grid is actually 16x16

  • @fredoverflow
    @fredoverflow 3 ปีที่แล้ว +1

    I always thought the F in TTF stood for "font", was I mistaken?

    • @_invencible_
      @_invencible_ 3 ปีที่แล้ว

      You are right. He skipped the word Font and then it was just pure coincidence that the next word he said (file) also started with an F

  • @haroo5738
    @haroo5738 3 ปีที่แล้ว

    i cant pass a test yet i find this really interesting

  • @fliptip
    @fliptip 2 ปีที่แล้ว

    A so good video

  • @comment2891
    @comment2891 ปีที่แล้ว

    The really interesting stuff is so-called "font hinting". There's a Wikipedia article about it.

  • @DanielNetSet
    @DanielNetSet 2 ปีที่แล้ว

    8:12 does that mean that rendering 1 billion 'B' letters is more costly than 1 billion 'I" letters in the ttf format?

    • @GamesWithGabe
      @GamesWithGabe  2 ปีที่แล้ว +1

      Not in practice because programmers will typically "cache" the letter to a texture. So they'll rasterize it once, then save the pixels, and then basically stamp the letter where they need it every time they need to use it :)

    • @DanielNetSet
      @DanielNetSet 2 ปีที่แล้ว

      @@GamesWithGabe well then, next video should be "The Code Behind Font Rasterization | How it Works" ay?