Skip to content

Commit

Permalink
Fixed bug 4903 - Lack of color multiply with alpha (SDL_BLENDMODE_MOD…
Browse files Browse the repository at this point in the history
… + SDL_BLENDMODE_BLEND) blending mode for all renderers

Konrad

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.
  • Loading branch information
slouken committed Jan 16, 2020
1 parent 669729a commit 981e0d3
Show file tree
Hide file tree
Showing 19 changed files with 819 additions and 159 deletions.
3 changes: 3 additions & 0 deletions include/SDL_blendmode.h
Expand Up @@ -50,6 +50,9 @@ typedef enum
SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate
dstRGB = srcRGB * dstRGB
dstA = dstA */
SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply
dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
dstA = (srcA * dstA) + (dstA * (1-srcA)) */
SDL_BLENDMODE_INVALID = 0x7FFFFFFF

/* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
Expand Down
11 changes: 11 additions & 0 deletions src/render/SDL_render.c
Expand Up @@ -75,6 +75,10 @@
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)

#define SDL_BLENDMODE_MUL_FULL \
SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_DST_COLOR, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
SDL_BLENDFACTOR_DST_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)

#if !SDL_RENDER_DISABLED
static const SDL_RenderDriver *render_drivers[] = {
#if SDL_VIDEO_RENDER_D3D
Expand Down Expand Up @@ -970,6 +974,7 @@ IsSupportedBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
case SDL_BLENDMODE_BLEND:
case SDL_BLENDMODE_ADD:
case SDL_BLENDMODE_MOD:
case SDL_BLENDMODE_MUL:
return SDL_TRUE;

default:
Expand Down Expand Up @@ -3288,6 +3293,9 @@ SDL_GetShortBlendMode(SDL_BlendMode blendMode)
if (blendMode == SDL_BLENDMODE_MOD_FULL) {
return SDL_BLENDMODE_MOD;
}
if (blendMode == SDL_BLENDMODE_MUL_FULL) {
return SDL_BLENDMODE_MUL;
}
return blendMode;
}

Expand All @@ -3306,6 +3314,9 @@ SDL_GetLongBlendMode(SDL_BlendMode blendMode)
if (blendMode == SDL_BLENDMODE_MOD) {
return SDL_BLENDMODE_MOD_FULL;
}
if (blendMode == SDL_BLENDMODE_MUL) {
return SDL_BLENDMODE_MUL_FULL;
}
return blendMode;
}

Expand Down
3 changes: 2 additions & 1 deletion src/render/direct3d11/SDL_render_d3d11.c
Expand Up @@ -636,7 +636,8 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
/* Create blending states: */
if (!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_BLEND) ||
!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_ADD) ||
!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD)) {
!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MOD) ||
!D3D11_CreateBlendState(renderer, SDL_BLENDMODE_MUL)) {
/* D3D11_CreateBlendMode will set the SDL error, if it fails */
goto done;
}
Expand Down
1 change: 1 addition & 0 deletions src/render/metal/SDL_render_metal.m
Expand Up @@ -357,6 +357,7 @@ - (void)dealloc
MakePipelineState(data, cache, @" (blend=blend)", SDL_BLENDMODE_BLEND);
MakePipelineState(data, cache, @" (blend=add)", SDL_BLENDMODE_ADD);
MakePipelineState(data, cache, @" (blend=mod)", SDL_BLENDMODE_MOD);
MakePipelineState(data, cache, @" (blend=mul)", SDL_BLENDMODE_MUL);
}

static void
Expand Down
7 changes: 6 additions & 1 deletion src/render/psp/SDL_render_psp.c
Expand Up @@ -676,7 +676,12 @@ PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
case SDL_BLENDMODE_MOD:
sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
sceGuEnable(GU_BLEND);
sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
sceGuBlendFunc(GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
break;
case SDL_BLENDMODE_MUL:
sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_DST_COLOR, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
break;
}
data->currentBlendMode = blendMode;
Expand Down
21 changes: 21 additions & 0 deletions src/render/software/SDL_blendfillrect.c
Expand Up @@ -42,6 +42,9 @@ SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB555);
break;
default:
FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
break;
Expand All @@ -65,6 +68,9 @@ SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB565);
break;
default:
FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
break;
Expand All @@ -88,6 +94,9 @@ SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB888);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint32, DRAW_SETPIXEL_MUL_RGB888);
break;
default:
FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
break;
Expand All @@ -111,6 +120,9 @@ SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint32, DRAW_SETPIXEL_MUL_ARGB8888);
break;
default:
FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
break;
Expand All @@ -137,6 +149,9 @@ SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint16, DRAW_SETPIXEL_MUL_RGB);
break;
default:
FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
break;
Expand All @@ -153,6 +168,9 @@ SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint32, DRAW_SETPIXEL_MUL_RGB);
break;
default:
FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
break;
Expand Down Expand Up @@ -182,6 +200,9 @@ SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
case SDL_BLENDMODE_MOD:
FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA);
break;
case SDL_BLENDMODE_MUL:
FILLRECT(Uint32, DRAW_SETPIXEL_MUL_RGBA);
break;
default:
FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
break;
Expand Down

0 comments on commit 981e0d3

Please sign in to comment.