简体   繁体   English

SDL2 透明表面

[英]SDL2 Transparent surface

I am trying to create a transparent surface, blit it bigger surface (size of my screen), then create a texture of it, copy to the renderer, and finaly render present.我正在尝试创建一个透明的表面,将其放大到更大的表面(我的屏幕尺寸),然后创建它的纹理,复制到渲染器,最后呈现呈现。

I have seen many other forums saying I have to use SetBlendMode (for surface, texture, and renderer), ColorKey, SetSurfaceBlendMode.我看到许多其他论坛说我必须使用 SetBlendMode(用于表面、纹理和渲染器)、ColorKey、SetSurfaceBlendMode。 I tried them all but I can't seem to get it to work.我尝试了所有这些,但似乎无法使其正常工作。 I read that SDL_BlitScaled is not suitable for combining surfaces that have transparent pixels, but I am completely lost as to what I have to do instead.我读到 SDL_BlitScaled 不适合组合具有透明像素的表面,但我完全不知道我必须做什么。

What I noticed, when I use SDL_CreateRGBSurface (with an alpha value) to create a surface, the surface's PixelFormat is RGB888 instead of RGBA8888 (what I am expecting since I provide the alpha value).我注意到,当我使用 SDL_CreateRGBSurface(带有 alpha 值)创建一个表面时,该表面的 PixelFormat 是 RGB888 而不是 RGBA8888(这是我所期望的,因为我提供了 alpha 值)。 Using SDL_ConvertSurfaceFormat did not help.使用 SDL_ConvertSurfaceFormat 没有帮助。

Can somebody tell me what I am missing?有人可以告诉我我缺少什么吗?

Complete code: removed, my appologies完整代码:已删除,我的应用程序

Please note that I have removed the attempts to get transparency working请注意,我已经删除了使透明度工作的尝试

The renderer:渲染器:

mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED);

My render loop:我的渲染循环:

void CApp::Render()
{
    SDL_RenderClear(mRenderer);

    mBackGround->Render(mRenderer);
    mForeGround->Render(mRenderer);

    SDL_RenderPresent(mRenderer);
}

The big surface I am blitting to:我要表达的大表面:

mSurface = SDL_CreateRGBSurface(0, CApp::Window_W(), CApp::Window_H(), 32, 0, 0, 0, 0);

The code to get tiles from a spritesheet:从精灵表获取图块的代码:

bool Map::GetTilesFromSpriteSheet(SDL_Surface *pSpriteSheet, int pTile_w, int pTile_h)
{
    if(pSpriteSheet->w % pTile_w == 0 && pSpriteSheet->h % pTile_h == 0) {
        SDL_Rect srcRect;
        srcRect.w = pTile_w;
        srcRect.h = pTile_h;
        for(int y = 0; y < pSpriteSheet->h / pTile_h; y++) {
            for(int x = 0; x < pSpriteSheet->w / pTile_w; x++) {
                srcRect.x = x*pTile_w;
                srcRect.y = y*pTile_h;
                SDL_Surface* tempSurface = SDL_CreateRGBSurface(0, pTile_w, pTile_h, 32, 0, 0, 0, 0);
                if(SDL_BlitSurface(pSpriteSheet, &srcRect, tempSurface, nullptr)==0) {
                    mTiles.push_back(tempSurface);
                } else {
                    Log("Error extracting tile (%d,%d)(w,h): %s", x, y, SDL_GetError());
                    return false;
                }
            }
        }
        Log("Number of tiles: %d", static_cast<int>(mTiles.size()));
    } else {
        Log("Background spritesheet is incompatible with tile dimensions (%d,%d)(w,h).", pTile_w, pTile_h);
        return false;
    }
    return true;
}

This is where I combine the tiles to create the big surface:这是我组合瓷砖以创建大表面的地方:

bool Map::GenerateMap(std::vector<std::vector<int>> &pMap, std::vector<SDL_Surface*> &pTiles, SDL_Surface* pDestination)
{
    SDL_Rect rect;
    rect.w = mDstTile_W;
    rect.h = mDstTile_H;
    SDL_Surface* transparent = SDL_CreateRGBSurface(0, mDstTile_W, mDstTile_H, 32, 0, 0, 0, 0);

    for(int y = 0; y < static_cast<int>(pMap.size()); y++) {
        for(int x = 0; x < static_cast<int>(pMap.at(static_cast<unsigned long>(y)).size()); x++) {
            rect.x = x*mDstTile_W;
            rect.y = y*mDstTile_H;
            int index = static_cast<int>(pMap.at(static_cast<unsigned long>(y)).at(static_cast<unsigned long>(x)));
            if(index < 0) {
                if(SDL_BlitScaled(transparent, nullptr, pDestination, &rect) != 0) {
                    Log("Error blitting transparent surface to destination: %s", SDL_GetError());
                }
            } else if(SDL_BlitScaled(pTiles[static_cast<unsigned long>(index)],
                              nullptr, pDestination, &rect) != 0) {
                Log("Error blitting surface to destination: %s", SDL_GetError());
                return false;
            }
        }
    }
    SDL_FreeSurface(transparent);
    return true;
}

And finaly, this is the code to render the big surface to the screen, first by creating a texture:最后,这是将大表面渲染到屏幕的代码,首先是创建一个纹理:

void ForeGround::Render(SDL_Renderer* pRenderer)
{
    if(mTexture) SDL_DestroyTexture(mTexture);
    mTexture = SDL_CreateTextureFromSurface(pRenderer, mSurface);

    if(mTexture == nullptr) {
        Log("Unable to create foreground texture: %s", SDL_GetError());
    } else if (SDL_RenderCopy(pRenderer, mTexture, nullptr, nullptr)) {
        Log("Unable to render foreground: %s", SDL_GetError());
    }
}

As @keltar mentioned, I was not creating surfaces with an alpha value.正如@keltar 提到的,我没有创建具有 alpha 值的曲面。

I had to change the SDL_CreateRGBSurface call.我不得不更改SDL_CreateRGBSurface调用。 The code snippet below creates an empty, transparent surface where I can blit to if needed (for example, tiles from a spritesheet).下面的代码片段创建了一个空的、透明的表面,如果需要,我可以在其中进行 blit(例如,来自 spritesheet 的图块)。

SDL_Surface* tempSurface = SDL_CreateRGBSurface(..., 32, 0xff, 0xff00, 0xff0000, 0xff000000);

The code snippet below creates a black, non-transparent surface.下面的代码片段创建了一个黑色的、不透明的表面。

SDL_Surface* tempSurface = SDL_CreateRGBSurface(..., 32, 0xff, 0xff00, 0xff0000, 0x00000000);

This was enough for me, I did not have to use SDL_SetRenderDrawBlendMode , SDL_SetSurfaceBlendMode , SDL_SetTextureBlendMode , or SDL_ConvertSurface .这对我来说已经足够了,我不必使用SDL_SetRenderDrawBlendModeSDL_SetSurfaceBlendModeSDL_SetTextureBlendModeSDL_ConvertSurface A quick look at the SDL wiki showed:快速浏览 SDL wiki 显示:

By default surfaces with an alpha mask are set up for blending as with默认情况下,带有 alpha 蒙版的曲面设置为与

SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND) SDL_SetSurfaceBlendMode(表面,SDL_BLENDMODE_BLEND)

Which explained why I did not have to call any of those functions.这解释了为什么我不必调用任何这些函数。 A big shout-out to keltar for his quick answer!对 keltar 的快速回答大喊大叫!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM