Partially-transparent sprites

Discussions related to the extensions to the language available in LBB
guest
Site Admin
Posts: 197
Joined: Tue Apr 03, 2018 1:34 pm

Partially-transparent sprites

Post by guest »

(copied from the old forum)

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:

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

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

    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: Select all

    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.