代码之家  ›  专栏  ›  技术社区  ›  Mashpoe

SDL_纹理使所有内容呈现黑色

  •  1
  • Mashpoe  · 技术社区  · 7 年前

    我在SDL中开发了一个相当大的应用程序有一段时间了,最近注意到一个奇怪的bug;每当一个窗口关闭时,另一个窗口上的所有内容都将呈现完全黑色。当我画一条红色的线时,它会是黑色的,当我画一个SDL_纹理时,它会画一个黑色的矩形来代替图像。

    过了一段时间,我从头开始制作简化版的应用程序,成功地重现了这个问题。该程序包括一个窗口类,用于存储窗口、其渲染器和SDL_纹理。window类还包括一个渲染函数,用于在其窗口(包括SDL_纹理)上渲染内容。还有一个函数允许每个窗口对象处理SDL事件,例如关闭的窗口。当窗口关闭时,窗口、渲染器和纹理都会被破坏。

    class Window {
        SDL_Window *window;
        SDL_Renderer *renderer;
        Uint32 windowID;
    
        SDL_Texture *texture;
    
        void cleanup() {
            SDL_DestroyWindow(window);
            SDL_DestroyRenderer(renderer);
            SDL_DestroyTexture(texture);
        }
    
        bool running = true;
    public:
    
        void init() {
    
            window = SDL_CreateWindow("Window", 50, 50, 721, 558, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            windowID = SDL_GetWindowID(window);
            SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
    
            // load texture
            SDL_Surface* loadedSurface = IMG_Load("picture.png");
            texture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
            SDL_FreeSurface(loadedSurface);
    
        }
    
        bool isRunning() {
            return running;
        }
    
        void render() {
            // clear the screen with a green color
            SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
            SDL_RenderClear(renderer);
    
            // create a rectangle for drawing things
            SDL_Rect rect = {0, 0, 100, 100};
    
            // draw a red rectangle
            SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
            SDL_RenderFillRect(renderer, &rect);
    
            // draw the texture/image on top of the rectangle
            if (SDL_RenderCopy(renderer, texture, NULL, &rect) < 0) {
                printf("Unable to render texture! Error: %s\n", SDL_GetError());
            }
    
    
    
            SDL_RenderPresent(renderer);
        }
    
        void events(SDL_Event &e) {
            if (e.window.windowID == windowID && e.window.event == SDL_WINDOWEVENT_CLOSE) {
                running = false;
                cleanup();
            }
        }
    };
    

    主功能一次管理多个窗口,并分别为每个窗口提供SDL事件:

    int main(int argc, const char * argv[]) {
    
        if (SDL_Init(SDL_INIT_VIDEO) < 0) { // initialize SDL and IMG
            printf("SDL could not initialize! Error: %s\n", SDL_GetError());
        } else if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) {
            printf("SDL_image could not initialize! Error: %s\n", IMG_GetError());
        } else {
            std::vector<Window*> windows; // vector of window objects
    
            // add window objects to the vector
            windows.push_back(new Window());
            windows.push_back(new Window());
            windows.push_back(new Window());
            windows.push_back(new Window());
    
            // initialize all windows
            for (int i = 0; i < windows.size(); i++) {
                windows[i]->init();
            }
    
            // game loop
            bool loop = true;
            while (loop) {
                SDL_Delay(50); // delay between each frame
    
                // render all windows
                for (int i = 0; i < windows.size(); i++) {
                    windows[i]->render();
                }
    
                // handle new events
                SDL_Event e;
                while (SDL_PollEvent(&e)) {
    
                    // loop backward through windows
                    // in case one of them has to be
                    // removed from the vector
                    for (unsigned long i = windows.size(); i-- > 0;) {
                        if (windows[i]->isRunning()) {
                            windows[i]->events(e);
                        } else {
                            // delete a window if it has been closed
                            delete windows[i];
                            windows.erase(windows.begin() + i);
                        }
                    }
                }
    
                if (windows.empty()) { // if all windows are closed,
                    loop = false;      // stop the loop
                }
            }
    
        }
    
        return 0;
    }
    

    其他窗口关闭后 .唯一能呈现不同颜色的是 SDL_RenderClear ,我在上面的代码中使用它来渲染绿色背景,从而暴露黑色图像和矩形形状。

    我已经测试过,以确保纹理、渲染器和窗口在出现此问题后仍然有效,并且没有出现错误。

    我至少想找出问题的原因,以及是否有任何可能的解决方案。

    1 回复  |  直到 7 年前
        1
  •  2
  •   user7860670    7 年前

    渲染器仍处于活动状态时,不应破坏窗口。尝试在中执行方法 cleanup()

    void cleanup()
    {
        SDL_DestroyTexture(texture);
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
    }