Texture with an alpha channel

Hello. ?I seem to be having a problem drawing a texture with an alpha channel - the alpha channel is ignored.

If I set the draw color to FF000080 and call?SDL_RenderFillRect()?then I see a red rectangle blended into the black and white rectangles already there, as I expect. ?Next, if I make a texture, fill it with the color?FF000080, and then blend it in using?SDL_RenderCopy() over?a black and white rectangle, I expect to see a result visually identical to the first. ?Instead, I see a bright red rectangle completely wiping out the black and white ones there.

I created a simple test.py to show what I mean. ?It draws once using SDL_RenderFillRect() on the left and once using SDL_RenderCopy() on the right.

I think the two draws should appear the same, not differently. ?I’m probably?missing an important line somewhere but I’m just not seeing it. ?Thanks for any help.

-Roger

import sdl2
import ctypes

sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)

window = sdl2.SDL_CreateWindow(‘test’,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sdl2.SDL_WINDOWPOS_UNDEFINED,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sdl2.SDL_WINDOWPOS_UNDEFINED,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?640, 480, 0)

renderer = sdl2.SDL_CreateRenderer(window, -1, sdl2.SDL_RENDERER_ACCELERATED)
sdl2.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255) # black
sdl2.SDL_RenderClear(renderer)
sdl2.SDL_RenderPresent(renderer)

size = 32

case 1 using SDL_RenderFillRect

sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_NONE)
r = sdl2.SDL_Rect(0, 0, size / 2, size)
sdl2.SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff)
sdl2.SDL_RenderFillRect(renderer, r)

sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_BLEND)
r = sdl2.SDL_Rect(0, 0, size, size / 2)
sdl2.SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0x80)
sdl2.SDL_RenderFillRect(renderer, r)

case 2 using SDL_RenderCopy

sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_NONE)
r = sdl2.SDL_Rect(size * 2, 0, size / 2, size)
sdl2.SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff)
sdl2.SDL_RenderFillRect(renderer, r)

texture = sdl2.SDL_CreateTexture(renderer,?
? ? sdl2.SDL_PIXELFORMAT_RGBA8888, sdl2.SDL_TEXTUREACCESS_TARGET,?
? ? size, size)
sdl2.SDL_SetRenderTarget(renderer, texture)
sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_NONE)
sdl2.SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0x80)
sdl2.SDL_RenderClear(renderer)
sdl2.SDL_SetRenderTarget(renderer, None)

sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_BLEND)
r = sdl2.SDL_Rect(size * 2, 0, size, size / 2)
sdl2.SDL_RenderCopy(renderer, texture, None, r)

sdl2.SDL_RenderPresent(renderer)

while window != None:
? ? e = sdl2.SDL_Event()

? ? if sdl2.SDL_PollEvent(ctypes.byref(e)) != 0:
? ? ? ? if e.type == sdl2.events.SDL_QUIT:
? ? ? ? ? ? sdl2.SDL_DestroyWindow(window)
? ? ? ? ? ? window = None

sdl2.SDL_DestroyTexture(texture)
sdl2.SDL_DestroyRenderer(renderer)
renderer = None
sdl2.SDL_Quit()

Roger, my memory is fuzzy but i believe for a given combination of source and destination surface parameters, SDL will do a straight replace of target contents on blit. you end up with the alpha channel you expect in the target buffer, just not blended with what was already there. i had a hell of a time with this over a year ago and did some trial and error to get what i wanted.

here is a relevant snippet from the docs for SDL 1.2:
RGBA->RGBA with SDL_SRCALPHA

The source is alpha-blended with the destination using the source alpha channel. The alpha channel in the destination surface is left untouched. SDL_SRCCOLORKEY is ignored.

RGBA->RGBA without SDL_SRCALPHA

The RGBA data is copied to the destination surface. If SDL_SRCCOLORKEY is set, only the pixels not matching the colorkey value are copied.

i just looked back at my code and SDL_SRCALPHA is a parameter to SDL_CreateRGBSurface, so you need the right combination of attributes on both surfaces and to the blit call. how this translates to SDL2 is beyond me but HTH anyway.

Have you tried setting the blend mode of the texture using SDL_SetTextureBlendMode (http://wiki.libsdl.org/SDL_SetTextureBlendMode?highlight=(\bCategoryRender\b)|(CategoryEnum)|(CategoryStruct))?

Hello. ?I seem to be having a problem drawing a texture with an alpha channel - the alpha channel is ignored.

This is now solved.

lgm <xxx.xxx at x-mail.net> wrote:

Have you tried setting the blend mode of the texture using?SDL_SetTextureBlendMode??

This is what I was missing! ?I’m not sure why?SDL_SetRenderDrawBlendMode() didn’t work.

Setting this results in both images in the test appearing the same.

The diff to use it in the test looks like this:

-sdl2.SDL_SetRenderDrawBlendMode(renderer, sdl2.SDL_BLENDMODE_BLEND)
+sdl2.SDL_SetTextureBlendMode(texture, sdl2.SDL_BLENDMODE_BLEND)
r = sdl2.SDL_Rect(size * 2, 0, size, size / 2)
sdl2.SDL_RenderCopy(renderer, texture, None, r)

Thanks,
-Roger

This is what I was missing! I’m not sure why SDL_SetRenderDrawBlendMode() didn’t work.

Glad it worked. [Wink]
As I understand it, the distinction is that the RenderDraw calls use the RenderDrawBlendMode and the RenderCopy calls use the TextureBlend mode to decide how to calculate the resulting pixel values. So if you draw to a texture using alpha blending and then copy that texture to another texture (the renderer texture) without alpha blending, those alpha values you used in the draw are just ignored.