Texture paint: Bad alpha fringe #34233

Closed
opened 2013-02-14 02:57:37 +01:00 by WK Bong · 21 comments

%%%Win7-64, GTX 560 Ti
2.66 test build, r54336

Problem exist back to 2.64a (didn't check other older versions)

Bad alpha fringe in texture paint.
Easy to produce.

Attached 2 files:

  1. Screenshot of the bug in 2.64a
  2. Blend file from 2.66 testbuild

%%%

%%%Win7-64, GTX 560 Ti 2.66 test build, r54336 Problem exist back to 2.64a (didn't check other older versions) Bad alpha fringe in texture paint. Easy to produce. Attached 2 files: 1. Screenshot of the bug in 2.64a 2. Blend file from 2.66 testbuild %%%
Author

Changed status to: 'Open'

Changed status to: 'Open'
Author

%%%Also while painting in total alpha, you don't have a gauge where the canvas is, it is transparent. Selected outline still needed in texture paint mode.%%%

%%%Also while painting in total alpha, you don't have a gauge where the canvas is, it is transparent. Selected outline still needed in texture paint mode.%%%

%%%Developer note:
Checked on file. That's not color management issue, it just how brushes are blending with transparent but colored background. Not sure how this shall be done actually..%%%

%%%Developer note: Checked on file. That's not color management issue, it just how brushes are blending with transparent but colored background. Not sure how this shall be done actually..%%%
Member

%%%This is not a bug but a limit of using 24 bits color (and 8 byte alpha). You paint using very low blending values, and this accumulates badly when repeated many times.
Internally we should use 16 bits (or floats) or to make this behave correctly. Or code ways to merge operations in 1 pass, to prevent these rounding errors.

I will assign this to Antony for future reference, he'll be working on better painting in Blender this year. It's no bug however, but a real (important) todo item.%%%

%%%This is not a bug but a limit of using 24 bits color (and 8 byte alpha). You paint using very low blending values, and this accumulates badly when repeated many times. Internally we should use 16 bits (or floats) or to make this behave correctly. Or code ways to merge operations in 1 pass, to prevent these rounding errors. I will assign this to Antony for future reference, he'll be working on better painting in Blender this year. It's no bug however, but a real (important) todo item.%%%

%%%It is my understanding that color blending should be done in premultiplied space. I think for byte images we use straight alpha, but for this kind of operations this is bound to give trouble.%%%

%%%It is my understanding that color blending should be done in premultiplied space. I think for byte images we use straight alpha, but for this kind of operations this is bound to give trouble.%%%

%%%Hi, a first try for a fix is to check if the imbuf is using alpha and if it does, check if we are in premul space. If not, multiply color with alpha prior to blending. This is trivial and could possibly be done before release. My only skepticism is: Should we do this automatically for mix mode blending, or possibly have an extra "over" blend mode that does that? My understanding is: mix is just a linear combination of colors while in painting we do over operation, not mix. If mix is supposed to behave like over, then other places where mix is used will be buggy as well.

Also I'm a bit in the dark about what space other color operation modes are supposed to work in.%%%

%%%Hi, a first try for a fix is to check if the imbuf is using alpha and if it does, check if we are in premul space. If not, multiply color with alpha prior to blending. This is trivial and could possibly be done before release. My only skepticism is: Should we do this automatically for mix mode blending, or possibly have an extra "over" blend mode that does that? My understanding is: mix is just a linear combination of colors while in painting we do over operation, not mix. If mix is supposed to behave like over, then other places where mix is used will be buggy as well. Also I'm a bit in the dark about what space other color operation modes are supposed to work in.%%%

%%%Reopening, this -is- a bug.%%%

%%%Reopening, this -is- a bug.%%%
Member

%%%RGB byte images should all be straight alpha.

But many blending ops assume brushes to be premul...%%%

%%%RGB byte images should all be straight alpha. But many blending ops assume brushes to be premul...%%%

%%%As far as I can tell it's only projecting painting that is wrong here, when disabling that or painting in the image editor the fringes are not there.

Further there is a more subtle (old) issue here, which is that you can also get fringes due to the OpenGL texture being in straight alpha. All OpenGL textures should actually be premultiplied for mipmapping and texture filtering to work correct. It's mostly noticeable if you have a straight alpha image with e.g. a white background that is fully transparent.%%%

%%%As far as I can tell it's only projecting painting that is wrong here, when disabling that or painting in the image editor the fringes are not there. Further there is a more subtle (old) issue here, which is that you can also get fringes due to the OpenGL texture being in straight alpha. All OpenGL textures should actually be premultiplied for mipmapping and texture filtering to work correct. It's mostly noticeable if you have a straight alpha image with e.g. a white background that is fully transparent.%%%
Author

%%%Agree on the projection painting is one of the culprit here.

  1. Projection Painting ON, Straight alpha ON, the fridge halo is most visible.
  2. Projection Painting Off and Straight Alpha ON, the fridge is subtle
  3. Projection Painting Off, Permultiply ON, the fridge is subtle
    These are with the brush textures premultiplied and MIP Map ON

Plus one more big problem I see is the UX.
To get a brush texture to be most useable (with least problem), one needs to set so many parameters.
As far as my experience tell me, there is only but 1 brush texture setting that is acceptable for texture painting to mimic the quality of 2D painting software.
That setting is

  1. Alpha texture, white on texture part, alpha on else (User must define)
  2. Alpha permultiplied
  3. MIP Map on
  4. Image mapping clip for good preview of the brush

How about making these settings default?%%%

%%%Agree on the projection painting is one of the culprit here. 1. Projection Painting ON, Straight alpha ON, the fridge halo is most visible. 2. Projection Painting Off and Straight Alpha ON, the fridge is subtle 3. Projection Painting Off, Permultiply ON, the fridge is subtle These are with the brush textures premultiplied and MIP Map ON Plus one more big problem I see is the UX. To get a brush texture to be most useable (with least problem), one needs to set so many parameters. As far as my experience tell me, there is only but 1 brush texture setting that is acceptable for texture painting to mimic the quality of 2D painting software. That setting is 1. Alpha texture, white on texture part, alpha on else (User must define) 2. Alpha permultiplied 3. MIP Map on 4. Image mapping clip for good preview of the brush How about making these settings default?%%%

%%%This can get complex. I'm not sure what is the correct approach either.

For byte images, we can do association during painting, however for float images, we should unassociate and modify the color also when doing alpha painting operations. Is this correct? I'm not sure but I think it's possible to have premultiplied images with colour > 0 and alpha = 0. How does that case get handled? My color fu is not good enough here.%%%

%%%This can get complex. I'm not sure what is the correct approach either. For byte images, we can do association during painting, however for float images, we should unassociate and modify the color also when doing alpha painting operations. Is this correct? I'm not sure but I think it's possible to have premultiplied images with colour > 0 and alpha = 0. How does that case get handled? My color fu is not good enough here.%%%

%%%It is simply not defined. A premultiplied image can have any color if alpha = 0. Its like a random colored light with 0 intensity. You can't measure the color it has, but if you make it brighter (increase alpha) you might be surprised.

Thats why it is best to avoid premultiplication in such cases. Premultiplied colors make sense for additive operations, but for anything else you should use straight alpha together with the over operation, which essentially does not touch the color if both alpha values are zero or replaces the color if one alpha is zero with the other. %%%

%%%It is simply not defined. A premultiplied image can have any color if alpha = 0. Its like a random colored light with 0 intensity. You can't measure the color it has, but if you make it brighter (increase alpha) you might be surprised. Thats why it is best to avoid premultiplication in such cases. Premultiplied colors make sense for additive operations, but for anything else you should use straight alpha together with the over operation, which essentially does not touch the color if both alpha values are zero or replaces the color if one alpha is zero with the other. %%%

%%%Tobias, I think you are mistaken here. Color components give the perceived intensity in premultiplied space. I am thinking two possible solutions here.

Either "paint occlusion" for add/erase alpha or disallow alpha operations for float images entirely. I'll test it out and see.%%%

%%%Tobias, I think you are mistaken here. Color components give the perceived intensity in premultiplied space. I am thinking two possible solutions here. Either "paint occlusion" for add/erase alpha or disallow alpha operations for float images entirely. I'll test it out and see.%%%

%%%"Its like a random colored light with 0 intensity."

This is factually incorrect. Associated alpha images with RGB values contain their intensities (luminance) across all three RGB values. The alpha purely measures occlusion.

"Thats why it is best to avoid premultiplication in such cases."

This too, is factually incorrect. See Alvy Ray Smith et al. Associated / premultiplied alpha currently models reality more appropriately than unassociated / straight / unpremultiplied.

Is this a bug? If the paint stroke is honouring the transparent RGB value, we should expect a pinky tone if painting red atop of a white, no? That's part of the downside of an unassociated / straight / unpremultiplied image.

"1. Projection Painting ON, Straight alpha ON, the fridge halo is most visible."

As above. Ton's suggestion might be right here. This may not be a bug.

"2. Projection Painting Off and Straight Alpha ON, the fridge is subtle"

This is the accumulation error that Ton mentions?

"3. Projection Painting Off, Permultiply ON, the fridge is subtle"

This, while incorrectly mangling the image, is again the accumulation issue.

Is this even a bug beyond the accumulation error?%%%

%%%"Its like a random colored light with 0 intensity." This is factually incorrect. Associated alpha images with RGB values contain their intensities (luminance) across all three RGB values. The alpha purely measures occlusion. "Thats why it is best to avoid premultiplication in such cases." This too, is factually incorrect. See Alvy Ray Smith et al. Associated / premultiplied alpha currently models reality more appropriately than unassociated / straight / unpremultiplied. Is this a bug? If the paint stroke is honouring the transparent RGB value, we should expect a pinky tone if painting red atop of a white, no? That's part of the downside of an unassociated / straight / unpremultiplied image. "1. Projection Painting ON, Straight alpha ON, the fridge halo is most visible." As above. Ton's suggestion might be right here. This may not be a bug. "2. Projection Painting Off and Straight Alpha ON, the fridge is subtle" This is the accumulation error that Ton mentions? "3. Projection Painting Off, Permultiply ON, the fridge is subtle" This, while incorrectly mangling the image, is again the accumulation issue. Is this even a bug beyond the accumulation error?%%%

%%%"This is factually incorrect. Associated alpha images with RGB values contain their intensities (luminance) across all three RGB values. The alpha purely measures occlusion."

This is true, but only if alpha is > 0 and not very close to 0. In case of zero alpha you loose all luminance information and if you are very close to zero alpha you loose color/luminance precession. This usually doesn't matter, but it matters in the case when you just manipulate the alpha. Lets say you have (0.6, 0.2, 0.9) as a color/luminance and associate an alpha with one ULP bigger then 0: (0.6 * ULP, 0.2 * ULP, 0.9*ULP, ULP) -> (ULP, 0, ULP, ULP). If you now set Alpha to a higher value again you definitely don't get back the initial values. They will be very quantized and in case of alpha = 0 you won't get even close.

"This too, is factually incorrect. See Alvy Ray Smith et al. Associated / premultiplied alpha currently models reality more appropriately than unassociated / straight / unpremultiplied."

I have read some of his papers. But anything related to premultiplied alpha is also related to matting, where it makes perfectly sense. But changing the alpha in a drawing operation is not the same as matting and shouldn't be done with premultiplied alpha, except you can live with the accuracy loss.

"Is this a bug? If the paint stroke is honouring the transparent RGB value, we should expect a pinky tone if painting red atop of a white, no?"

This depends on the alpha of the destination and the source, on the desired operation and which type of representation is used as well. See: http://docs.oracle.com/javase/7/docs/api/java/awt/AlphaComposite.html
%%%

%%%"This is factually incorrect. Associated alpha images with RGB values contain their intensities (luminance) across all three RGB values. The alpha purely measures occlusion." This is true, but only if alpha is > 0 and not very close to 0. In case of zero alpha you loose all luminance information and if you are very close to zero alpha you loose color/luminance precession. This usually doesn't matter, but it matters in the case when you just manipulate the alpha. Lets say you have (0.6, 0.2, 0.9) as a color/luminance and associate an alpha with one ULP bigger then 0: (0.6 * ULP, 0.2 * ULP, 0.9*ULP, ULP) -> (ULP, 0, ULP, ULP). If you now set Alpha to a higher value again you definitely don't get back the initial values. They will be very quantized and in case of alpha = 0 you won't get even close. "This too, is factually incorrect. See Alvy Ray Smith et al. Associated / premultiplied alpha currently models reality more appropriately than unassociated / straight / unpremultiplied." I have read some of his papers. But anything related to premultiplied alpha is also related to matting, where it makes perfectly sense. But changing the alpha in a drawing operation is not the same as matting and shouldn't be done with premultiplied alpha, except you can live with the accuracy loss. "Is this a bug? If the paint stroke is honouring the transparent RGB value, we should expect a pinky tone if painting red atop of a white, no?" This depends on the alpha of the destination and the source, on the desired operation and which type of representation is used as well. See: http://docs.oracle.com/javase/7/docs/api/java/awt/AlphaComposite.html %%%

%%%As I said these operations should be done in premultiplied space. One other thing that I noticed gimp does not allow that we do, is alpha operations on the alpha channel. The reason is simple: If you tweak alpha you need to also tweak colour in premultiplied space. I would say only allow editing alpha in straight space, if at all.

@Sergey, brecht. This looks like it would be a lot easier if we had premultiplied alpha in byte images too so I am curious why it isn't so. I could of course convert on the go but it will cost in performance. Should we consider switching there for byte images too?%%%

%%%As I said these operations should be done in premultiplied space. One other thing that I noticed gimp does not allow that we do, is alpha operations on the alpha channel. The reason is simple: If you tweak alpha you need to also tweak colour in premultiplied space. I would say only allow editing alpha in straight space, if at all. @Sergey, brecht. This looks like it would be a lot easier if we had premultiplied alpha in byte images too so I am curious why it isn't so. I could of course convert on the go but it will cost in performance. Should we consider switching there for byte images too?%%%

%%%Gimp allows operations on the alpha channel. You can directly manipulate the alpha or you can use masks or even both together. No problem, because it stores the color separated from the alpha. But that obviously a thing you shouldn't try with premultiplied alpha, because of the singularity at 0 opacity. %%%

%%%Gimp allows operations on the alpha channel. You can directly manipulate the alpha or you can use masks or even both together. No problem, because it stores the color separated from the alpha. But that obviously a thing you shouldn't try with premultiplied alpha, because of the singularity at 0 opacity. %%%

%%%Closed a duplicate report: http://projects.blender.org/tracker/index.php?func=detail&aid=35095&group_id=9&atid=498

I don't think premultiplied byte images can work, because of precision issues, 8 bit is not to store alpha * color and then recover the color afterwards. As far as I can tell we just have to get the math for the blending functions right, if Gimp and Photoshop can do it then we should be able to do it too?

Testing in Gimp, it seems that the colors are blended as if premultiplied, no color from zero alpha areas bleeds in. The side effect of this is that it gives hard edges in the RGB part of the image, you can see this when doing Anti-Erase to reveal the RGB colors. There is no way to avoid that though, if you paint over zero alpha areas the RGB under the brush will be lost as it can't be in the blending or otherwise you get fringing.

So as part of the blending operations we have to premultiply the color and then unpremultiply it afterwards, or some equivalent in integer math.%%%

%%%Closed a duplicate report: http://projects.blender.org/tracker/index.php?func=detail&aid=35095&group_id=9&atid=498 I don't think premultiplied byte images can work, because of precision issues, 8 bit is not to store alpha * color and then recover the color afterwards. As far as I can tell we just have to get the math for the blending functions right, if Gimp and Photoshop can do it then we should be able to do it too? Testing in Gimp, it seems that the colors are blended as if premultiplied, no color from zero alpha areas bleeds in. The side effect of this is that it gives hard edges in the RGB part of the image, you can see this when doing Anti-Erase to reveal the RGB colors. There is no way to avoid that though, if you paint over zero alpha areas the RGB under the brush will be lost as it can't be in the blending or otherwise you get fringing. So as part of the blending operations we have to premultiply the color and then unpremultiply it afterwards, or some equivalent in integer math.%%%

%%%Figured out the right formulas now and fixed 2D image painting. I'll tackle projection painting next.%%%

%%%Figured out the right formulas now and fixed 2D image painting. I'll tackle projection painting next.%%%

%%%Texture paint fixed as well now. Thanks for the report, closing.%%%

%%%Texture paint fixed as well now. Thanks for the report, closing.%%%

Changed status from 'Open' to: 'Resolved'

Changed status from 'Open' to: 'Resolved'
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
7 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#34233
No description provided.