mapeditor / tiled

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

Like Tint Color, add a Color Offset or Fog Color to a layer #2920

Open Wiering opened 3 years ago

Wiering commented 3 years ago

I like the ability to tint a layer with Tint Color, however this can only make colors darker. So I would like to propose a way to add color to layers, which could be done in two ways: either by using a Color Offset, which is added to the color, or by introducing a Fog Color.

Color Offset

This is an RGB value that is added to each pixel after the Tint has been applied.

ActionScript has something similar: ColorTransform, which consists of a MultiplyColor (like Tint) and an AddColor (Offset).

Every pixel is calculated by: Pixel.rgb * Tint.rgb + Offset.rgb

This can be especially useful for background layers to give more depth, like in this example:

Back layer: Tint = 64, 64, 64, Offset = 75, 102, 187 Mid layer: Tint = 128, 128, 128, Offset = 50, 75, 125 Front layer: normal

image

That would also make it possible to remove detail from background layers by bringing them down to a single color by setting the Tint to 0, 0, 0 and then setting the Offset to a certain color:

image

The ColorTransform is actually much more flexible because it also allows negative numbers and numbers above 255, but just having an Color Offset would be a big help.

Fog Color

Instead, each layer could have a Fog Color. This would use Alpha as the intensity (0 = no fog, 255 = filled with fog color).

Every pixel is calculated by:
(Pixel.rgb Tint.rgb) (1 - Fog.a) + Fog.rgb * Fog.a

For the first example that would be: Back layer: Fog Color = 100, 150, 250, alpha = 192 Mid layer: Fog Color = 100, 150, 250, alpha = 128

In the second example, alpha would be 255

I don't know which option would be better. The Fog Color would probably be easier to use because you'd often set this to be the same as the background color and it would be easier to experiment with different intensities. But the Color Offset would be easier to implement. I don't know if either are supported by game engines, but people can probably easily create a shader to use them.

bjorn commented 3 years ago

It's a nice suggestion! And indeed I'm also wondering what would be preferable here, since I like the simplicity of the additive color but also the intuitiveness of the "fog color".

Currently Tiled uses a software renderer so this functionality is not easily added by some lines in a shader. The tint color is implemented as follows:

https://github.com/bjorn/tiled/blob/546c59fd404b49eae911a84ddb046669f87b9d99/src/libtiled/maprenderer.cpp#L51-L78

This approach has quite some memory and CPU overhead, though this is generally alright for the editor since it tries hard to repaint only changed or newly exposed areas of the map.

An additive color could probably be implemented by adding the following lines after multiplying with the tint color:

painter.setCompositionMode(QPainter::CompositionMode_Plus);
painter.fillRect(resultImage.rect(), additiveColor);

Whereas a fog color would use the default composition mode SourceOver:

painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.fillRect(resultImage.rect(), fogColor);

Of course the conditions in the function will have to be adjusted to such a new color as well. The majority of the work however would be in adding this property to the Layer class like the tint color, to load and save it in the various formats and to enable changing it in the UI.

@Wiering Are you personally in need of this feature?