Fix UE's alpha handling

This is a bit ridiculous:

Source is a layered photoshop file with normal layer transparency. I don’t know if this affects other formats. Here’s how it looks in photoshop:

Here’s the same texture in UE’s texture browser:

Same texture with alpha turned off:

The pixels in a transparent PSD are straight alpha - that is the edges of those plants in my particular document are stored as a 32 bit value: three 8 bit colour values and an 8 bit alpha value: RGBA(0, 0, 0, 0.5). The pixel is in no way pre-multiplied. But on import UE is blending the pixel with white by the alpha value, resulting in edge pixels that are RGBA(0.5, 0.5, 0.5, 0.5).

It should be using the exact pixel data as supplied by the layer stack and pre-multiplying that against the underlying visible layers. If there’s no more visible layers then you’re done. Don’t multiply it by white to finish it off, just use the RGB value you already have.

  1. It’s not reasonable to fix this by creating the right background colours, merging the layers and transferring their transparency to an alpha channel. That is a MASSIVE amount of work, especially on images that aren’t a single flat colour.
  2. It’s very desirable to keep PSD files editable and layered in their natural state. This is a quality of life thing.
  3. It’s desirable to import the original PSD and not a modified copy or a PNG.

Please fix the PSD importer, it shouldn’t have been this way for so long. In this case it’s going to directly cause me hundreds of hours of work to get around it. Seriously, this is worth a hotfix.

I’m still using 4.19 but presumably if it wasn’t fixed by now then it isn’t fixed in 4.20.

Have you tried used a DitherTemporalAA node in your material? First of all, set the material’s shading model to subsurface. Then, add the DitherTemporalAA node. Plug the alpha map (or the base color texture’s alpha pin) in AlphaTreshold, then create a constant node (1+ left click) and set it’s value to 1, and plug it in random. Hold 3 + left click, set the color to something similar to your material’s main color but darker. Plug it in the subsurface slot. I do this with all my masked materials, makes a huge difference.

Nice idea! The materials aren’t masked though, they’re regular translucency. It won’t really get around the issue of any partially-opaque parts being totally the wrong colour either.

as you’ve already noticed, the texture shouldn’t be white when the alpha is turned off which is the direct symptom of the problem.
you say this only happens upon import but the issue is not from unreal but from the PNG format. the PNG format discards the colors of the pixels when they are transparent, which is why they become white.
try using a file format with proper alpha channel handling (i.e. TGA) and you’ll stop having this problem entirely

Worth reading the post before commenting as we’re not discussing PNG format, but you’re not right about that either. If we were talking about PNG it’s also not pre-multiplied, only the completely transparent pixels are white. This has no relevance at all to partially transparent pixels.

I’ve made a simple PSD importer before, so I know what’s available in the file. UE is doing it wrong. This is a classic problem.

PNG supports saving color in transparency. Check your PS settings at save/export. If there’s no such, then try what said. (Or just switch to GIMP, he-he-he.)
You may also try to mess with textures’ compression settings.

Sorry guys but can everyone please stop “helping”? You haven’t read the post and this is an actual identified problem in UE that Epic needs to fix.

Edit: To clarify this issue has been buried before. It’s a fundamental problem with the PSD importer in UE. Needs to be fixed.

not sure what kind of response you want if our “help” is of no use to you. Epic simply will not come to the forum to acknowledge a problem and deliver a fix, you should know that by know.

so the PSD importer might be broken in UE. simply use TGA and move on, and/or write a PSD-TGA script if you want quality of life

Epic won’t fix this from here. Submit a bug report if you think the PSD importer is broken (or better yet, a PR and a bug report).

I’ve had plenty of issues in the past with other engines with the same issue. Most of the time the problem is the file format and not the importer. AFAIK Epic use more compressed image formats internally (otherwise your repository will grow exponentially will all the PSD source data), so it’s unlikely they’re going to stumble on this.

Guys, let’s get over it. It’s broken, it will be fixed, and knowledge of issue in the userbase will cause it to be fixed quicker. Apologists need not apply. I’ll never understand the logic of commenting when you absolutely know you can’t help. While I do appreciate the effort, subverting every fix with a half-baked solution doesn’t help us as a group.

