The Math Behind Font Rasterization | How it Works

Sdílet
Vložit
  • čas přidán 16. 05. 2024
  • #SoME
    Join the Discord: / discord
    If you have ever wondered how a font is rasterized, look no further. In this video I go into depth about the necessity for font rasterization, the math behind it, and how we convert the math to pixels on the screen. I also go over how 1st and 2nd order Bezier curves work. I talk about how to gain an intuition for Bezier curves, and how to formulize that intuition into Mathematical formulae. I also go over how to test if a point will intersect with a 2nd order Bezier curve. This is my entry into 3Blue1Brown's SoME competition and I hope you enjoy it!
    0:00 Intro
    0:38 A Brief History of Fonts
    3:48 Using Math to Draw Letters
    5:42 What are Bezier Curves?
    9:09 How do Bezier Curves Really Work?
    12:41 Testing Pixels
    15:13 Edge Cases
    ---------------------------------------------------------------------
    Website: ambrosiogabe.github.io/
    Github: github.com/ambrosiogabe
    Here are some books I recommend if you want to learn about game engine development more thoroughly. I do not profit off any of these sales, these are just some books that have helped me out :)
    My Recommended Game Engine Books:
    Game Engine Architecture: www.gameenginebook.com/
    Game Physics Cookbook (Read this before the next physics book): www.amazon.com/Game-Physics-C...
    Game Physics (Ian Millington): www.amazon.com/Game-Physics-E...
    Game Programming Patterns (Free): gameprogrammingpatterns.com/
    My Recommended Beginning Game Programming Books:
    JavaScript Game Design: www.apress.com/gp/book/978143...
    My Recommended Java Books:
    Data Structures/Algorithms: www.amazon.com/Data-Structure...
    LWJGL (Free, but I haven't read this thoroughly): lwjglgamedev.gitbooks.io/3d-g...

Komentáře • 272

  • @LookingGlassUniverse
    @LookingGlassUniverse Před 2 lety +272

    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  Před 2 lety +13

      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 Před 2 lety

      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 Před 2 lety

      @@GamesWithGabe 0

    • @oldmonk8895
      @oldmonk8895 Před 2 lety +1

      @@black_TM333 uwu

    • @solofi6680
      @solofi6680 Před rokem

      Those blob characters made me remember 3blue3brown

  • @SimonBuchanNz
    @SimonBuchanNz Před 2 lety +232

    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  Před 2 lety +33

      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 Před 2 lety +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 Před 2 lety

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

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +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 Před 2 lety +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.

  • @asherhaun2632
    @asherhaun2632 Před 2 lety +41

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

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +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!

  • @krytharn
    @krytharn Před 2 lety +88

    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 Před 2 lety +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 Před 2 lety +6

      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 Před 2 lety +64

    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  Před 2 lety +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 Před 2 lety +1

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

    • @nielsdegroot9138
      @nielsdegroot9138 Před 2 lety +2

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

    • @erwinmulder1338
      @erwinmulder1338 Před 2 lety +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 Před 2 lety

      @@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 Před 2 lety +64

    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  Před 2 lety +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

    • @synonymous8390
      @synonymous8390 Před 2 lety

      @@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 Před 2 lety +67

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

    • @groszak1
      @groszak1 Před 2 lety

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

    • @nikkiofthevalley
      @nikkiofthevalley Před rokem +2

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

  • @TorMatthews
    @TorMatthews Před 2 lety +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  Před 2 lety +8

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

    • @ramoncf7
      @ramoncf7 Před 2 lety +1

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

  • @dorktales254
    @dorktales254 Před 2 lety +2

    I just found a gem of a channel

  • @HJfod
    @HJfod Před 2 lety +5

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

  • @ashfvt7712
    @ashfvt7712 Před 2 lety +3

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

  • @Nikson2981
    @Nikson2981 Před 2 lety +2

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

  • @hiyata4694
    @hiyata4694 Před rokem

    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!

  • @kosmiksausagezz8349
    @kosmiksausagezz8349 Před 2 lety +13

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

  • @groug5770
    @groug5770 Před 2 lety

    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 :)

  • @oliviers589
    @oliviers589 Před 2 lety +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.

  • @andrewchen861
    @andrewchen861 Před 2 lety +2

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

  • @UpstreamNL
    @UpstreamNL Před 2 lety +2

    Looking forward to part 2!

  • @onur759
    @onur759 Před rokem

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

  • @skii_mask_
    @skii_mask_ Před 2 lety

    this deserves so much more attention.

  • @aparrot4254
    @aparrot4254 Před 2 lety +1

    Love this video. Always wondered how font was rendered

  • @JxH
    @JxH Před 2 lety +89

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

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +36

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

    • @takix2007
      @takix2007 Před 2 lety +14

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

    • @UltraLuigi2401
      @UltraLuigi2401 Před 2 lety +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 Před 2 lety +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 Před 2 lety +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 Před 2 lety +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.

  • @gokselkucuksahin
    @gokselkucuksahin Před 2 lety

    Future 3Brown1Blue channel.
    Keep going.

  • @RecOgMission
    @RecOgMission Před 2 lety

    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.

  • @Azeal
    @Azeal Před 2 lety

    Fascinating stuff!

  • @Just_Moh_it
    @Just_Moh_it Před 2 lety +1

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

  • @cornelhanekom5689
    @cornelhanekom5689 Před 2 lety

    Thanks, this video made my day

  • @erikawwad7653
    @erikawwad7653 Před 2 lety

    stellar vid mate

  • @ASalfity
    @ASalfity Před 2 lety +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.

  • @meowzerus
    @meowzerus Před 2 lety

    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  Před 2 lety +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 :)

  • @janthummler3548
    @janthummler3548 Před 2 lety

    this was super interesting, thanks!

  • @Banaannaa
    @Banaannaa Před 2 měsíci

    Incredible, earned a sub

  • @kvetter
    @kvetter Před 2 lety +9

    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  Před 2 lety +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 Před 2 lety +2

      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.

  • @nikkiofthevalley
    @nikkiofthevalley Před 2 lety

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

  • @benshand6659
    @benshand6659 Před 2 lety

    Great video man

  • @roy04
    @roy04 Před 2 lety

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

  • @Psychopatz
    @Psychopatz Před 2 lety

    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.

  • @elliot_yoyo
    @elliot_yoyo Před 2 lety +1

    great video ! thanks

  • @kipchickensout
    @kipchickensout Před rokem +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

  • @arivanhouten6343
    @arivanhouten6343 Před 2 lety

    Wonderful!

  • @bob450v4
    @bob450v4 Před 2 lety +1

    Amazing 🤩

  • @hichemchalouah5052
    @hichemchalouah5052 Před 2 lety

    That's helpful thanks.

  • @404statuscode
    @404statuscode Před 2 lety +4

    Amazing Video😃

  • @patrikstaron
    @patrikstaron Před 2 lety +1

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

  • @rejophilipjose7763
    @rejophilipjose7763 Před 2 lety +1

    Great video

  • @hellfishii
    @hellfishii Před 2 lety

    This video is fire

  • @a-ramenartist9734
    @a-ramenartist9734 Před 2 lety

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

  • @WashingtonFernandes
    @WashingtonFernandes Před 2 lety

    really good vid.

  • @Paul-kx7vg
    @Paul-kx7vg Před 2 lety

    What an amazing video.

  • @hilbert_curve3680
    @hilbert_curve3680 Před 2 lety +5

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

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +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

  • @mikkicon
    @mikkicon Před 2 lety

    Very interesting

  • @rahulsharma-gw7fc
    @rahulsharma-gw7fc Před 2 lety

    finally learnt how Bezier curve work after years.

  • @simexafrica5630
    @simexafrica5630 Před 2 lety

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

  • @fliptip
    @fliptip Před 2 lety

    A so good video

  • @Roxor128
    @Roxor128 Před 2 lety +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 Před 2 lety +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: czcams.com/video/1b5hIMqz_wM/video.html

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety

      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 :)

  • @harriehausenman8623
    @harriehausenman8623 Před 2 lety +7

    3b1b sent me

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +1

      Oh nice! I hope you enjoyed the video :)

    • @harriehausenman8623
      @harriehausenman8623 Před 2 lety +1

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

    • @miniwizard
      @miniwizard Před 2 lety +2

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

    • @MattRose30000
      @MattRose30000 Před 2 lety +1

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

  • @Banaannaa
    @Banaannaa Před 2 měsíci

    amazing

  • @Eltaurus
    @Eltaurus Před 2 lety +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 Před 2 lety

      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 Před 2 lety

      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.

  • @repeekyraidcero
    @repeekyraidcero Před 2 lety

    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)

  • @Dr.RokiaAbdein
    @Dr.RokiaAbdein Před 3 měsíci

    great great great !!!

  • @hamedrahmati3129
    @hamedrahmati3129 Před 2 lety

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

  • @ScriptGuider
    @ScriptGuider Před 2 lety

    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  Před 2 lety

      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 :)

  • @ZedaZ80
    @ZedaZ80 Před 2 lety +2

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

  • @jacobolus
    @jacobolus Před 2 lety +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 Před rokem

      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 Před rokem

      @@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.

  • @warny1978
    @warny1978 Před 2 lety

    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.

  • @anlcangulkaya6244
    @anlcangulkaya6244 Před 2 lety +2

    awesome

  • @ReBufff
    @ReBufff Před 2 lety +2

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

  • @cmilkau
    @cmilkau Před 2 lety

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

  • @clarkwain2817
    @clarkwain2817 Před 2 lety

    thanks.

  • @spaceowl5957
    @spaceowl5957 Před 2 lety

    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  Před 2 lety +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 :)

  • @EquaTechnologies
    @EquaTechnologies Před rokem

    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)?

  • @aaaaaa-rr8xm
    @aaaaaa-rr8xm Před rokem

    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.

  • @CaspianSnakeYTX_X
    @CaspianSnakeYTX_X Před 2 lety

    Cool

  • @qxtr5853
    @qxtr5853 Před 2 lety +6

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

  • @BlitzkriegHD
    @BlitzkriegHD Před 2 lety

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

  • @jamesking2439
    @jamesking2439 Před 2 lety +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 Před 2 lety

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

  • @ZaItan1
    @ZaItan1 Před 2 lety

    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

  • @xmorse
    @xmorse Před 2 lety

    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  Před 2 lety +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

  • @yeetman6416
    @yeetman6416 Před 2 lety

    Not what I thought!

  • @groszak1
    @groszak1 Před 2 lety +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.

  • @rustybucket2248
    @rustybucket2248 Před rokem

    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  Před rokem +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 Před rokem +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

  • @anfanger4
    @anfanger4 Před 2 lety

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

  • @briannem.6787
    @briannem.6787 Před 2 lety

    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?

  • @DaydreamStudios_Official

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

  • @bartat404
    @bartat404 Před 2 lety

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

  • @Zytron
    @Zytron Před 2 lety

    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!"

  • @romajimamulo
    @romajimamulo Před 2 lety +1

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

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety +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 :)

  • @SteinGauslaaStrindhaug
    @SteinGauslaaStrindhaug Před 2 lety +1

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

  • @P4INKillers
    @P4INKillers Před 2 lety +2

    I'll take code over math notation any day.

  • @matthewrease2376
    @matthewrease2376 Před 2 lety

    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 :)

  • @haroo5738
    @haroo5738 Před 2 lety

    i cant pass a test yet i find this really interesting

  • @forthrightgambitia1032

    14:17 - why do you use the y coordinates here?

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety

      Hey Forthright! I use the y-coordinates there because I'm testing to see if the pixel has intersected with the x-axis. If we do it that way, then it's basically the same as looking for where P(t) = 0 for the y-coordinates. I believe you could just as easily do a vertical test though and then you would use the x-coordinates instead :)

    • @forthrightgambitia1032
      @forthrightgambitia1032 Před 2 lety +1

      @@GamesWithGabe ah I see the Bezier curve will always have x and y values equally interpolated between there start and end values for both so the same equation controlled by t holds for x and y.

  • @wonderwise5493
    @wonderwise5493 Před 2 lety

    I have a question, isn't possible to save an interior point in the font file? It would simplify all the calculations. I'm not a programmer, if someone know why it is not used, it will satisfy my curiosity.

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety

      Hey wonderwise! If you're asking if it's possible to save the points that make the curves in a file, then it's not only possible but that's how the file format actually works.
      Essentially a ttf file stores a bunch of binary "tables" of data. There's one table called the glyf table. This table stores all the information about where points are located. It basically just has a bunch of binary that represents the points, and it will tell you if the next two points are a straight line, or if the next three points are a Bezier curve.
      Microsoft actually has some really great documentation that's pretty easy to read. You can read about the glyf table here docs.microsoft.com/en-us/typography/opentype/spec/glyf . And a glyf, aka glyph, is just any single shape. Character sets like the Arabic character set will actually only define a few different glyphs, and those glyphs get combined into a single character. The Chinese character does something similar, and it's all really interesting to learn about :)

    • @wonderwise5493
      @wonderwise5493 Před 2 lety

      @@GamesWithGabe thanks for answer, maybe my question was a little misleading. I meant you could save a single reference point which is in the interior area of the font curves and lines. And therefore, it wouldn't be needed to check where is the interior and exterior of the font.

    • @wonderwise5493
      @wonderwise5493 Před 2 lety

      And you could fill the interior colour of the font from that reference point.

    • @GamesWithGabe
      @GamesWithGabe  Před 2 lety

      No problem! And you could do something like that, but the interior points would change depending on the size of the font. Another problem is, flood fill algorithms are actually pretty slow, and if you can come up with an algorithm that works for every single pixel, then you can run the algorithm for every single pixel at the same time. This means you can use the GPU to hardware accelerate the process, or multithread it on the CPU to make it several times faster depending on how many cores there are

    • @wonderwise5493
      @wonderwise5493 Před 2 lety

      @@GamesWithGabe okay, thanks a lot, I understand it now

  • @bluekeybo
    @bluekeybo Před 2 lety

    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  Před 2 lety +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 Před rokem

    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.

  • @precursortopain8262
    @precursortopain8262 Před 2 lety

    Oh yeah, rasterize dat shit breh!

  • @leesweets4110
    @leesweets4110 Před rokem

    Why cant the interior, which is to be filled in black, simply be identified by a single pixel, or vector direction from one of the defined edge points, or a set thereof?

  • @fredoverflow
    @fredoverflow Před 2 lety +1

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

    • @_invencible_
      @_invencible_ Před 2 lety

      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

  • @blargoner
    @blargoner Před 2 lety +3

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