preface

Traditional web pages are rendered in pixels, so images cannot be scaled to arbitrary sizes and kept flat like SVG. In other words, enlarging the pixel logic of an image inevitably leads to a decrease in visual quality (information distortion). So we often use technical means to avoid distortion, such as:

  • Replace bitmaps with SVG
  • Replace bitmap fonts with vector fonts such as TrueType fonts

If forced to do pixel manipulation, we have several tools to correct the distortion:

  • Adjust the sampling algorithm for Image scaling using THE CSS image-rendering property
  • Smoothing a Font using the CSS Font-Smoothing attribute
  • Use Canvas’s anti-aliasing API when drawing
  • Enlarge the element size, then use Transform to restore the layout size
  • In some special cases, browser hardware acceleration can be used to smooth aliasing
  • Blurring the image forces the user to turn on the titanium brain

This article will briefly mention the above points and introduce a new idea of anti-aliasing through CSS BackgroundImage (I call it Pixel-offset anti-aliasing). It should be noted in advance that there is no need to discuss anti-aliasing in mobile browsers due to the high screen resolution and weak processor performance of mobile phones. This article is mostly limited to large monitors on the desktop (I hope you’re not reading this blog on an 8K monitor).

Anti – aliasing and related technology

Anti-aliasing formation

Aliasing and image Aliasing are not the same thing, but for gamers they are almost the same thing. To use CSS anti-aliasing, we first have to mention aliasing.

Why the serrations?

Our eyes perceive the shape of an object and are aware of a “line” that doesn’t actually exist. In the image below, we can feel the lines, although they don’t look very smooth:

In the figure below, the lines with arrows represent our perceived line segments, and the grids where the remaining line segments intersect represent pixel grids. As you can see from the image above, wherever the arrow line passes through, it will be filled with yellow color. But the ideal line segment is perfect, it’s perfectly smooth. Mapping a smooth line segment in an uncertain direction onto a screen with a low DPI of pixels will result in information loss. The larger the pixel grain, the more serious the loss of information (hereinafter referred to as the sawtooth).

How can it look without teeth?

Here I’ve drawn a picture that allows you to look at it closely and then squint at it while standing slightly away from the monitor:

Around the pixels, I used yellow graffiti to fill in the missing information. The size of the yellow doodle represents pixel transparency. Here’s an anti-aliasing finished image, as you can see that the edges of the image are filled with transparent pixels:

Common anti-aliasing techniques

In the audio world, we can reduce the distortion of information coming to our ears with high-quality players and lossless audio. But in gaming, the average gamer is unlikely to have an 8K monitor at home. The move from 720p to 1080p resolution has been accompanied by several anti-aliasing technologies that have also grown with the game industry.

  • SSAA (Super Sampling Anti-Aliasing)

Super sampling anti-aliasing, it will double the resolution of the current picture rendering, such as 1024Γ—768 graphics on 2 times SSAA, the actual operation of the graphics card will become 2048Γ—1536, after this, and then down sampling, the multiple pixel fusion, mapping back to the display of a single pixel. Pixel fusion allows for a more natural color transition without noticeable burrs. However, as the computation of the hardware increases (exponentially), it can be expected to consume extremely high performance.

  • MSAA (Multi Sampling Anti-Aliasing)

Multi-sampling anti-aliasing, which multiply-samples data for a specific cache region — easily understood as multi-sampling the edges of a polygon. High performance cost, but good results.

  • FXAA (Fast Approximate anti-aliasing)

Fast approximate anti – aliasing, it finds the edges of all graphics in the screen and smooth processing. Although many graphic edges do not correspond to the actual edges of the game (such as materials and textures), FXAA has a low performance cost and is cost-effective, making it a common choice for anti-aliasing.

  • DLSS (Deep Learning Super Sampling)

Deep learning super sampling, it uses hardware-accelerated deep learning algorithm, according to geometry, color, time domain multiple aspects of data (in human terms, according to the past frame, shape, pixel momentum data, etc.) on real-time rendering of low resolution image reconstruction multi-fold super sampling results. Compared to traditional rendering, not only image quality can be greatly improved, but also frame rate can be greatly improved.


