We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4903 - Lack of color multiply with alpha (SDL_BLENDMODE_MOD + SDL_BLENDMODE_BLEND) blending mode for all renderers
Summary: Lack of color multiply with alpha (SDL_BLENDMODE_MOD + SDL_BLENDMODE_BLEND) b...
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: HG 2.1
Hardware: All All
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-12-17 19:20 UTC by Konrad
Modified: 2020-01-16 17:24 UTC (History)
0 users

See Also:


Attachments
Patch with SDL_BLENDMODE_MUL (602.86 KB, patch)
2019-12-17 19:20 UTC, Konrad
Details | Diff
Patch with SDL_BLENDMODE_MUL (151.58 KB, patch)
2019-12-17 19:55 UTC, Ozkan Sezer
Details | Diff
Test case (239.89 KB, application/x-zip-compressed)
2020-01-16 11:58 UTC, Konrad
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Konrad 2019-12-17 19:20:12 UTC
Created attachment 4111 [details]
Patch with SDL_BLENDMODE_MUL

Hello

This kind of blending is rather quite useful and in my opinion should be available for all renderers. I do need it myself, but since I didn't want to use a custom blending mode which is supported only by certain renderers (e.g. not in software which is quite important for me) I did write implementation of SDL_BLENDMODE_MUL for all renderers altogether.

SDL_BLENDMODE_MUL implements following equation:

dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
dstA = (srcA * dstA) + (dstA * (1-srcA))

Background:

https://i.imgur.com/UsYhydP.png

Blended texture:

https://i.imgur.com/0juXQcV.png

Result for SDL_BLENDMODE_MOD:

https://i.imgur.com/wgNSgUl.png

Result for SDL_BLENDMODE_MUL:

https://i.imgur.com/Veokzim.png

I think I did cover all possibilities within included patch, but I didn't write any tests for SDL_BLENDMODE_MUL, so it would be lovely if someone could do it.
Comment 1 Ozkan Sezer 2019-12-17 19:55:46 UTC
Created attachment 4112 [details]
Patch with SDL_BLENDMODE_MUL

The original patch was broken (changed line ending modes of
SDL_blit_auto.c and SDL_blit_auto.h, ending up being 600k.)
The attached version is the same but keeps the original line
endings.
Comment 2 Konrad 2019-12-17 21:31:15 UTC
Thank you Ozkan. I think that's because I did use perl on Windows resulting in different line ending mode. I do apologize as I didn't check it.
Comment 3 Konrad 2020-01-14 18:35:20 UTC
Hello

Is this new blending mode likely or unlikely to be implemented? I would very much appreciate the answer because if not I will have to give up on this kind of blending for the software renderer even despite the fact that I did create this patch. However, I do not wish to have a custom branch of SDL2 because I prefer to keep track with the official one and report bugs or provide patches directly.

It would be lovely if Ryan could take a look as well and state his opinion on this.
Comment 4 Konrad 2020-01-14 18:54:29 UTC
Please note this kind of blending can be done via a trick which I'm afraid adds too much overhead, at least for me:

1. Create a render target with the same size as source texture.
2. Clear it with alpha (RGBA -> 0x00000000).
3. Set color modulation to what we want (e.g. red) for source texture.
4. Set composition mode of SDL_BLENDMODE_BLEND for source texture.
5. Draw texture into the render target.
6. Set renderer target to default.
7. Set modulation color of our render target to white (RGBA -> 0xFFFFFFFF).
8. Set composition mode of SDL_BLENDMODE_MOD for our render target.
9. Draw our render target into the default target.

I do use all default blending modes available within SDL2 (including SDL_BLENDMODE_MOD for light effects in a game). The only one I'm missing is multiplication with an inversed alpha (SDL_BLENDMODE_MUL) which is used to colorize parts of a character depending on players settings.
Comment 5 Konrad 2020-01-15 19:00:28 UTC
On side note, a friend of mine suggested me to try out Blend2D which is a 2D vector graphics engine purely done in software with a JIT pipeline (it uses asmjit). Its context would still have to be attached to SDL2 surface to update window though. Interestingly enough, a few days ago they did add a modulate composition operator (FYI, I didn't suggest it there since I just found out about this engine):

https://github.com/blend2d/blend2d/commit/df6288809fac2929c0ea9b2b34d538b16f304bbf

They already had BL_COMP_OP_MULTIPLY which is actually what my patch here does and the naming is for those composition operations is pretty much the same as in our case.
Comment 6 Sam Lantinga 2020-01-16 07:35:59 UTC
Do you have test code that renders your results above? When I take two textures and use SDL_BLENDMODE_MOD with the two textures, I get your MUL result, for all renderers.
Comment 7 Konrad 2020-01-16 11:58:58 UTC
Created attachment 4167 [details]
Test case

Hey Sam

Sure, but keep in mind you need alpha channel for MUL to look different than MOD. Alpha channel is used to determine how much of the source color (intensity) is blended into the destination depending on source alpha.

Check the attachment. I did put a sample code there with some bitmaps (one of them has alpha on unused bits, but SDL2 loads it just fine). This example shows the following window:

https://i.imgur.com/pN9RQ4o.png

Left - SDL_BLENDMODE_BLEND
Center - SDL_BLENDMODE_MOD
Right - SDL_BLENDMODE_MUL

Notice that MOD does not take source alpha to calculate intensity of blending (because all it does is DstAlpha = DstAlpha).

You can use "m" key on your keyboard to enable color modulation as well. That is to see the difference after modulating the source texture with a red color:

https://i.imgur.com/IzYuNRa.png
Comment 8 Sam Lantinga 2020-01-16 16:54:08 UTC
Thanks for the test case!

This patch is now in for 2.0.12:
https://hg.libsdl.org/SDL/rev/2d5b5a5ccbfb
Comment 9 Sam Lantinga 2020-01-16 16:54:29 UTC
By the way, nice work with the implementation!
Comment 10 Konrad 2020-01-16 17:24:22 UTC
I'm glad to hear that!

That being said, I believe software renderer in general is quite useful. At first I had some issues with it leading to 9-10 fps with non-optimal pixel format, but after some tweaks with texture format and certain optimizations for it I managed to get about 80 fps on 3840x1600 resolution. This is more than playable considering the fact that the game does usually around 5000 drawcalls and sometimes even more within one frame (calls to SDL_RenderCopy and SDL_RenderFillRect).