Lights and shadows with a single blending mode: Multiply & Double

Artists often use blending modes such as Multiply for shadows and a different one, like Color Dodge for lights, but it’s possible to achieve similar results with just one new blending mode: Multiply & Double. Allow me to proselytize. :smiley_cat:

:diamond_shape_with_a_dot_inside:Two blending modes is hard:

Using different blending modes for light and shadow gets complicated in the transition areas, where both modes can overlap, or worse, leave the object unaffected by either light or darkness.

:diamond_shape_with_a_dot_inside:Hard Light is good but not enough:

The blending mode Hard Light behaves kind of like Multiply when a top channel has under 50% brightness, and kind of like Screen otherwise.
This allows you to have lights and shadows in just one clipped layer!

Hard light

However Hard Light has its own problems. It behaves specially weird when a gradient is blended to a dark color (notice the nasty resulting gradient):

The reason for this becomes apparent when one looks at the graph of the Hard light equation:

(you can play with the sliders here). The sharp change in slope (and therefore channel intensities) is caused by the dual nature of Hard Light, and it’s really hard to avoid when lighting dark characters or objects.

:diamond_shape_with_a_dot_inside:Multiply is too dark:

A basic rendering program calculates the resulting color of an object by multiplying its base color with that of the light it’s recieving.

Here the green light’s color is multiplied by the yellow ball’s color, resulting in that yellowish green ball. Multiplication has the nice feature that the resulting color seems like a mix of the two, but darker if they are too pure and different, such as red and blue:
:red_circle:(1,0,0)*:large_blue_circle:(0,0,1) = :black_circle:(0,0,0) results in black. This is because a perfectly blue object doesn’t reflect red light.
Of course in real life, lights and objects are very impure and rarely very saturated.

Knowing this, one might think that Multiply is the perfect blending mode to paint like a rendering software! however our channels only go from 0 to 1, so their multiplication always results in smaller numbers, unlike rendering software that can have lights of any intensity. :bulb:

:diamond_shape_with_a_dot_inside:Doubling the intensity of multiply:

Taking this into account, it’s possible to create a simple blending mode that doubles the intensity of the light to compensate for its darkness, so that instead of the normal Multiply
(r1, g1, b1)*(r2, g2, b2)
we have
2*(r1, g1, b1)*(r2, g2, b2)
Here we can see how it looks when two images are combined this way.

But since no one is really interested in blending a squirrel with balloons, here’s a more useful example of the power of this blending mode:

C, D and E show B and A being combined with different blending modes. We can see the oversaturated transitions of Hard Light, the darkness of Multiply and the perfection of Multiply & Double! it even has a lovely cinematic feel.
In this blending mode, 50% grey is the neutral color. anything above it acts as a brightener and everything below it as a darkener (very intuitive)!

:diamond_shape_with_a_dot_inside:There’s no nice way to do it currently:

It’s possible to achieve this effect by using Multiply mode and then doubling the result with this filter mask

but doing so introduces an unholy amount of banding in some areas. It’s possible to avoid the banding by using a higher color depth (16 bits), but inexperienced users or people with slow computers might find it difficult.
I believe that it being done in a single step as a proper blending mode would reduce the rounding errors and produce less banding.
In fact, Hard Light behaves as Multiply & Double for its channels under 50%, so this is testable:


the banding is much worse when done manually!

:diamond_shape_with_a_dot_inside:The future is now:

To demonstrate the greatness of this blending mode, here’s a comparison between a sphere lit in shadingreference.com and one lit in krita using Multiply & Double with the same colors.


Uncanny!

As far as I’ve searched, I haven’t found this blending mode on any painting software :interrobang:, so having it would defy the status quo of digital art and usher in a new era for humanity!

:diamond_shape_with_a_dot_inside:Conclusion/TLDR:

A new blending mode that doubles the result of Multiply (so 2ab instead of ab) would be great for doing realistic lighting/shading. Some of the existing blending modes are good but not enough.
You can play around with it by changing the sliders here!

I leave you with some examples of my art that were lit by faking Multiply & Double:

Feels like playing with real light|
Bonus use as a mood adjuster

14 Likes

How do you feel about using overlay instead?

A overlayed on B is the same as B hardlight on A (they are commuted blending modes) so the same problems displayed in the Hardlight examples appear.
Overlay specifically has trouble darkening bright objects

1 Like

@Reptorian may be interested in it. As far as I know, he created a lot of blending modes for krita.

Adding through “addition” may also be a feasible solution.

1 Like

Thanks! I did try doubling it through addition but doing it in two steps resulted in similar banding issues to the ones showcased in this post. Oh! I hope Reptorian notices it then :smiley_cat:

This looks very interesting.
But how you think how to solve when 2xaxb is above 1? Because clipping will cause a heavy loss of information.

Honestly I was looking at the graphs and thinking if not a gamma like curve would not solve this better instead of a linear progression until a clip at 0.5 forward.
Something like a ** b. 0 ** 0 forced to be zero, 0.5 ** 0.5 = 0.7 and 1 ** 1 = 1.

1 Like

Ooh hold on, I’ll graph some possibilities up when I get home

That’s a really nicely done pitch! :slight_smile::+1:

