Tint not working after latest update?

It seems tint() has stopped working in the latest update.
I cant get it to change color or alpha.

Can anybody else confirm this?

@Kirl It seems to be working OK for me. Can you post a simple example of what’s not working for you.

@Kirl Here’s what I used to test tint.

function setup()
    parameter.integer("tintR",0,255,255)
    parameter.integer("tintG",0,255,255)
    parameter.integer("tintB",0,255,255)
    parameter.integer("tintA",0,255,255)
end

function draw()
    background(255)
    tint(tintR,tintG,tintB,tintA)
    sprite("Planet Cute:Character Boy",WIDTH/2,HEIGHT/2)
end

Thanks dave, it seems to still work on img, but not on fills + ellipse. A couple of projects which used this (possibly incorrect functionality?) dont render correctly anymore. Test code below.

-- Fade Tst

-- Use this function to perform your initial setup
function setup()
    img = image(WIDTH/10, WIDTH/10)
    setContext(img)
    ellipse(img.width/2, img.height/2, img.width)
    setContext()
end

-- This function gets called once every frame
function draw()
    background(40, 40, 50)

    fill(255)
    local step = WIDTH/10
    for i=1, WIDTH-step/2, step do
        local r = i/(WIDTH-step)
        
        fill(255)
        tint(255*r)
        ellipse(step/2+i, HEIGHT/2, WIDTH/10)
        sprite(img, step/2+i, HEIGHT/2-step)
        
        fill(0)
        text("tint \
" .. string.format("%.2f",tint()), step/2+i, HEIGHT/2)
    end
    
end

Try using tint’s alpha channel instead of the color ( tint(255, 255*r) ) it seems to be half strength. So alpha 255, seems to render as 125 for images.

@kirl It does look like something is wrong. I changed tint(255r) to tint(255r*2) to double the value and it seemed to work.

@kirl Put fill(255) after setContext(img). I guess the image needs that to work right.

There still seems to be something wrong, a modified example shows that tint(255, 255r) and fill(255, 255r) give different results.

-- Fade Tst

-- Use this function to perform your initial setup
function setup()
    img = image(WIDTH/10, WIDTH/10)
    setContext(img)
    fill(255)
    ellipse(img.width/2, img.height/2, img.width)
    setContext()
end

-- This function gets called once every frame
function draw()
    background(40, 40, 50)

    local step = WIDTH/10
    for i=1, WIDTH-step/2, step do
        local r = i/(WIDTH-step)
        
        fill(255)
        tint(255, 255*r)
        ellipse(step/2+i, HEIGHT/2, WIDTH/10)
        sprite(img, step/2+i, HEIGHT/2-step)
        
        noTint()
        fill(255, 255*r)
        ellipse(step/2+i, HEIGHT/2-step*2, WIDTH/10)
        
        
        fill(0)
        text("tint \
" .. string.format("%.2f",r), step/2+i, HEIGHT/2)
    end
    
end


@Kirl Looking at the documentation, tint is multiplied with the sprite color. fill probable doesn’t do that. So that might be the difference in the color.

This seems a bit counter intuitive though, you’d expect the color to stay the same if I only change the alpha. In order to get the expected behaviour one has to multiply the color by weird values…

tint(255*(1/r), 255r) yields the same results as fill(255, 255r). This doesn’t make sense to me. The old behaviour seems more straightforward, consistent, and much more readable.

Also is it correct that tint should only affect images and not drawing styles? Because I found it quite usefull in the past.

@Kirl good catch on this, I believe it’s due to us removing some pre-multiplied alpha blending from the built-in shaders. I’ll see if I can restore the functionality to the expected behaviour.

That’s great to hear Simeon! I tried fixing some old projects, but it proved to be a real headache to set the right color offsets in certain cases.

@Kirl looks like this is a bug in the sprite batching code. There’s a hidden API to disable sprite batching (and with modern iPads, this may not even impact performance).

Put spriteBatching(false) into your setup() function to turn it off.

@Kirl another way to fix this is to set img.premultiplied = true after you finish rendering it with setContext() in your setup() function. This will tell Codea that your image should use the premultiplied render path and won’t multiply the alpha against the texture colours.

Edit: you should probably use this solution for now. I’ll change the runtime to mark images used in setContext as premultiplied automatically in future, so if you use this solution then it won’t effect your code when Codea is updated (except that you’ll be able to delete the manual setting of the image’s premultiplied flag).

Excellent, thanks for a fix that I can apply right now simeon!

spriteBatching(false) didn’t work for me though, unless I did something wrong…

@Kirl oh the spriteBatching change must be relying on some other changes. The premultiplied fix is the better one to use anyway.