The role of the picture Alpha pre-multiplied [transfer]

Premultiplied Alpha This concept of game development will not know. Xcode's engineering options include Compress PNG Files, Premultiplied Alpha for PNG, and Premultiplied Alpha for Texture Packer. So the question is, what is Premultiplied Alpha? I was confused by this question for a long time. I found this article by Nvidia before. Actually, I said it very clearly. However, there were a lot of related concepts that I didn't understand at the time, so I didn't understand it. I finally understood when I read Real Time Rendering a few days ago.

Alpha Blending

To figure this out, first understand how the alpha channel works. If you already know it, you can skip it.

The most common pixel representation format is RGBA8888 (r, g, b, a), 8 bits per channel, 0-255. For example, the red 60% transparency is (255, 0, 0, 153). In order to express the convenience, the alpha channel is generally recorded as a normalized floating point number of 0-1, which is (255, 0, 0, 0.6). The Premultiplied Alpha multiplies the RGB channel by the transparency (r * a, g * a, b * a, a), and the 50% transparent red becomes (153, 0, 0, 0.6). The

transparent channel works by Alpha Blending during rendering. If a color Cs with a transparency of as is rendered onto the color Cd, the mixed color is calculated by the following formula,

Co=αsCs+(1−αs)CdCo=αsCs+(1−αs)Cd

is rendered in 60% transparent red. To the white background as an example:

Co=(255,0,0)⋅0.6+(255,255,255)⋅(1−0.6)=(255,102,102)Co=(255,0,0)⋅0.6+(255,255,255)⋅(1−0.6)=(255,102,102)

That is, visually, (255, 0, 0, 0.6) is rendered to a white background and (255, 102, 102) is the same color. If the color is stored in Premultiplied Alpha format, ie Cs has been multiplied by transparency, the blending formula becomes:

Co=Cs′+(1−αs)CdCo=Cs′+(1−αs)Cd

Why do you want Premultiplied Alpha? The pixel format after

Premultiplied Alpha becomes unintuitive, because when drawing, first select an RGB color from the palette, and then set the transparency separately. If RGB is multiplied by transparency, it is unclear whether the primary color is what. As can be seen from the previous Alpha Blending formula, after the Premultiplied Alpha, there is one less multiplication when mixing, which can improve some efficiency, but this is not the main reason. The main reason is:

Textures without Premultiplied Alpha cannot be Texture Filtering (unless nearest neighbor interpolation is used).

is the most common filtering method for linear interpolation. A picture with a width of 2px and a height of 1px, the left pixel is red, and the right is green 10% transparency. If you scale this image to 1x1, then zoom 1 The color of the pixel is the result of linear interpolation of the left and right pixels, that is, the two channels of each pixel are added up and divided by 2. If you use a color without Premultiplied Alpha for interpolation, the result is:

((255,0,0,1)+(0,255,0,0.1))⋅0.5=(127,127,0,0.55)((255,0,0,1)+(0,255,0,0.1))⋅0.5=(127,127,0,0.55)

If Green Premultiplied Alpha, which is (0, 255 * 0.1, 0, 0.1), and after mixing with red:

((255,0,0,1)+(0,25,0,0.1))⋅0.5=(127,25,0,0.55)((255,0,0,1)+(0,25,0,0.1))⋅0.5=(127,25,0,0.55)

The third color is the result of a mixture without Premultiplied Alpha. Comparing the results of the fourth Premultiplied Alpha color, it is clear that the fourth color is more intuitive, and the third color is too green, because the green channel is not multiplied by transparency, so It takes too much weight when linearly interpolating.

So Premultiplied Alpha The most important thing is to make linear image interpolation with transparency image texture. Such rotation, scaling, or non-integer texture coordinates can be displayed normally, otherwise a strange color will be produced near the edge of the transparent pixel, as in the above example.

Texture Processing

We use PNG image textures, generally not Premultiplied Alpha. The game engine is manually processed after loading the PNG texture, and then glTexImage2D is passed to the GPU. For example, CCImage::premultipliedAlpha:

复制代码

void Image::premultipliedAlpha() {
    unsigned int* fourBytes = (unsigned int*)_data;
    for (int i = 0; i < _width * _height; i++) {
        unsigned char* p = _data + i * 4;
        fourBytes[i] = CC_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]);
    }  
    _hasPremultipliedAlpha = true;
}

复制代码

in Cocos2D-x and the GPU-specific texture format, such as PVR and ETC, generally generate textures. Is the default Premultiplied Alpha, these formats are generally GPU hard decoding, the engine will be slow to process with the CPU.

总之 glTexImage2D The texture data passed to the GPU is preferably Multiplied Alpha, either pre-multiplied by the texture tool when generating the texture, or Post-multiplied by the game engine or UI framework when the texture is loaded.