Dropping by to say that OP has a valid point here, but pre-multiplying against previous layers in a stack is definitely not desirable default importer behavior and should not be hardcoded, but an option to do so on import would be good. For now, gotta rely on automation or manual labor to bring in proper pixel colors to the layers.

An option would suit me! Can you explain what you mean by not pre-multiplying layers against each other though? The only time I can see that being relevant would be if you’re exploding a PSD file into multiple textures based on group or layer, in which case yes, you wouldn’t pre-multiply against layers that will not appear in that specific individual texture result. If we had this feature it’d save me even more work.

For the current use case in addition to individual layers PSD files also provide a flattened version of all of the visible images with the correct blends calculated, so it’s almost no work to open a PSD and write the colour and alpha to a texture. The important thing is to treat the data as pre-multiplied and not do anything to it. The issue with the current importer is that it does pre-multiplication against white. All that has to be changed to fix this is to use the data without messing with it.

The only downside to not preserving pre-multiplied data is if you choose to use your image without applying the alpha channel. Then it’ll have hard, aliased edges where before there were none. But you’d get a pretty hideous image in that case due to lack of control over the eventual background colour. In that case the material using the texture should use its alpha to blend between your image and the desired background colour. This is still a better outcome than the importer deciding that you wanted white as your new pre-multiplied background colour.

Anyway, now that it looks like we have a decent feature request I’ll put in a bug report. Sorry I was grumpy everyone.

Exactly that. And additionally, when alpha channel information has no correlation to color channel in respect to how they are going to be utilized.
But I can clearly see speedups in PSD workflow, if your suggestion(namely, grabbing color data from underlying layer, where current has none) gets implemented as a toggle in texture import settings.

Link to a pretty good blog post about the nature of the problem for other people reading thread.

Interestingly enough TGA has exactly the same problem - it’s pre-multiplied against white on import. I don’t know how people have been using this like this for so long, when you consider the process to get around it:

  1. Select all visible layers, add as alpha channel
  2. Copy all layers combined, paste in the back, blur, then duplicate and merge the layer several times to get colour bleed to force opaque pixels
  3. Save (as anything)

That’s a lot of work.

This is the poster-child for not pre-multiplying the colour data, yep! I’d put it in the actual texture settings though, so it can be changed after import.

Excellent link too. It’s a shame that this problem isn’t easily solvable in Photoshop either.

This is not exactly a format specific thing. It is related to texture filtering. For many importers/exporters out there( not only UE or shop specific) the default behavior is use white color on a color channel, where no color data exists. If you sample your texture with nearest filter, you will never run into problems, because there will be always a match. When you introduce bilinear interpolation, pixel with color(0,1,0,1) and pixel with color(1,1,1,0) can get averaged to (0.5,1,0.5,0.5). The issue also propagates to mip chain generation. A common approach is to dilate the color channels, so that color data extends past alpha borders spatially. Applicable to photoshop, you should be able to automate the dilation process with an action/macro. If you are seeing checkerboarded(transparent) pixels in photoshop, those will end up white whereas you need those to be closest match possible to the content, you are trying to cut out. There is no pre-multiplication involved.

Oh yeah, that makes sense. I wondered about that earlier. When mipmapping it should seek out the nearest valid pixel with any amount of opacity above zero and sample that. In fact, it could just average out the other three pixels being considered during reduction, or however many are valid.

I get that, but I’m saying posting this here won’t get Epic’s attention - make an actual bug report if you haven’t already to get Epic eyes on it.

There was value in talking about it. There’s just no use in finding a work-around when what we want is a comprehensive feature request to put to Epic.

Bilinear filtering or mipmapping cannot assume that alpha is treated as opacity and zero alpha pixels would be invalid. In our game we store albedo to rgb and roughness to alpha. You could code custom mipmapping filter that would do that but bilinear filtering is done by gpu hardware and cannot be modified.

Yeah after thinking about it for a few days doing it during mipmap generation would be a strange place to fix it.

I’ve lost the issue tracker link but it turns out Epic became aware of it in April finally and are going to do exactly what we’re discussing, I can only assume that they’ll handle bleed as an import step or something. Obviously it’d be an option in the texture.

Are mipmaps really generated on the GPU? That doesn’t seem right but I’ve never gone beyond a high level with it.