What’s the most efficient way to turn a multicolor surface or texture into a black and white one? Basically any non black or transparent pixel should be set to white.
Basically any non black or transparent pixel should be set to white.
To be clear, is this really what you wanted? If so, my avatar…
… would look like this…
Which is kind of a cool effect, but did you instead want to make it grayscale (which is what a “black and white” movie is more like)? So it looks like this instead…
The algorithm changes a little, but both are simple bits of processing on an SDL_Surface.
Neither of those, this is what I’m trying to achieve:
Basically I want all non background pixels to be set to white, I change the background in your avatar to black to show the final effect I want. And I want to do it in hardware, so no reading across the bus. I could precalculate it on load time and fairly easily do it in software, but I’d like to do it on the GPU.
Oh, I misunderstood what you meant, sorry.
If you’re using SDL_RenderCopy or SDL_RenderCopyEx with an SDL_Texture, you might be able to force this with modulation, but I don’t know if this actually works in practice:
(EDIT: this doesn’t work.)
// Multiply red, green, and blue by 255,
// effectively making every pixel white.
SDL_SetTextureColorMod(myTexture, 255, 255, 255);
// Multiply alpha by 255, so completely transparent pixels
// stay transparent (0*255=0), and everything else becomes
// fully opaque.
SDL_SetTextureAlphaMod(myTexture, 255);
…assuming this will saturate to full intensity if the multiplication against 255 becomes > 255, then the SDL_RenderCopy will give you the result you want, with one exception: if any of R,G, or B is zero, you won’t get a full white pixel on that one.
I’d have to think this through some more. This is very easy with a pixel shader, but the SDL_render options are pretty limited here.
Actually this doesn’t multiply the channels by 255, it multiplies them with 1. So 255, 255, 255 will just get you your original texture. So that doesn’t work
I found something on the wiki called “SDL_TEXTUREMODULATE_COLOR” which is an enum, but I can’t find anything else about how or where to use it, anyone?
To followup, Sam just added custom blend modes, which might be useful here:
I saw that, I’m going to play around with it as soon as I get a chance! He actually filled one of my other feature requests for subtractive blending, SDL might finally do everything I need it to!
Having some trouble implementing a custom blend mode, namely subtractive. Here’s the relevant code:
Creating my renderer:
SDL_Renderer* main_renderer = NULL;
main_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Setting up the blend mode as per Sams example:
SDL_BlendMode SubBlendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
SDL_SetTextureBlendMode(tempbuffer, SubBlendMode);
SDL_SetTextureAlphaMod(tempbuffer, 255);
And rendering it:
SDL_RenderCopy(main_renderer, tempbuffer, &srcRect, &dstRect);
But it is rendering with no blending at all. Should be noted that the “tempbuffer” texture has no alpha channel, I want to subtract the RGB values from the destination RGB values. Not exactly sure who to set up the blend mode to do that.
The operation I want is:
dstR = dstR - (srcR * srcTextureAlphaMod)
dstG = dstG - (srcG * srcTextureAlphaMod)
dstB = dstB - (srcB * srcTextureAlphaMod)
In fact, it seems the default accelerated renderer doesn’t support this as no matter what I set the blend mode to it doesn’t change the outcome.
[edit]If I change the blendoperation to ADD it works fine, but not subtract. So, help!
Are you on Windows and using the direct3d renderer? It seems the subtractive modes are not yet implemented in SDL for this renderer. Pretty sure Direct3D 9 can do that, but perhaps there were other issues. You could try the opengl renderer.
Yes I’m on Windows. I just use SDL_RENDERER_ACCELERATED, assuming SDL would automatically select the best one? How do you force a certain renderer? Didn’t find anything on the wiki.
It does. Direct3D almost always got better drivers on Windows.
You can tell SDL to select a specific renderer by looking at the available ones with SDL_GetNumRenderDrivers
and SDL_GetRenderDriverInfo
. If it lists one that is named opengl
, use the index of it in the SDL_CreateRenderer
call.
Alternatively, you can use SDL’s hint system. Set the environment variable SDL_RENDER_DRIVER
to opengl
and SDL will choose this one in the automatic render driver selection, if it is available. It is just a hint, it might get ignored. Check the name of the created renderer to make sure.
Just in case you’re not familiar with environment variables: You can simply open cmd.exe
and set it there. The command set
manages the environment variables for that console.
set SDL_RENDER_DRIVER=opengl
mysdlprogram.exe
Oh, I just noticed that the direct3d11
renderer supports the subtractive blend mode. However, it looks like this driver does not get built with the default config. (Guessing not enough testing yet? Seemed to work decently the few times I tried it.) If you build SDL yourself, you have to define SDL_VIDEO_RENDER_D3D11=1
to enable it. If you got one of the nightly builds it might be enabled in there. I’ll check later. Edit: The visualstudio build from https://buildbot.libsdl.org doesn’t have it.
Note that the direct3d11
renderer will be selected after the direct3d
renderer in the automatic selection. You have to use one of the methods described above to select it.
Got it sorted out. OpenGL supports the subtractive blending I need. I’m sticking to OpenGL for compatibility reasons, there may be more than Windows versions in my future. The Wiki really needs to be updated to all the new functionality.
Here’s the relevant parts of my code, hope it helps someone until the Wiki is updated:
// Enumerate all available renderers on the system
int numRenderers = SDL_GetNumRenderDrivers();
if (numRenderers < 0)
{
cout << "Unable to enumerate renderers: " << SDL_GetError() << endl;
SDL_Quit();
return 0;
}
// Iterate through them and select the desired one based on the name string. Set the index value to -1 to let SDL autoselect in case our renderer doesn't exist (TODO: error checking)
SDL_RendererInfo renderInfo;
int rendIndex = -1;
for (int i = 0; i < numRenderers; ++i)
{
SDL_GetRenderDriverInfo(i, &renderInfo);
if (strcmp(renderInfo.name, "opengl") == 0)
{
rendIndex = i;
break;
}
}
// Create our renderer with the selected index, or use the default -1 if our desired one was not found
SDL_Renderer* main_renderer = NULL;
main_renderer = SDL_CreateRenderer(window, rendIndex, SDL_RENDERER_ACCELERATED);
if (main_renderer == NULL)
{
cout << "Unable to create renderer: " << SDL_GetError() << endl;
SDL_Quit();
return 0;
}
Great. I’m sure the wiki will get updated once 2.0.6 is finalized.
For reference, here is what blend modes the renderers report as supported on my systems with the current tip. This may change before the 2.0.6 release. OpenGL should also be able to do more.
Linux
Intel GMA 950 on Linux
SDL2 e3797888c6f1 2017-08-20
There are 4 renderers available.
-- 0 --
Name: opengl
Texlimits: 2048x2048
Flags: (0x0000000a) hardware targettexture
Texturefmts: 5
SDL_PIXELFORMAT_ARGB8888 0x16362004 372645892
SDL_PIXELFORMAT_YV12 0x32315659 842094169
SDL_PIXELFORMAT_IYUV 0x56555949 1448433993
SDL_PIXELFORMAT_NV12 0x3231564e 842094158
SDL_PIXELFORMAT_NV21 0x3132564e 825382478
Blendmodes: NONE, BLEND, ADD, MOD, and 29996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 0
ADD REV_SUBTRACT 0
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 0
SUBTRACT REV_SUBTRACT 0
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 0
REV_SUBTRACT SUBTRACT 0
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 1 --
Name: opengles2
Texlimits: 2048x2048
Flags: (0x0000000a) hardware targettexture
Texturefmts: 8
SDL_PIXELFORMAT_ARGB8888 0x16362004 372645892
SDL_PIXELFORMAT_ABGR8888 0x16762004 376840196
SDL_PIXELFORMAT_RGB888 0x16161804 370546692
SDL_PIXELFORMAT_BGR888 0x16561804 374740996
SDL_PIXELFORMAT_YV12 0x32315659 842094169
SDL_PIXELFORMAT_IYUV 0x56555949 1448433993
SDL_PIXELFORMAT_NV12 0x3231564e 842094158
SDL_PIXELFORMAT_NV21 0x3132564e 825382478
Blendmodes: NONE, BLEND, ADD, MOD, and 89996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 10000
ADD REV_SUBTRACT 10000
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 10000
SUBTRACT REV_SUBTRACT 10000
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 10000
REV_SUBTRACT SUBTRACT 10000
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 2 --
Name: opengles
Texlimits: 2048x2048
Flags: (0x0000000a) hardware targettexture
Texturefmts: 1
SDL_PIXELFORMAT_ABGR8888 0x16762004 376840196
Blendmodes: NONE, BLEND, ADD, MOD, and 89996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 10000
ADD REV_SUBTRACT 10000
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 10000
SUBTRACT REV_SUBTRACT 10000
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 10000
REV_SUBTRACT SUBTRACT 10000
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 3 --
Name: software
Texlimits: 0x0
Flags: (0x00000009) software targettexture
Texturefmts: 8
SDL_PIXELFORMAT_ARGB8888 0x16362004 372645892
SDL_PIXELFORMAT_ABGR8888 0x16762004 376840196
SDL_PIXELFORMAT_RGBA8888 0x16462004 373694468
SDL_PIXELFORMAT_BGRA8888 0x16862004 377888772
SDL_PIXELFORMAT_RGB888 0x16161804 370546692
SDL_PIXELFORMAT_BGR888 0x16561804 374740996
SDL_PIXELFORMAT_RGB565 0x15151002 353701890
SDL_PIXELFORMAT_RGB555 0x15130f02 353570562
Blendmodes: NONE, BLEND, ADD, MOD, and 0 custom blendmodes.
Windows
Intel HD Graphics 400 on Windows
SDL2 e3797888c6f1 2017-08-20
There are 5 renderers available.
-- 0 --
Name: direct3d
Texlimits: 8192x8192
Flags: (0x0000000a) hardware targettexture
Texturefmts: 3
SDL_PIXELFORMAT_ARGB8888 0x16362004 00372645892
SDL_PIXELFORMAT_YV12 0x32315659 00842094169
SDL_PIXELFORMAT_IYUV 0x56555949 01448433993
Blendmodes: NONE, BLEND, ADD, MOD, and 9996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 0
REV_SUBTRACT REV_SUBTRACT 0
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 0
ADD REV_SUBTRACT 0
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 0
SUBTRACT REV_SUBTRACT 0
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 0
REV_SUBTRACT SUBTRACT 0
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 1 --
Name: direct3d11
Texlimits: 16384x16384
Flags: (0x0000000a) hardware targettexture
Texturefmts: 4
SDL_PIXELFORMAT_ARGB8888 0x16362004 00372645892
SDL_PIXELFORMAT_RGB888 0x16161804 00370546692
SDL_PIXELFORMAT_YV12 0x32315659 00842094169
SDL_PIXELFORMAT_IYUV 0x56555949 01448433993
Blendmodes: NONE, BLEND, ADD, MOD, and 249996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 10000
MAXIMUM MAXIMUM 10000
ADD SUBTRACT 10000
ADD REV_SUBTRACT 10000
ADD MINIMUM 10000
ADD MAXIMUM 10000
SUBTRACT ADD 10000
SUBTRACT REV_SUBTRACT 10000
SUBTRACT MINIMUM 10000
SUBTRACT MAXIMUM 10000
REV_SUBTRACT ADD 10000
REV_SUBTRACT SUBTRACT 10000
REV_SUBTRACT MINIMUM 10000
REV_SUBTRACT MAXIMUM 10000
MINIMUM ADD 10000
MINIMUM SUBTRACT 10000
MINIMUM REV_SUBTRACT 10000
MINIMUM MAXIMUM 10000
MAXIMUM ADD 10000
MAXIMUM SUBTRACT 10000
MAXIMUM REV_SUBTRACT 10000
MAXIMUM MINIMUM 10000
-- 2 --
Name: opengl
Texlimits: 16384x16384
Flags: (0x0000000a) hardware targettexture
Texturefmts: 5
SDL_PIXELFORMAT_ARGB8888 0x16362004 00372645892
SDL_PIXELFORMAT_YV12 0x32315659 00842094169
SDL_PIXELFORMAT_IYUV 0x56555949 01448433993
SDL_PIXELFORMAT_NV12 0x3231564e 00842094158
SDL_PIXELFORMAT_NV21 0x3132564e 00825382478
Blendmodes: NONE, BLEND, ADD, MOD, and 29996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 0
ADD REV_SUBTRACT 0
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 0
SUBTRACT REV_SUBTRACT 0
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 0
REV_SUBTRACT SUBTRACT 0
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 3 --
Name: opengles2
Texlimits: 8192x8192
Flags: (0x0000000a) hardware targettexture
Texturefmts: 8
SDL_PIXELFORMAT_ARGB8888 0x16362004 00372645892
SDL_PIXELFORMAT_ABGR8888 0x16762004 00376840196
SDL_PIXELFORMAT_RGB888 0x16161804 00370546692
SDL_PIXELFORMAT_BGR888 0x16561804 00374740996
SDL_PIXELFORMAT_YV12 0x32315659 00842094169
SDL_PIXELFORMAT_IYUV 0x56555949 01448433993
SDL_PIXELFORMAT_NV12 0x3231564e 00842094158
SDL_PIXELFORMAT_NV21 0x3132564e 00825382478
Blendmodes: NONE, BLEND, ADD, MOD, and 89996 custom blendmodes.
Color Op Alpha Op Modes
ADD ADD 9996
SUBTRACT SUBTRACT 10000
REV_SUBTRACT REV_SUBTRACT 10000
MINIMUM MINIMUM 0
MAXIMUM MAXIMUM 0
ADD SUBTRACT 10000
ADD REV_SUBTRACT 10000
ADD MINIMUM 0
ADD MAXIMUM 0
SUBTRACT ADD 10000
SUBTRACT REV_SUBTRACT 10000
SUBTRACT MINIMUM 0
SUBTRACT MAXIMUM 0
REV_SUBTRACT ADD 10000
REV_SUBTRACT SUBTRACT 10000
REV_SUBTRACT MINIMUM 0
REV_SUBTRACT MAXIMUM 0
MINIMUM ADD 0
MINIMUM SUBTRACT 0
MINIMUM REV_SUBTRACT 0
MINIMUM MAXIMUM 0
MAXIMUM ADD 0
MAXIMUM SUBTRACT 0
MAXIMUM REV_SUBTRACT 0
MAXIMUM MINIMUM 0
-- 4 --
Name: software
Texlimits: 0x0
Flags: (0x00000009) software targettexture
Texturefmts: 8
SDL_PIXELFORMAT_ARGB8888 0x16362004 00372645892
SDL_PIXELFORMAT_ABGR8888 0x16762004 00376840196
SDL_PIXELFORMAT_RGBA8888 0x16462004 00373694468
SDL_PIXELFORMAT_BGRA8888 0x16862004 00377888772
SDL_PIXELFORMAT_RGB888 0x16161804 00370546692
SDL_PIXELFORMAT_BGR888 0x16561804 00374740996
SDL_PIXELFORMAT_RGB565 0x15151002 00353701890
SDL_PIXELFORMAT_RGB555 0x15130f02 00353570562
Blendmodes: NONE, BLEND, ADD, MOD, and 0 custom blendmodes.