Game Development
Raiting:
12

How to overcome the common artifacts of graphics


The artists painted bright graphics, the programmers built it into the game, the animators added movements - it would seem, everything is ready. But no, managers do not like:
You need to remove gray spots and white lines. Then the pulsating button jerks, there the progress bar goes with a ladder.
You look at the game resources - there is nothing in them, all sprites are cropped. You read the code - the formulas are correct, there is enough shader accuracy. But the result was still unimportant. Where is the mistake?

image

A small poll for those who already know where the artifacts come from. What to do in this situation?


You need a powerful graphics card and fresh drivers;
It is worth making downloadable sets of graphics for all possible screen resolutions;
Square textures with the sizes of a degree of two do not have such problems;
This is all due to the compression of graphics (PVRTC / DXT5 / ETC1 / ...);
In the graphics editor you will have to smudge the edges slightly;
This should have happened, because we did not prepare graphic data;
Only antialiasing will help;
You need textures and targets in the premultiplied alpha mode.

What is the correct answer, why exactly and how to overcome the artifacts of graphics read under the cut.
Bilinear texture filtering
Mobile platforms use bilinear texture filtering so that the sprites can move smoothly and at different resolutions do not blur into pixels. In terms of OpenGL ES, this is the GL_LINEAR parameter:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
image
Example of magnification 4 times (centered GL_NEAREST, right GL_LINEAR).

image
Example of a 2-fold decrease (centered on GL_NEAREST, on the right is GL_LINEAR).

image
There are white artifacts in the tree branches in the game, although there is nothing in the editor. Under the description everything is like here

When a texture is drawn with a scale other than 1.0 or with fractional coordinates, color artifacts appear on the border with transparency. The matter is that OpenGL ES for usual RGBA-textures firstly independently interpolates channels R, G, B, A, and only then this result is mixed with the screen. If the interpolation looks natural for a channel with alpha (A), then for the color channels R, G, B, previously unseen pixels begin to affect the visible neighbors at the object boundary.

As one solution to the problem, it is suggested to use textures with pre-indexed alpha ( premultiplied alpha ), then Interpolation will occur without artifacts. It is the premultiplied alpha mode that is useful when drawing graphics into a target, in particular, if you independently implement anti-aliasing of 3D models using OpenGL ES 2.0.

An alternative solution is to add strokes in transparent areas. For this, transparent pixels borrow color from an opaque neighbor or averaging colors from several opaque neighbors. Such a calculation is conveniently carried out by the front of the wave from the boundary of the transparent to the opaque.

image
Example of a 2-pixel stroke in the transparent area (far right)

In addition, you can collect graphics sets for all resolutions and draw sprites only in whole coordinates. On retina-screens the movement will be smooth enough. Only here the graphics will be very much.
Pixel Shaders
One has only to think about how the texture is drawn in non-integer coordinates on a single scale, as soon as the problem of boundary aliasing arises. The fact is that iron calculates the physical pixels in the pixel shader, and for our fractional boundary, the texture coordinates s, t move beyond [0..1]. In the GL_CLAMP_TO_EDGE mode, when you go beyond the boundaries of the texture, the frame overlaps. For textures that are joined, this is normal, but for different sprites there are thickenings.

image
In order not to ripple the edges of the sprite is enough to make a one-pixel (for scale 1) or 2-pixel (for the scale 0.5) transparent frame and draw it as part of the sprite. In other words, the trim command in the graphics editor not only removes transparency, but adds the aliasing problem. Therefore, it will be more correct to do trim, and then increase the canvas relative to the center by 2 pixels (regular graphics) or 4 pixels (retina graphics with the possibility of downscale).

image

image
Example of border aliasing (from above) and smooth motion (from below)

For 3D, by the way, the idea of ​​overdraw also works , but implementation requires preliminary calculations and the formation of additional triangles with transparency.
Atlases
When you put the texture in the atlas, the mode property is lost, because GL_CLAMP_TO_EDGE , because now it works on boundaries of the entire atlas. And since there is no duplication of the boundaries of the elements of the atlas, then joints can break.

image
Enlightenings in honey when placing textures in an atlas

Here, the duplication of the outer boundary of the joining elements in the atlas itself comes to the rescue. The size of the frame depends on the scale of the drawing, usually 1-2 pixels are enough. For a scale> = 1, a single-pixel frame is sufficient. Only in case of reduction, 2 or more pixels are required.
Compressed atlases
In order for the game to work on devices with a small amount of RAM, you have to compress the atlases into one of the available formats: PVRTC, ETC1, DXT1, DXT5, ETC2, etc.

The peculiarity of these hardware formats is the separation of the entire texture into 4x4 blocks and further compression with losses. In addition to blockiness, for each block, as a rule, not more than 2 base colors are available. As a result, all 16 pixels of the block are obtained by choosing from 4 possible values ​​calculated in some way based on the base colors.

For formats with independent blocks ( ETC1 / 2 , DXT1 / 5) it is enough to expand each element that is placed in a regular atlas , to a rectangle with a size multiple of 4 pixels. In this case, neighboring elements will not affect each other.

image
Example of the isolation of the elements of the atlas in blocks 4x4

For the PVRTC format, where almost every pixel is affected by the colors of 4 adjacent blocks, dilute the elements of the atlas to a distance of 4 pixels. This is achieved by forming a 2-pixel protective area along the contour of each element of the atlas, where the useful area is centered in this case.

image

For polygonal atlases helps to maintain the distance between neighboring elements.
Results
The methods considered combine special processing of graphic data: both individual textures and elements of the atlas. Such processing is well automated and, as a rule, does not distract employees from the creative process.

Therefore, in the survey, the most common correct answer is 6, "It should have happened, because we did not prepare graphic data." I note that this does not detract from the usefulness of other methods.

Now is the time to reflect and ask: "what can the resource collector do and is the preparation of graphics data by processes?"

P.S. Comments are welcome to the methods considered, as well as information on other effective ways to combat artifacts in 2D graphics.
Skull 10 october 2017, 10:21
Vote for this post
Bring it to the Main Page
 

Comments

Leave a Reply

B
I
U
S
Help
Avaible tags
  • <b>...</b>highlighting important text on the page in bold
  • <i>..</i>highlighting important text on the page in italic
  • <u>...</u>allocated with tag <u> text shownas underlined
  • <s>...</s>allocated with tag <s> text shown as strikethrough
  • <sup>...</sup>, <sub>...</sub>text in the tag <sup> appears as a superscript, <sub> - subscript
  • <blockquote>...</blockquote>For  highlight citation, use the tag <blockquote>
  • <code lang="lang">...</code>highlighting the program code (supported by bash, cpp, cs, css, xml, html, java, javascript, lisp, lua, php, perl, python, ruby, sql, scala, text)
  • <a href="http://...">...</a>link, specify the desired Internet address in the href attribute
  • <img src="http://..." alt="text" />specify the full path of image in the src attribute