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 2828

Summary: Subtractive Blending
Product: SDL Reporter: BadManiac <martin_maniac>
Component: renderAssignee: Sam Lantinga <slouken>
Status: REOPENED --- QA Contact: Sam Lantinga <slouken>
Severity: enhancement    
Priority: P2 CC: martin_maniac
Version: 2.0.3   
Hardware: x86_64   
OS: Windows 7   

Description BadManiac 2014-12-28 15:53:22 UTC
Would like to have a new blending mode SDL_BLENDMODE_SUB, which performs the operation dstRGB = dstRGB - (srcRGB * srcA). This is currently not available.

When posting on the forums a while back I got good response which tells me there might be more users that could have use for this function: http://forums.libsdl.org/viewtopic.php?t=10592
Comment 1 Sam Lantinga 2017-08-14 12:58:44 UTC
This is implemented for accelerated renderers in this commit:
https://hg.libsdl.org/SDL/rev/180e8906dc3c

I think this is what you want:

        blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA,
                                               SDL_BLENDFACTOR_ONE,
                                               SDL_BLENDOPERATION_SUBTRACT,
                                               SDL_BLENDFACTOR_ZERO,
                                               SDL_BLENDFACTOR_ONE,
                                               SDL_BLENDOPERATION_SUBTRACT)
Comment 2 BadManiac 2017-08-20 09:26:58 UTC
Hi Sam,
Thank you for taking care of my bug report. This is exactly what I was looking for. However a certain feature seems to be missing from the custom blend modes.

When using a custom blend mode, SDL_SetTextureAlphaMod seems to have no effect. I feel this should be taken into consideration. Example code below:

// I set up my subtractive blend mode like so
SDL_BlendMode SubBlendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
SDL_SetTextureBlendMode(tempbuffer, SubBlendMode);

// Then I set an alpha mod for the entire texture, let's say 50%
SDL_SetTextureAlphaMod(tempbuffer, 128);

// And render it
SDL_RenderCopy(main_renderer, tempbuffer, &srcRect, &dstRect);


It doesn't matter what alpha mod I set, it still always subtracts it at 100% intensity. And in this case my source texture doesn't have an alpha channel, but even if it did i feel the alpha mod should be taken into consideration?
The subtract operation should be, in my opinion:
dstRGB = dstRGB - (srcRGB * (srcAlpha * srcAlphaMod))

This way you have more flexibility, you can set the TextureAlphaMod to 255 and use the source texture alpha channel. Another option would be to add another BlendFactor called "SDL_BLENDFACTOR_SRC_ALPHAMOD". Might be a better solution? Either way, there should be a way to use the AlphaMod, right? Thoughts?