CSS anti-aliasing technology

Below, we mention several common anti-aliasing techniques.

CSS Font-Smoothing

The font smoothing property was an early CSS specification that was later removed for a variety of reasons. But it is still possible to become compatible with prefix attributes (such as -webkit-font Smoothing). In general, font smoothing has three options: None, Subpixel-Antialiased, and Antialiased. The value works just as the name suggests, for non-aliasing, sub-pixel and (full pixel) aliasing.

Typically, each pixel on a screen is a combination of three primary color stripes (perhaps red, green and blue). Subpixel anti-aliasing means that fonts will be rendered in subpixels (such as red light). Non-glowing pixels appear black, while the remaining pixels appear dark during anti-aliasing, as shown below:

Full-pixel anti-aliasing renders the font as a whole pixel, including red, blue and green stripes. In anti-aliasing, if the font is larger than one pixel, it will be smoothed by an adjacent transparent dark pixel, as shown below:

The width of the “back” character in the “back wave” is actually less than one pixel, so it is also rendered in a transparent dark color. In addition to the words, on the @maxvoltar blog, there are examples of pictures in English, directly quoted below:

  • none

  • subpixel-antialiased

  • antiliasing

So how do you choose the three values?

My advice is to just understand the rendering mechanics and presentation. Pixel anti-aliasing causes fonts to appear slightly thinner, while subpixel anti-aliasing causes fonts to appear too thick. The opposite is true on a black background. You don’t have to use it just because you know it — all three methods have their pros and cons. In general, just throw away this property and let the browser decide how the font should be rendered. If you introduce special fonts (such as printed fonts), smooth them out. (I believe that the scope of freedom is limited under the Chinese page layout.)

Attached, if you are interested, I left the relevant link at the end of the article, you can check it again.

CSS Image-Rendering

The image-rendering property is used to set the Image scaling algorithm. There are several common values for this property. See the following components:

As you can see, after the Pixelated value is set, the browser does not smooth the edges, whereas Auto softens the entire image. That is, using the Transform Scale to zoom in on the image, the browser will apply the default smooth zoom algorithm (maybe bilinear interpolation or something like that).

Can you enlarge the picture several times, and then reduce it back to the real size? Here are the results:

We don’t know if the browser has optimized multiple scales concatenation, or if it’s using some kind of sampling algorithm that doesn’t lose image information.

Hardware accelerated anti-aliasing

The hardware-accelerated anti-aliasing feature with the browser came to me when I was experimenting with PXAA (although it’s already been blotted out). After the element is rotated by Transform:Rotate, if the element is rendered by the GPU, the browser’s GPU’s anti-aliasing properties are applied — say you’re running the browser with a GTX 1060TI, The configuration can then be found in the Nvidia control panel (although this is quite a guess, to be tested). It sounds a bit complicated, but look at the following example:

After the element is rotated and hardware acceleration (TranslateZ) is applied, the rendered edges are smoothed. But if you just enable hardware acceleration or use rotation alone, it won’t work. In my tests, this anti-aliasing method was somewhat experienced on Chrome kernel browsers on Windows – you can even soften the edges by rotating them just 0.1Β° (though it’s not obvious).

So much for CSS-related anti-aliasing techniques, the next section starts with new ideas.

Pixel-Offset Anti-Aliasing

Pixel offset anti-aliasing (POAA) is an amazing method that no one seems to have shared on the Internet, but the results are quite amazing. I don’t know exactly how It works, but It works! . Here are two images drawn using the BackgroundImage property. Let me show you the result of applying POAA:

Results show

The principle of

