Retained mode fill problem with very small alpha values

I was playing around with retained mode a bit for creating some nice visuals. to fade them out, I draw a black rectangle with small alpha over the scene each frame. but this seems only to work for alpha values above 10. Below 10 the already present pixels only get gray. the smaller the alpha is, the lighter are the artefacts. See the example below. Is this a bug? I use iPad3 if that is important.

-- CoolVisual

backingMode(RETAINED)
--displayMode(FULLSCREEN)

time = 0

-- Use this function to perform your initial setup
function setup()
    background(0, 0, 0, 255)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    fill(0, 0, 0, 1)
    noStroke()
    noSmooth()
    rectMode(CENTER)
    rect(WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)


    -- This sets the line thickness
    strokeWidth(3)
    smooth()

    -- Do your drawing here
   lineCapMode(SQUARE)
    for i = 1,20 do
        stroke(127+127*math.sin(time/125), 127+127*math.sin(time/37), 127+127*math.sin(time/91), 255)
        local x1 = WIDTH/2 + 417 * math.sin(time/2)
        local y1 = HEIGHT/2 + 317 * math.sin(time/17)
        local x2 = WIDTH/2 + 419 * math.sin(time/25)
        local y2 = HEIGHT/2 + 327 * math.sin(time/3)
        line(x1, y1, x2, y2)
        time = time + 0.01
   end
end

Same thing happens with iPad 2

Hello @KilamMalik, it is not a bug, in the sense that it is what is expected to happen. It is the consequence of colour channels being represented by integers in the range 0 to 255 and the effects of rounding. See the code below, for further explanation:


--
-- Alpha blending, at low alpha
--

-- For pre-multiplied format colours:
-- Dca' = Sca + (1 - Sa/255) * Dca
-- Da'  = Sa  + (1 - Sa/255) * Da
-- 
-- c = red, green or blue; a = alpha (opacity).
-- S = source; D = destination (the canvas).
-- Each channel is an integer between 0 and 255.

-- For source colour (0, 0, 0, Sa) and Da = 255:
-- Dca' = Dca     - Sa * Dca / 255
-- Da'  = Da + Sa - Sa * Da  / 255 = 255

-- If Sa * Dca / 255 is less than 0.5, then there can be no effect
-- on the canvas. Or, equivalently, if:
-- Sa * Dca < 127.5.

-- If Sa = 10, this inequality is satisfied if:
-- Dca < 12.75 < 13.

-- If Sa = 1, this inequality is satisfied if:
-- Dca < 127.5 < 128.

backingMode(RETAINED)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    iparameter("alpha", 1, 15)
    oAlpha = alpha
    print("Touch the viewer to restart.\
")
    for i = 1, 15 do
        print(i, math.floor(127.5/i))
    end
    dim = math.min(WIDTH, HEIGHT) * 3/5
    noStroke(); noSmooth(); rectMode(CENTER)
    init()
end

function draw()
    if alpha ~= oalpha then -- Slider has changed
        oalpha = alpha
        init()
    end
    fill(0, alpha)
    rect(WIDTH/2, HEIGHT/2, dim, dim)
end

function touched(touch)
    init()
end

function init()
    background(127.5/alpha)
    fill(0)
    for j = 0, 7 do
        for i = j % 2, 7, 2 do
            rect(WIDTH * (i/8 + 1/16), HEIGHT * (j/8 + 1/16),
                WIDTH/8, HEIGHT/8)
        end
    end
    local r = math.random(128, 255)
    local g = math.random(128, 255)
    local b = math.random(128, 255)
    fill(r, b, g)
    rect(WIDTH/2, HEIGHT/2, dim, dim) 
end

Hello @mpilgrem, thats interesting. As Codea uses OpenGL, that means OpenGL uses integer on iPad? Or does Codea only call glColor3i instead of glColor3f? I never had this problems on the PC, but maybe I just didn’t run into it before as I’m trying different things with Codea :slight_smile: Thanks for looking into that, so my only option now is to only call the alpha-rect every n-th frame… which looks a bit jerky, but slows down the fade out.