C++ SDL2透明表面

C++ SDL2透明表面,c++,windows,sdl-2,C++,Windows,Sdl 2,我试图创建一个透明的表面,将其放大(屏幕大小),然后创建一个纹理,复制到渲染器,最后渲染当前 我看到许多其他论坛说我必须使用SetBlendMode(用于表面、纹理和渲染器)、ColorKey、SetSurfaceBlendMode。我都试过了,但似乎都没用。我读到SDL_BlitScaled不适合组合具有透明像素的曲面,但我完全不知道我必须做什么 我注意到,当我使用SDL_CreateRGBSurface(带有alpha值)创建曲面时,曲面的像素格式是RGB888,而不是RGBA888(因为我

我试图创建一个透明的表面,将其放大(屏幕大小),然后创建一个纹理,复制到渲染器,最后渲染当前

我看到许多其他论坛说我必须使用SetBlendMode(用于表面、纹理和渲染器)、ColorKey、SetSurfaceBlendMode。我都试过了,但似乎都没用。我读到SDL_BlitScaled不适合组合具有透明像素的曲面,但我完全不知道我必须做什么

我注意到,当我使用SDL_CreateRGBSurface(带有alpha值)创建曲面时,曲面的像素格式是RGB888,而不是RGBA888(因为我提供了alpha值,所以我期望这样)。使用SDL_ConvertSurfaceFormat没有帮助

有人能告诉我我错过了什么吗

完整代码:删除,我的任命

请注意,我已删除了使透明度正常工作的尝试

渲染器:

mRenderer = SDL_CreateRenderer(mWindow, -1, SDL_RENDERER_ACCELERATED);
我的渲染循环:

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

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

    SDL_RenderPresent(mRenderer);
}
我要飞到的大表面:

mSurface = SDL_CreateRGBSurface(0, CApp::Window_W(), CApp::Window_H(), 32, 0, 0, 0, 0);
从精灵表获取互动程序的代码:

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;
}

正如@keltar提到的,我并没有创建具有alpha值的曲面

我必须更改
SDL\u CreateRGBSurface
调用。下面的代码片段创建了一个空的、透明的表面,如果需要的话,我可以将其blit到该表面(例如,从精灵表中平铺)

下面的代码片段创建了一个黑色的不透明表面

SDL_Surface* tempSurface = SDL_CreateRGBSurface(..., 32, 0xff, 0xff00, 0xff0000, 0x00000000);
这对我来说已经足够了,我没有使用
SDL\u SetRenderDrawBlendMode
SDL\u SetSurfaceBlendMode
SDL\u SetTextureBlendMode
,或者
SDL\u ConvertSurface
。快速查看SDL wiki显示:

默认情况下,带有alpha遮罩的曲面将设置为与的混合

SDL_设置曲面BLENDMODE(曲面、SDL_BLENDMODE_混合)


这就解释了为什么我不需要调用这些函数。对凯尔塔的快速回答大声呼喊

所有曲面都没有alpha通道<代码>创建RGB曲面(…,32,0,0,0,0,0)没有意义,因为未定义掩码,但为方便起见,SDL将其视为RGB888(反映在所述函数的文档中)<代码>创建RGB表面(…,32,0x000000ff,0x0000ff00,0x00ff0000,0)再次创建RGB888,因为alpha通道掩码为0宽。例如,对所有曲面使用
32、0xff、0xff00、0xff0000、0xff000000
(可以说您不需要alpha作为背景,但类继承已经是一场灾难)。在每个帧上重建纹理的速度很慢,最好使用流式纹理和lock+memcpy。@keltar惊讶于我的错误是多么愚蠢。我看到有人用它,但我不明白为什么。我现在知道了,非常感谢你!接下来的问题是,你是说类继承像我那样是一场灾难,还是说总体上是一场灾难?另外,我可以用你们的建议回答我自己的问题,或者你们可以把它作为一个解决方案发布?当然,若问题解决了,就发布你们的答案,这很好。我为这场“灾难”感到抱歉,因为它是基于观点的。如果你认为它对你有用-那很好。如果它最终咬人——仍然很好,现在你知道为什么了。请原谅我,为什么你认为这是一场灾难?面向对象的方法已经自学了,我还在学习!我同意,背景不需要透明度,但我也认为它不会造成太大伤害。然而,我也不知道我是否会将其保留为2层贴图(背景+前景)。也许我会再加一层,还不确定。我打算到达那座桥时再过桥。
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());
    }
}
SDL_Surface* tempSurface = SDL_CreateRGBSurface(..., 32, 0xff, 0xff00, 0xff0000, 0xff000000);
SDL_Surface* tempSurface = SDL_CreateRGBSurface(..., 32, 0xff, 0xff00, 0xff0000, 0x00000000);