Common game anti-aliasing techniques are based on data generated at multiple steps from model to lighting before and after rendering, so we can filter information and reconstruct the image based on frame history, pixel momentum, enhanced sampling, etc. But what the browser presents to the user is, so to speak, rendered. There seems to be very few ways we can participate in rendering inside the browser (CSS Houdini may come later). For example, with BackgroundImage drawing these pixels on your screen, you can’t participate in rendering to change them, and you can’t use pre-rendered data to tell the browser “you should do this.” The good news is that programmers are people who believe that any problem can be solved.

I think you remember from the beginning that we mentioned FXAA. FXAA can be summed up in two simple steps: edge finding -> edge reconstruction. In this blog post on FXAA, explain exactly how FXAA works. For a graphic edge that has been found, FXAA processes it to look like this, as shown in the next two images:

By feeding FXAA a source image, you can confirm the edges of an object by color or contrast, and make the whole look smooth by changing the opacity of the dots around the pixels. If you think about it, when we use background age, we already know where the edges are. The edge is not hidden in the king’s hat, it is in the code we write. For example, the source for the circular gradient in the previous section looks like this:

.circle-con {
    $c1: #cd3f4f;
    $c2: #e6a964;
    position: relative;
    height: 300px;
    background-image: repeating-radial-gradient(
        circle at 0% 50%.$c1 0.$c2 50px
    );
}
Copy the code

You can easily find the edge — yes, the place where the gradient color changes — 0px(50px). Now that we have the edge information, we need to reconstruct the edge. The reconstructed edge may be broken down into the following steps:

  • The point of transparency that you need some way to get
  • These points need to be able to form line segments
  • The line segment perfectly matches our background age
  • Overlay the line segment on the upper layer of the BackgroundImage to apply our changes

This is the general idea, we are not involved in browser rendering, but through post-processing methods like FXAA. Work on rendered images. However, when you think about the above steps, the problem is how to generate anti-aliased stripes.

In short, we need to continue to refine our thinking.

In BackgroundImage, pixels are basic units that cannot be divided, and the transparency of a point obviously cannot be simulated by the size of the point. There are two solutions:

  • Opacity, using CSS Opacity, or CSS RGBA function, SCSS function.
  • The two colors are fused to simulate pixel transparency, if you don’t want to pull JS, SCSS can also solve the problem.

As for line segments, you can also use BackgroundImage to simulate them. For example, for the above section of CSS code, you can rewrite it as follows:

.circle-con {
    $c1: #cd3f4f;
    $c2: #e6a964;
    $line-width: 1px;
    position: relative;
    height: 300px;
    background-image: repeating-radial-gradient(
        circle at 0% 50%.$c1 0,
        transparent calc($line-width),
        transparent calc(50px - $line-width),
        $c2 50px
    );
}
Copy the code

After taking the line segment, offset the container by a few pixels and place it in the browser to test the result:

As you can see, you naturally get a line segment of color mixed with transparency. The direction of transparency is just not where we want it to go. I want to be able to get the reverse of the transparent lines:

Through experimentation, I found that I could simply switch the color order. Let’s say this is a line segment drawn at 50% of the container:

.old {
    background: linear-gradient(
        var(--deg), 
        transparent, 
        transparent 
        calc(50% - var(--line-width)), 
        yellow 50%, 
        red 50%, 
        transparent calc(50% + var(--line-width)), 
        transparent
    );
}
Copy the code

If we reverse the colors of the line segments, we get:

.new {
    background: linear-gradient(
        var(--deg), 
        transparent, 
        transparent 
        calc(50% - var(--line-width)), 
        red 50%, 
        yellow 50%, 
        transparent calc(50% + var(--line-width)), 
        transparent
    );
}
Copy the code

We get the line segment blur we want! The next thing to do is match the lines.

Here’s a moment of wonder:

Well done!

Take a finished GIF, which looks best slightly away from the screen:

The finished product also added some contents and adjusted related parameters on the basis of the line matching:

  • Dark and light colors have different values of transparency
  • The offset of the X axis and the Y axis are different
  • The thickness of the fitting line segment is adjusted

The code of the finished product is as follows:

