Strange alpha blending when transforming

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
BitterTea
Prole
Posts: 2
Joined: Mon Jul 26, 2021 10:09 am

Strange alpha blending when transforming

Post by BitterTea »

Hello everyone. I dont know if this is a bug or what, but Im looking for the way around it.

Basically, when linear filtering is on and any transformation (other than translation) is applied, textures with alpha show strange blending artifacts that look like an outline. Its very noticeable when background is the same color as the texture.

Example:

Texture used - solid color square in the middle and a black border representing the edges of the texture. Everything else is fully transparent
Image

Result
Image

Same happens with meshes, with addition that it shows up also when vertices change positions.
Same if rendered to a canvas, but the outline becomes darker for some reason.

Setting filtering to nearest fixes it.

Adding a shader that discards alpha lower than a threshold (about 0.6-0.7) does also hide this outline, but cuts off the alpha drastically.

Example code:

Code: Select all

tex = love.graphics.newImage('tex.png') --texture from the post
love.graphics.setBackgroundColor(167/255,127/255,255/255)

function love.draw()
    love.graphics.draw(tex,50,100) -- normal
    love.graphics.draw(tex,320,100,0,1.2,1.2) -- scaled
end
Is there any way around it?
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Strange alpha blending when transforming

Post by grump »

That's because the transparent pixels have a color, too - they are probably white in your texture, and filtering causes that white to bleed into the purple. Make them the same color as the interior and the issue will disappear.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Strange alpha blending when transforming

Post by pgimeno »

Yeah indeed. To expand on grump's answer, I've made a series of images to explain what's going on.

Here's your image in GIMP with a 2x zoom:

Image

The transparent area is alpha. GIMP has a nice option to separate the alpha from everything else, accessible from Layer -> Mask -> Add Layer Mask:

Image

That converts the alpha of the image into a layer mask, which is something you can draw on independently of the layer, or enable/disable. Here's the layer list view after adding the mask:

Image

By Ctrl+clicking on the layer mask, you disable it and that lets you view the original colours in the layer (you can try it with this image of an invisible pink unicorn, to verify that it is indeed pink: https://upload.wikimedia.org/wikipedia/ ... nicorn.png )

This is what you see:

Image

This proves that grump was right, the pixels were white. Now, linear filtering is a linear interpolation between pixels. When the RGB of that image is scaled, say 4x, with linear filtering, this happens:

Image

See how the pixels fade to white, which is the neighbouring colour? When the alpha is applied, the white is still visible:

Image

And that's the problem that you're having. The easiest solution, as grump said, is to use an image that has all purple pixels even in transparent areas. In GIMP, when we have the mask separated and disabled, we can pick the purple with the eyedropper then flood-fill the white with purple, and finally apply the mask again (to turn it into alpha) and save:

Image

Result:
Image
User avatar
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

Re: Strange alpha blending when transforming

Post by ReFreezed »

To expand a bit more to what the others have said, programmatically you'd have to do the equivalent of this:

Code: Select all

local texData = love.image.newImageData("tex.png")

local transparentRed   = 167/255
local transparentGreen = 127/255
local transparentBlue  = 255/255

texData:mapPixel(function(x,y, r,g,b,a)
	-- Note that half-transparent pixels are not handled.
	if a == 0 then
		return transparentRed, transparentGreen, transparentBlue, 0
	else
		return r, g, b, a
	end
end)

tex = love.graphics.newImage(texData)
This is something you have to think of whenever dealing with transparency in textures and any kind of filtering (except for nearest-neighbor). Unfortunately, image editors generally don't do anything like this automatically when saving an image. Fortunately it's easy to make your own tool to fix this.
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Strange alpha blending when transforming

Post by grump »

ReFreezed wrote: Mon Jul 26, 2021 1:59 pm programmatically you'd have to do the equivalent of this:
Or just convert to premultiplied alpha:

Code: Select all

local img = love.image.newImageData('tex.png')
img:mapPixel(function(x, y, r, g, b, a)
	return r * a, g * a, b * a, a
end)

-- but you have to remember to set the correct blend mode:
love.graphics.setBlendMode('alpha', 'premultiplied')
BitterTea
Prole
Posts: 2
Joined: Mon Jul 26, 2021 10:09 am

Re: Strange alpha blending when transforming

Post by BitterTea »

Thank you guys! Changing color values of transparent pixels solves this issue.

It made me wondering though, couldnt LOVE just make an exception to its linear filter for 0.0 alpha pixels to blend with neighbors only by alpha channel and not the colors? I mean, I havent seen other frameworks/engines behave like LOVE does currently.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Strange alpha blending when transforming

Post by grump »

BitterTea wrote: Mon Jul 26, 2021 2:34 pm It made me wondering though, couldnt LOVE just make an exception to its linear filter for 0.0 alpha pixels to blend with neighbors only by alpha channel and not the colors?
That's not LÖVE's linear filter, that's how the blendmode formula in the hardware works. You can use premultiplied data instead to get the expected behavior, code for this is in this thread.
I mean, I havent seen other frameworks/engines behave like LOVE does currently.
Which have you seen that work differently?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot], zingo and 3 guests