mapeditor / tiled

Flexible level editor
https://www.mapeditor.org/
Other
11.24k stars 1.76k forks source link

Linear sRGB blending for layers #3385

Open Froyok opened 2 years ago

Froyok commented 2 years ago

Current issue: It seems that Tiled is doing color blending in sRGB gamma space and while this might be the expected behavior for a lot of users, it can cause quality issues (wrong/undesired color behaviors) and problems when trying to match the render of a game engine.

The issue mainly arise when blending layers together in the editor's viewport, when having semi-transparent pixels.

Describe the solution you'd like: Having an option to choose how to blend colors, via a simple boolean setting in the preferences to choose between Linear sRGB and sRGB, would be just enough. :smile:

There are plenty of resource on while blending colors this is better (for example this and this or this as well).

I would understand if this option would be off by default (and even limited to hardware acceleration mode) given that not all applications behave like this by default and to not break existing users workflows. For example Photoshop blends color in sRGB by default too but you can change that in the preferences.

Game engines like Unity or Unreal Engine, but also mine, on the other hand work in Linear sRGB color space and therefore the look in-editor cannot be 100% matched with the engine.

Example: The best and most obvious example is when trying to blend a pure red and green color together with a gradient as the mask. In sRGB this produce a darkening in the middle of the transition while in Linear sRGB we get the orange/yellow color.

Here is the gradient example with on the left my game engine and on the right Tiled's viewport: Y0615_124825

Describe alternatives you've considered No alternative possible. This is a color management issue and cannot really be solved by a pipeline/workflow change on my side. Linear color blending is needed for other steps in my game engine (like bloom) and therefore sRGB blending is not possible.

Misc: I have looked around but it seems nobody requested this before, either here or on the forums. Also if anybody has technical questions, feel free to ask.

bjorn commented 2 years ago

Boy, it must be my age but the sRGB blend looks like the more natural one to me, but I get what these people are coming from... something to do with how colors behave in real life. ;-)

I had a quick look at QPainter, which is what Tiled currently uses to paint the map view, and unfortunately I could not find any apparent option for changing the color space used for blending. However, there must be some way since apparently Krita does have this option, as per your first reference, though that does not mean it could be easily translated to Tiled.

If it will not be realistically possible to add this to the software paint engine, another option would be to investigate whether it would be possible to do this with a new Qt Quick scene-graph based renderer that we'd eventually like to develop.

Froyok commented 2 years ago

Boy, it must be my age but the sRGB blend looks like the more natural one to me, but I get what these people are coming from... something to do with how colors behave in real life. ;-)

Hehe no worries, it depends a lot on context anyway (like a lot of stuff when speaking about colors). :smile:

I had a quick look at QPainter, which is what Tiled currently uses to paint the map view

Qt seems to have a notion of color spaces at least, but not sure how far this can used: https://doc.qt.io/qt-6/qcolorspace.html

Anyway, no problem I will try to manage on my side. Fortunately I don't a lot of semi-transparent pixels, but I figured it wouldn't hurt to ask.

bjorn commented 2 years ago

Qt seems to have a notion of color spaces at least, but not sure how far this can used: https://doc.qt.io/qt-6/qcolorspace.html

Hmm, yes it does. Might be worth trying to modify the color space of the QSurfaceFormat used in hardware accelerated rendering mode in MapView::setUseOpenGL. I'm also wondering whether we'll need to actually convert the images. I still doubt we can get it to do the right thing when software rendering.

Froyok commented 2 years ago

By the way, I wanted to give another example (and the reason why I opened this issue in the first place).

On the following image, you can see at the bottom half the original background color. The top half is black image blended over it at 50%. Top left corner is using sRGB, top right is using Linear sRGB: Y0615_143036 Perceptually the top left is the expected result in this scenario, but that's not really my point here. The things is that the difference is quite big and I cannot match the result in my game engine. My context is that I'm drawing tiles as shadow on my map, but since I use Linear sRGB blending in my game I get very different results to the point where in Tiled things are too dark.

I think my workaround will be to adjust the layer opacity to compensate for the time being for this particular case.