.repeat-con {
    --c1: #cd3f4f;
    --c2: #e6a964;
    --c3: #5996cc;
    position: relative;
    height: 300px;
    background-image: repeating-linear-gradient(
        var(--deg),
        var(--c1),
        var(--c1) 10px,
        var(--c2) 10px,
        var(--c2) 40px,
        var(--c1) 40px,
        var(--c1) 50px,
        var(--c3) 50px,
        var(--c3) 80px
    );

    &.antialiasing {
        &:after {
            --offsetX: 0.4 px.;
            --offsetY: -0.1 px.;
            --dark-alpha: 0.3;
            --light-alpha: 0.6;
            --line-width: 0.6 px.;
            content: ' ';
            position: absolute;
            top: var(--offsetY);
            left: var(--offsetX);
            width: 100%;
            height: 100%;
            opacity: 0.5;
            background-image: repeating-linear-gradient(
                var(--deg),
                var(--c3),
                transparent calc(0px + var(--line-width)),
                transparent calc(10px - var(--line-width)),
                var(--c2) 10px,
                var(--c1) 10px,
                transparent calc(10px + var(--line-width)),
                transparent calc(40px - var(--line-width)),
                var(--c1) 40px,
                var(--c2) 40px,
                transparent calc(40px + var(--line-width)),
                transparent calc(50px - var(--line-width)),
                var(--c3) 50px,
                var(--c1) 50px,
                transparent calc(50px + var(--line-width)),
                transparent calc(80px - var(--line-width)),
                var(--c1) 80px); }}}Copy the code

Theoretically, SCSS functions can automatically determine the position of line segments in code and generate pixels filled with anti-aliasing. Either LinearGradient, ConicGradient or RadialGradient can be anti-aliased. But I’m just writing it as an experiment, so I didn’t write the corresponding tool function. Welcome to Github.

Practice & Afterword

While playing at CodePen, watching big players draw pictures with BackgroundImage is pretty but annoying. So I tried to do an anti-aliasing Demo idea (really good kang is the source of motivation). This would be a code snipb of the Gists, but Gists I saw in a article recommended for gold Gists the day before yesterday someone drew coupons with BackgroundImage showing small circles with Gists Gists Gists. This is the Gists blog CSS Magic.

I should make it clear that POAA is only suitable for low-resolution monitors (strictly speaking DPI, which is the ratio of resolution to size). Like the 2K monitor I use, but because of its size, it works through POAA), which naturally rules out macs or phones. POAA can only be used as a technical supplement, so I call it “illusion” because it is not a convenient practical option. If you need to draw in a browser in production, SVG and Canvas will be preferred. Choosing BackgroundImage mapping, in my impression, only happens when it takes time and simplicity (like drawing coupons). This makes BackgroundImage an awkward substitute for developers who don’t know SVG. But… Shouldn’t SVG be something that designers know? So I don’t know who should draw the graph.

Finally, I recommend you to visit my blog, where you can experience the magic of POAA through the joystick and console.

Ah, I must have drunk at least three bottles of fat house happy water while writing this article. I’m gonna get fat and cry again. See here, don’t like three even comfort me before you go? / (γ„’ o γ„’) / ~ ~

Eggs:The brain to put

Ok, so this is not “pure visualization”, but a way of blurring the image to smooth out the edges, and then sharpening the image to enhance the edges. This method is often used in daily life when using tools such as PhotoShop to process images; Sometimes enhancements in computer games are handled this way.

Blur first, then sharpen, the two steps can not be reversed, and the adjustment of parameters is also very important (very metaphysical). Here’s how I tried it on my own blog:

  • CSS Filter Series SVG custom filters
  • CSS Filter Tandem Blur and Constract filters

But unfortunately, my level is limited, and I can’t get the desired effect, so I just close the case. Next problem.

To read more

  • DLSS 2.0- Real-time rendering image reconstruction based on deep learning
  • Please Stop β€œFixing” Font Smoothing
  • Use CSS to enable hardware acceleration to improve site performance
  • Implementing FXAA