Custom blend modes using SkBlender

375 views
Skip to first unread message

Giuseppe Salvo

unread,
Nov 10, 2021, 6:12:56 AM11/10/21
to skia-discuss
Hello,

I'm trying to use an SkBlender to implement a custom blend mode, but I'm not getting the expected results. Are there any examples on how to use the SkBlender? How alpha is managed in blend modes, etc.

Thanks! 

Brian Osman

unread,
Nov 10, 2021, 9:59:27 AM11/10/21
to skia-d...@googlegroups.com
Here's a really quick example that implements "normal" source-over blending using a blender: https://fiddle.skia.org/c/752133b526b98510df1523f114e2d145

The main thing to remember is that the two incoming colors (src and dst) are both already premultiplied by their own alpha values. The way that many people configure GL's blending state (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is only correct if the source color is still unpremultiplied.

Regardless of that, once your blend function returns, that final color is written directly to the surface, with no further adjusting of alpha, etc.

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/309427be-62c6-426e-9e6e-590c25f59420n%40googlegroups.com.
Message has been deleted

Giuseppe Salvo

unread,
Nov 10, 2021, 6:07:11 PM11/10/21
to skia-discuss
Hi Brian,

Thanks for the example! In short, I'm trying to replicate the PlusDarker blend mode present in CoreGraphics. I naively ported the formula straight into the shader, and it works correctly when there is no transparency, but not with transparency.

Here's a fiddle. Any tips on what I may be doing wrong? 

The blend more I'm trying to replicate:

What I'd expect is:
Expected.png

But, in Skia I get:
Skia.png

both red squares have 50% opacity.

Greg Daniel

unread,
Nov 10, 2021, 7:07:17 PM11/10/21
to skia-d...@googlegroups.com
So you may not believe me, but everything is working and what you are getting are the same two images!!!

So when you blend Red with .5 alpha and Solid White using plus-darken, you end up with a pixel that has 50% transparency (alpha = 0.5). So that is then blended with the background of the entire page. The default on fiddle is a black background, so things look darker. In the top right of Fiddle hit the "paint drop" icon to switch from dark mode to light mode. This gives a white background and your draw will look as you expect!

Brian Osman

unread,
Nov 11, 2021, 10:39:52 AM11/11/21
to skia-d...@googlegroups.com
Interesting. Do you have a snippet to show what you're doing in CG? The paint alpha in Skia will be applied to the source color before it reaches the blend mode (so the src color in your case will be the premultiplied result (0.5, 0, 0, 0.5)). I tried some alternate forms where we unpremul() the src color and then apply the alpha after the blend mode, but that seems to be worse. Seeing how you're doing something comparable in CG would let us understand the math a little better.

On Wed, Nov 10, 2021 at 6:07 PM Giuseppe Salvo <giuseppe...@gmail.com> wrote:

Giuseppe Salvo

unread,
Nov 11, 2021, 11:50:53 AM11/11/21
to skia-discuss
sure, in CG I'm just applying the PlusDarker blend mode, nothing else.

Here a snippet:

class CustomView: NSView {

    override func draw(_ dirtyRect: NSRect) {

        let context = NSGraphicsContext.current!.cgContext

        let rect = NSRect(x: 0, y: 0, width: 480, height: 480)

        let image = NSImage(named: "Image");

        image!.draw(in: rect)

        context.setAlpha(0.5)

        context.setBlendMode(CGBlendMode.plusDarker)

        let size = rect.size.height / 2

        let rectOverlay = CGRect(x: 0, y: rect.maxY - size, width: size, height: size)

        NSColor.red.setFill()

        rectOverlay.fill()

    }

}


As you can see, nothing special. This produces the image I posted in the previous message.

Greg Daniel

unread,
Nov 11, 2021, 4:51:36 PM11/11/21
to skia-d...@googlegroups.com
Giuseppe did you see my response earlier? I believe Skia is drawing things right and matches your test image. The issue is that the resulting draw has transparency that is introduced from the plus-darken blend. In Skia fiddle the background is black and in your test it is white. That's why they look different.

On Thu, Nov 11, 2021 at 4:21 PM Giuseppe Salvo <giuseppe...@gmail.com> wrote:
Hi Brian, 

Thanks for the example! In short, I'm trying to implement the PlusDarker blend mode, which is present in CoreGraphics. I naively ported the formula stated on the documentation straight into the shader, and it works correctly when the src color is not transparent, but not when there is transparency. 

Here's a fiddle. Any tips on what I may be doing wrong? 

CoreGraphics doc:

The expected result should be:
CleanShot 2021-11-10 at 23.53.24@2x.png

But, using Skia I get:
CleanShot 2021-11-10 at 23.54.49@2x.png

In both examples, the red rect had 50% opacity.

On Wednesday, 10 November 2021 at 15:59:27 UTC+1 brian...@google.com wrote:

Brian Osman

unread,
Nov 11, 2021, 5:11:51 PM11/11/21
to skia-d...@googlegroups.com
If you haven't seen it (many messages to this group get flagged as spam incorrectly), Greg Daniel replied earlier with an explanation of what's happening:

So you may not believe me, but everything is working and what you are getting are the same two images!!!
So when you blend Red with .5 alpha and Solid White using plus-darken, you end up with a pixel that has 50% transparency (alpha = 0.5). So that is then blended with the background of the entire page. The default on fiddle is a black background, so things look darker. In the top right of Fiddle hit the "paint drop" icon to switch from dark mode to light mode. This gives a white background and your draw will look as you expect!

Giuseppe Salvo

unread,
Nov 12, 2021, 9:44:21 AM11/12/21
to skia-discuss
oh, I missed Greg Daniel's message! Yes, that makes sense, with the white background the image is definitely more similar!
I think there is still some work to do in the alpha compositing, because it seems that CG is not just applying the dark plus formula directly. But anyway, thanks a lot for the help :)

Reply all
Reply to author
Forward
0 new messages