0
votes

while building my own graphics engine, I need to have a possibility of alpha blending (on SDL_Surface). Here is some testing code:

(...)/test2/test2_1.cpp :
#include"../render_SDL/ME_render.h"

int main(int argc, char* argv[])
{
    Init();
    SDL_Window* w = SDL_CreateWindow("Test", 50, 50, 800, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    ME_Objects o;
    ME_Rect r1(50, 100, 300, 200, ME_RGBA(0, 0, 255, 255));
    ME_Rect r2(200, 150, 250, 350, ME_RGBA(255, 0, 0, 127));
    o.Add(&r1);
    o.Add(&r2);
    SDL_Surface *s1 = SDL_GetWindowSurface(w);
    SDL_SetSurfaceBlendMode(s1, SDL_BLENDMODE_BLEND);
    Uint32 rmask, gmask, bmask, amask;
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    rmask = 0xff000000;
    gmask = 0x00ff0000;
    bmask = 0x0000ff00;
    amask = 0x000000ff;
    #else
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
    #endif
    SDL_Surface *s = SDL_CreateRGBSurface(0, 800, 600, 32, rmask, gmask, bmask, amask);
    SDL_SetSurfaceBlendMode(s, SDL_BLENDMODE_BLEND);
    o.ME_Rects[0].Render(s, 0, 0);
    o.ME_Rects[1].Render(s, 0, 0);
    ME_IMG i1(200, 250, "koncepcja.png");
    o.Add(&i1);
    ME_Line l1(10, 10, 160, 200, ME_RGBA(0, 255, 0, 255));
    o.Add(&l1);
    o.ME_IMGs[0].Load();
    o.UpdateBasicData(2, 0);
    o.ME_IMGs[0].Render(s, 0, 0);
    o.ME_Lines[0].Render(s, 0, 0);
    SDL_Rect scr = {0, 0, 800, 600};
    SDL_BlitSurface(s, NULL, s1, &scr);
    SDL_UpdateWindowSurface(w);
    Uint8 _r, _g, _b, _a;
    SDL_GetRGBA(((Uint32*)s1->pixels)[(151*s1->w)+201], s1->format, &_r, &_g, &_b, &_a);
    std::cout<<"RGBA: "<<(int)_r<<' '<<(int)_g<<' '<<(int)_b<<' '<<(int)_a<<'\n';
    bool running = true;
    while(running)
    {
        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
            case SDL_QUIT:
                running = false;
            case SDL_WINDOWEVENT:
                if(event.window.event==SDL_WINDOWEVENT_RESIZED)
                {
                     s1 = SDL_GetWindowSurface(w);
                     SDL_BlitSurface(s, NULL, s1, &scr);
                     SDL_UpdateWindowSurface(w);
                }
            }
        }
    }
    SDL_DestroyWindow(w);
    char _resp;
    std::cin>>_resp;
    Quit();
    return 0;
}
(...)/render_SDL/ME_render.h :
(...)
bool ME_Rect::Render(void* surface, uintmax_t scrposx1, uintmax_t scrposy1)
{
    for(uintmax_t i = x1-scrposx1; i<x2-scrposx1; ++i)  for(uintmax_t j = y1-scrposx1; j<y2-scrposx1; ++j)  ((Uint32*)(((SDL_Surface*)surface)->pixels))[(j*((SDL_Surface*)surface)->w)+i] = SDL_MapRGBA(((SDL_Surface*)surface)->format, color.r, color.g, color.b, color.a);
    return true;
}
(...)

So I am setting every pixel value directly. But, despite setting alpha value of the rectangle r2 to 127, this rectangle (on the screen) isn't transparent - it's color is dark red without the dependence on the background colors (black area with r1 - the blue rectangle). I checked the output. It shows:

RGBA: 127 0 0 255

instead of expected result:

RGBA: 127 0 255 255

How to make the alpha blending work correctly?

1

1 Answers

0
votes

I finally solved the problem by creating additional surface (of the dimensions of the rectangle r2) and filling it entirely with the color (transparent red). Then I blitted it to the surface s (in which the whole screen contents are stored) and then I blitted the surface s to s1 (window surface). And the alpha blending works!