[TEXTURING] Preventing colour bleeding using premultiplied alpha technique.

Guides and how to's on anything related to JK2, whether it's about modding or in-game topics.
Post Reply
User avatar
fau
Staff
Posts: 433
Joined: 16 Aug 2015, 01:01
Location: Warsaw / Poland
Contact:

[TEXTURING] Preventing colour bleeding using premultiplied alpha technique.

Post by fau »

Problem

Common technique for alpha blending semi-transparent picture over opaque background in id tech 3 engine is using default

Code: Select all

blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
This happens automatically when you use semi-transparent texture and doesn't require any shader script.

However in many cases this approach is wrong and causes visible artifacts, the most common being "colour bleeding":
Correct
Correct
capture-premult.png (20.29 KiB) Viewed 19529 times
Colour bleeding
Colour bleeding
capture-bleeding.png (22.14 KiB) Viewed 19529 times
Solution

Colour bleeding affects pictures with varying alpha and colour values, especially when they have sharp alpha drops like the one above. One technique to fix it is using picture with "premultiplied alpha". This means multiplying pixel colours by their alpha value and using blendFunc GL_ONE GL_ONE_MINUS_SRC_ALPHA. This technique has been used in both Q3A and JK2 original shaders but it's not very obvious just from reading them.

You can premultiply picture manually in your image editor (a bit complicated, google it) or using script:
  • ImageMagick scripts:

    Code: Select all

    convert in.png -background black -alpha Remove in.png -compose Copy_Opacity -composite out.png
    
    Alternatively (you may need to escape braces with \ if using from commandline):

    Code: Select all

    convert in.tga ( +clone -alpha Extract ) -channel RGB -compose Multiply -composite out.tga
  • GIMP script: http://www.gaming-reverends.com/main/in ... lyalpha-en (Select Colors -> Premultiply Alpha on flat image)
  • Sorry for no photoshop script. If you find one and test it please let me know.
In case of a simple 2D sprite like in the example, or overlaying translucent picture right on top of opaque one use blendFunc GL_ONE GL_ONE_MINUS_SRC_ALPHA eg:

Code: Select all

medal_capture
{
        nopicmip
        {
                clampmap menu/medals/medal_capture.tga
                blendFunc GL_ONE GL_ONE_MINUS_SRC_ALPHA
        }
}
Translucent sprites inside the game world (eg. vines, grates, grass, net fence etc.) require additional depthFunc and depthWrite keywords, but this is not in the scope of this tutorial. Premultiplied alpha technique can be used to avoid colour bleeding in complex shaders using translucent pictures, although it requires good understanding of blending modes (so do complex shaders). If not, there are other ways to prevent colour bleeding you may want to google like generating border colours.

Explanation

Colour bleeding is caused by linear filtering. In the example above fully transparent pixels are stored as white (apparently this is how image editors store fully transparent pixels by default). Linear filter works independently on each R G B and A channel so border RGB channels get unproportionally tinted by adjacent white-transparent pixels creating halo effect. Premultiplied alpha technique gives 100% correct result when combined with filters.

There are more advantages of using premultiplied alpha space, you can learn more about it from this wikipedia article: https://en.wikipedia.org/wiki/Alpha_compositing and many other places on the internet.

Updates

24.02.2017 – Alternative ImageMagick script thanks to ent. Works with ImageMagick 7.x.
Post Reply
Created by Matti from StylesFactory.pl and Warlords of Draenor (modified by jk2.info)
Powered by phpBB® Forum Software © phpBB Limited
 

 

cron