我正在尝试创建一个本身完全透明的 SDL 窗口,但是当将图像渲染到其上时,图像完全不透明并且图像的 Alpha 通道被保留(因此图像的透明像素保持透明) 。因此,结果只是屏幕上的图像,周围没有任何容器(想象一下在屏幕上贴一张现实生活中的贴纸)
所以这是简化的代码:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_syswm.h>
#include <iostream>
#include <Windows.h>
#include <string>
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* image;
int imageWidth = 0;
int imageHeight = 0;
bool init()
{
//Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
return false;
}
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
printf("Warning: Linear texture filtering not enabled!");
}
//Create window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 300, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS);
if (window == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
return false;
}
//Create renderer for window
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL)
{
printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
return false;
}
//Initialize renderer color
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
return false;
}
return true;
}
bool loadImage(const std::string& path)
{
//The final texture
SDL_Texture* newImage = NULL;
//Load image at specified path
SDL_Surface* loadedSurface = IMG_Load(path.c_str());
if (!loadedSurface)
{
printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
return false;
}
//Create texture from surface pixels
newImage = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (!newImage)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
return false;
}
imageWidth = loadedSurface->w;
imageHeight = loadedSurface->h;
//Get rid of old loaded surface
SDL_FreeSurface(loadedSurface);
image = newImage;
return true;
}
void displayImage()
{
SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
SDL_RenderClear(renderer);
SDL_SetWindowSize(window, imageWidth, imageHeight);
SDL_Rect renderQuad = { 0, 0, imageWidth, imageHeight };
SDL_RenderCopy(renderer, image, NULL, &renderQuad);
SDL_RenderPresent(renderer);
}
// Makes a window transparent by setting a transparency color.
bool windowColorKey(SDL_Window* window, COLORREF colorKey) {
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version); // Initialize wmInfo
SDL_GetWindowWMInfo(window, &wmInfo);
HWND hWnd = wmInfo.info.win.window;
// Change window type to layered
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// Set transparency color
return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
}
int main(int argc, char* args[]) {
// Initialize SDL: Create a window and renderer
init();
// Load the image
loadImage("example.png");
// Color key the background of the window (magenta)
windowColorKey(window, RGB(255, 0, 255));
// Render the image on the widnow with magenta for backround color
displayImage();
// Check for events
bool windowActive = true;
SDL_Event event;
while (windowActive)
{
while (SDL_PollEvent(&event) != 0)
{
if (event.type == SDL_QUIT || event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { windowActive = false; }
}
}
return 0;
}
使用 SDL_SetWindowOpacity() 不起作用,因为窗口的所有元素也是透明的。
目前我知道实现此目标的唯一方法是使用颜色键控,但不幸的是它效果不佳,因为某些图像将包含您用于颜色键控的颜色,此外图像将有一个小用于图像周围颜色键控的颜色边框。虽然很薄但是很烦人。
我正在考虑以其他方式使用分层窗口的功能,但无法找到或理解如何使用。
那么,问题是如何让窗口本身完全透明,同时完全控制窗口元素的透明度?
SDL 人员似乎已经意识到这一流行的请求和问题:
https://github.com/libsdl-org/SDL/issues/1872
并且不打算在 SDL_SetWindowOpacity() 之外做任何事情,这远没有透明背景那么有用或酷。