LB Booster
Programming >> Language extensions >> Partially transparent sprites
http://lbb.conforums.com/index.cgi?board=extensions&action=display&num=1470652303

Partially transparent sprites
Post by Richard Russell on Aug 8th, 2016, 10:31am

I received a query by email about LBB's support for partially transparent sprites, and thought it might be of more general interest. Although the LBB docs refer to this feature ("Sprites can have a linear transparency (alpha mask), allowing the background to show through to varying degrees") they don't go into any detail.

All the sprite examples in the LB docs show the upper half of the BMP (the 'mask' section) as a 'one bit per pixel' bitmap; that is every pixel is either white (fully transparent) or black (fully opaque); the implication is that this is all that LB supports. However in practice if you use intermediate shades of gray in the mask region 'interesting' things happen: LB appears to be attempting to implement varying degrees of transparency, but doesn't get it right.

In LBB this works correctly: the mask section of the sprite BMP is treated as a linear alpha channel, varying between white (100% transparent) and black (100% opaque); a mid-gray level will result in a 50% transparency - the background will show through but will be attenuated by half.

One important thing to appreciate is that sprites in LB and LBB are 'premultiplied', that is the foreground image (the bottom half of the sprite BMP) is assumed to have already been multiplied by the inverse of the mask. With a conventional sprite what this means is that wherever the mask is white (100%) the image must be black (0%).

When using a partially-transparent mask the same applies. So for example in regions of the sprite in which the mask is mid-gray (50% transparency) the foreground image must be attenuated by 50%. Only then will the correct 'mix' of background and foreground be obtained.

The reason for this is to simplify run-time calculations. The conventional 'mix' equation requires two multiplications as follows:

Code:
output = alpha * foreground + (1.0 - alpha) * background 

but by pre-multiplying the foreground this is simplified to:

Code:
output = pre_multiplied_foreground + (1.0 - alpha) * background 

Here's a program (adapted from something written by Anatoly a few years ago) which illustrates the effect; the sprite is opaque red on the left and fully transparent on the right. If you run it in LB rather than LBB the result is, well, strange!

Code:
    nomainwin

    WindowWidth = 600
    WindowHeight =  300

    open "Transparency Test" for graphics_nsb as #gr
    #gr "trapclose [quit]"
    #gr "size 2"
    #gr "down"

    d = 100
    for i = 0 to 255
        c$ = i;" ";i;" ";i
        #gr "color ";c$
        #gr "line ";i*2;" ";0;" ";i*2;" ";d
        c$ = 255-i;" ";0;" ";0
        #gr "color ";c$
        #gr "line ";i*2;" ";d;" ";i*2;" ";2*d
        next
    #gr "getbmp sprite 0 0 511 ";2*d

    for i = 1 to 100
        #gr "backcolor ";int(rnd(1)*255);" ";int(rnd(1)*255);" ";int(rnd(1)*255)
        #gr "place ";int(rnd(1)*600);" ";int(rnd(1)*300)
        #gr "circlefilled ";int(rnd(1)*100+10)
    next
    #gr "getbmp bg 0 0 600 280"

    #gr "background bg"
    #gr "Addsprite sprite sprite"
    #gr "Spritexy sprite 44 80"
    #gr, "Drawsprites"
    wait
'-----------------------------------
[quit]
    close #gr
    call tryUnloadBMP "sprite"
    call tryUnloadBMP "bg"
end

sub tryUnloadBMP picName$
on error goto [dontCare]
    unloadbmp picName$
[dontCare]
end sub 

Richard.

Re: Partially transparent sprites
Post by Mystic on Aug 10th, 2016, 4:13pm

Thanks for the more detailed explanation Richard!