Do you want to work on this issue?
You can request for a bounty in order to promote it!
Highlighted layers can be hard to see #3522
eishiya posted onGitHub
When using the Highlight Current Layer feature, layers that are above the highlighted layers are displayed at a lower opacity. This works well when there are only a few layers above the highlighted layer, but when there are many layers, they stack up and obscure the highlighted layer. For example, the highlighted layer here consists of two light pink flower tiles next to each other, but they're almost impossible to see.
This means that for maps with many layers, I often have to hide the other layers, lower their opacities, or bring my working layer to the top to be able to see what I'm doing, even though the Highlight Current Layer feature is meant to remove the need for that.
I can think of three possible solutions to this:
- Allow the higher layer opacity to be customisable. This would allow users to choose an opacity that works for them. However, since the required opacity depends on how many layers are drawn on top, the user would probably have to tweak this value quite often. I think this is the worst solution.
- Instead of using a fixed opacity value, calculate the opacity based on the number of visible layers above the selected layers, so that the total opacity adds up to some fixed value, or calculate the opacity based on which layer is being drawn, decreasing it as you go (see below). Perhaps this total/target opacity value could be something users can customise. I think this is the simplest solution, its only complication is having to count the number of layers that will need to be rendered, or performing a calculation based on how many faded layers have been drawn so far.
- Render all the higher layers at full opacity to a buffer, and then render that buffer at the desired lower opacity. This way, no matter how many layers there were, they'll always have the same total opacity. This has the side effect of avoiding layers blending with each other, which can be beneficial in reducing visual noise. From what I understand, this would be difficult to implement in Tiled.
I think (2) would be the simplest to implement.
Some tl;dr thoughts on opacity, which may also help with implementing (2):
It seems like currently, Tiled renders every layer with the same opacity, which results in lower layers having lower visibility and higher layers having higher visibility. To blend several layers with equal weight using just alpha blending, the alpha multiplier of each layer 1...n would need to be 1/n
(or, for 0-based indexing, 1/(n+1)
).
Of course, our goal isn't to just blend all the layers equally, but to also render them at a lower opacity, and have the total opacity of all these layers under control no matter how many layers there are. And ideally, these modifications to opacity should also not affect the RGB blending of all these layers too much. The best option would be to render them with multiplier 1/n to a buffer and then render the buffer at the desired opacity, but I suspect that's not possible, so we'll have to get clever with alpha values.
The sum of a/(2^n)
approaches a as n approaches infinity, we can use this to set an upper limit of a on our alpha. We can't just multiply them together, that gets the alpha values too low too quickly. But what if we average these two values?
alpha = ( a/(2^n) + 1/(n+1) )/ 2
The sum of this approaches alpha=1, but it takes much longer to get there compared to alpha = a.
Here's a chart comparing all the methods using a background (=highlighted layer) consisting of a grid of black and white squares above and #808080
mid-grey below, on top of which my test layers are blended. The test layers are pure white and pure black alternating, the bottom-most layer is always white, the top-most is always black. The black and white grid gives an idea of how visible the highlighted layer remains, and the grey field gives an idea of how well the faded layers are averaged together - the closer to #808080
, the truer the average.
Here is the same example from the top of this post, but with the layer opacities manually set to be those produced by
( a/(2^n) + 1/(n+1) )/ 2
, with a=0.4:
The pink flower is a lot more visible! There are 4 layers above the "highlighted" layer in this case.
Here's a fuller scenario, trying to edit the far background layer of a sidescroller level, which contains the lighter-blue hills. The art is low-detail and mostly silhouettes, so this should be a best-case scenario for Highlight Current Layer. However, behind the trees, the background hills are very hard to see using the current blending:
And here it is with the the above method:
I'd say that's an improvement :D
I think that rendering the layers to a buffer and then rendering that at a low opacity would be ideal, but perhaps this sort of formula might be a decent alternative. I stuck with a=0.4 in these examples since that's the current alpha multiplier Tiled uses, but I think a slightly higher multiplier could work better since the total alpha doesn't go up as quickly.