Have you done any tests with Hard Overlay? I gravitated towards using that a few years ago because subjectively it seemed to offer similar results to Multiply and Colour Dodge, and I could still use it for value adjustments like I was doing with the basic overlay.

Alright I’m home.
I played a bit with a^b and the likes but I didn’t find anything good sadly
Yeah I guess clipping is a donwside of this blending mode although it only happens in this region of a and b combinations
image
which is personally far from a deal breaker since it’s wise to avoid such extreme colors anyway and all 3 channels need to be clipped for it to be noticeable and then it only seems like mild overexposure :0 but still could be improved upon.
So I made this graph: https://www.desmos.com/calculator/ry9yuoopa3


that “cushions” the approach to white. This is similar to what Hard Light does with its channels over 50%!
I think my favorite results are around c=0.9, although I can’t test it on krita since I’m not a krita hacker :crying_cat_face:
c=2 is mathematically nice since the slope change always happens at x=0.5

If this blending mode is ever added I hope it has a more descriptive name than Cushioned Multiply & Double haha

Thank you ^^
I’ve actually tested every blending mode, both ways :sweat_smile:
Hard Overlay is nice and I think it was in my top 4 finalists, but it still has these harsh transitions when a gradient is on top of a dark surface
image

3 Likes

cushioned multiply seems more sober and normal seems more cartoony and slightly more interesting strangely enough.
I should make a test though just to clean my head about the exponential.

1 Like

Good luck!
if you or anyone else experimenting wants some pre-made drawings with the layers for colors and lights, here are some objects i used for testing
Krita file: https://drive.google.com/file/d/1QEoN_1wXqINiYXVAIZdEzDnFctWCqqcL/view?usp=sharing
image

2 Likes

wrote a small script to run the exponential thing. this creates a new QImage pixel by pixel considering 2 images in file and assumes both images have the same dimensions as it constructs the new image.

Sources:
image_a
image_b

Test:
image_cseems barely better than multiply.

original:

with your square your mix looks like blend=“Penumbra C”.

1 Like

What an interesting thread lease continue the investigation, maybe we can create something epic :wink:

1 Like

I did, however, I can’t compile Krita and there is still that selection tool that I still can’t figure out. So, I can’t try this.

From looking at your light images and the formula you propose, I think that you are just making the lights too dark. In fact the formula 2 * baseLayer * lightsLayer can be rewritten as baseLayer * (2 * lightsLayer) from which one can see that the lights are scaled up by 2.

The main issue I see is that of clipping in 8 bits as EyeOdin said. From what I said above, one could think that the solution is to just scale the lights layer by 2 and then mix it with the base layer using multiply, and that would be the same as using the proposed blend mode. But it isn’t. Imagine we have a base color with value equal to 0.5 and a light color with value equal to 0.75. If we use the approach where we first scale the lights then the steps would be:

  • scale the light by 2, giving 1.5.
  • we need to clamp the light to (0, 1) here because the values are stored in a layer, in 8 bits that’s the range.
  • multiply the light by the base layer(1 * 0.5), giving a value of 0.5 for the mix.
  • clamp the mix value again to (0, 1), giving again 0.5.

If we use the blend mode we can pack all the computations together:

  • scale the light by 2, giving 1.5.
  • [No need to clamp here].
  • multiply the light by the base, giving 0.75 for the mix.
  • clamp the mix value to (0, 1), giving again 0.75.

So yeah, using the blend mode would retain more information until the multiply is performed.

I want to note that in this image:

You have that pink color for the light, but you also have an intensity parameter. I guess that it acts as a multiplier. If you set that to 1, then it looks darker. A similar effect can be achieved using 16 or 32 bit float in Krita:

In the video I create a black disk layer over the base color disk and set its mode to multiply and lock the alpha channel. Then I convert the image to 16 bits float. Then I select that pink color and edit it, multiplying it’s components by 8. So the light has that color but lighter. Then I paint with that color. 16/32 bits are HDR, so colors can go beyond 1.0, like in the 3D program.

But ok, if one wants to fake all of that in 8 bits (I’m not using fake as pejorative), then a blend mode like this could help. the main issue I see with this is that the 2 factor is somewhat arbitrary. One could scale the lights by 3, 4, or other value. I think that this looking good would depend on how one makes the lights layer. Maybe someone makes it lighter or darker than you so maybe the mode would work best for them if that multiplier was different.

5 Likes

Thanks Ramon! I hope so

Aw, I see, well good luck with your project. Big fan of the freeze reflect modes btw

Thanks for the detailed reply,
I have experimented different ways of achieving the 2ab effect in 8-bits, such as (2a)b, a(2b), ab+ab, (a+a)b and so on. The best results for faking it are 2(ab) and ab+ab, but they all have the banding issues of doing it in separate steps.

Amazing test in the video, I had no idea that float depths could go so high, it does seem like it replicates the shadingreference result very accurately, because as you say the intensity acts as a multiplier.

I guess the “2” in “2ab” could be any other number but it being 2 makes 50% grey act neutrally, the same way most blending modes meant to increase contrast/simulate lighting and shading do, it even behaves exactly like Hard Light for channels under 50%!

1 Like