【问题标题】:Create opengl context in SDL and C++ using singleton pattern使用单例模式在 SDL 和 C++ 中创建 opengl 上下文
【发布时间】:2022-01-26 00:27:14
【问题描述】:

我正在尝试使用单例模式使用 SDL 和 OpenGL 创建一个简单的窗口,但是当我执行代码时出现一个白色窗口并且 VGA 的使用量也没有增加,任何错误处理程序都没有得到任何东西,这意味着一切效果很好。

当我取消 SDL_GetError 注释时,屏幕上出现以下错误:无效窗口,但它只出现在循环中

Main.cpp

#include <SDL2/SDL.h>
#include <glad/glad.h>

class StartScreen
{
public:
  int SCREEN_WIDTH = 800;
  int SCREEN_HEIGHT = 800;

private:
  static StartScreen *sInstance;
  SDL_GLContext context;
  static bool sInitialized;

  SDL_Window *window = nullptr;

public:
  static StartScreen *Instance()
  {
    if (sInstance == nullptr)
    {
      sInstance = new StartScreen();
    }

    return sInstance;
  };
  static void Release()
  {
    delete sInstance;
    sInstance = nullptr;

    sInitialized = false;
  };
  static bool Initialized()
  {
    return sInitialized;
  };

  void Render()
  {
    // SDL_GetWindowSize(window, &SCREEN_WIDTH, &SCREEN_HEIGHT);
    // glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glClearColor(250.0f / 255.0f, 119.0f / 255.0f, 110.0f / 255.0f, 1.0f);
    glClearDepth(1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    SDL_GL_SwapWindow(window);
  };

private:
  StartScreen()
  {
    sInitialized = Init();
  };
  ~StartScreen()
  {
    SDL_DestroyWindow(window);
    SDL_GL_DeleteContext(context);
    window = nullptr;
    SDL_Quit();
  };

  bool Init()
  {
    SDL_Log("%s", SDL_GetError());
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
      return false;
    }
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_Log("%s", SDL_GetError());
    SDL_Window *window = SDL_CreateWindow("Minecraft Clone",
                                          SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                          SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    SDL_Log("%s", SDL_GetError());
    if (window == NULL)
    {
      SDL_Log("Nao foi possivel criar a janela");
      return false;
    }

    context = SDL_GL_CreateContext(window);
    if (context == nullptr)
    {
      SDL_Log("Nao foi possivel inciar o contexto opengl");
    }

    SDL_Log("%s", SDL_GetError());
    if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
    {
      SDL_Log("Falha ao iniciar o glad");
      return false;
    }

    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    SDL_Log("%s", SDL_GetError());
    return true;
  };
};

StartScreen *StartScreen::sInstance = nullptr;
bool StartScreen::sInitialized = false;

class Manager
{
private:
  static Manager *sInstance;
  bool mQuit;
  StartScreen *mStart;

  SDL_Event mEvents;

public:
  static Manager *Instance()
  {
    if (sInstance == nullptr)
      sInstance = new Manager();
    SDL_Log("%s", SDL_GetError());
    return sInstance;
  };
  static void Release()
  {
    delete sInstance;
    sInstance = nullptr;
  };

  void Run()
  {
    while (!mQuit)
    {
      if (SDL_PollEvent(&mEvents))
      {
        if (mEvents.type == SDL_QUIT)
        {
          mQuit = true;
          return;
        }
      }
      mStart->Render();
      SDL_Log("%s", SDL_GetError());
    }
  };

private:
  Manager()
  {
    mQuit = false;
    mStart = StartScreen::Instance();
    SDL_Log("%s", SDL_GetError());
  };
  ~Manager()
  {
    Manager::Release();
    mStart = nullptr;
  };
};

Manager *Manager::sInstance = nullptr;

int SDL_main(int argc, char *argv[])
{
  Manager *game = Manager::Instance();
  game->Run();

  Manager::Release();
  game = nullptr;

  return 0;
}

【问题讨论】:

  • 单例模式的使用是您问题的相关部分吗?此外,单例非常像全局变量,因此不受欢迎。它们通常被认为是反模式。
  • 我认为您没有在编译时出现警告:将EXIT_FAILURE 作为bool 返回应该会引发警告。在任何情况下,它都会转换为true,这可能不是您想要的。使用异常,这样可以清楚地知道错误发生的地点和时间。
  • 顺便说一句:您缺少minimal reproducible example。确保您可以将您在此处发布的代码复制并粘贴到文件中并对其进行编译以产生与上述相同的结果。另外,复制'n'粘贴这些结果,不要转述。
  • 我找到了一种方法来编辑并将所有内容放在一起,并且在编译时给出相同的结果
  • 好的,这是一个开始:Manager::Release() 调用析构函数,而析构函数又调用Release()

标签: c++ sdl sdl-2 glad


【解决方案1】:

在渲染函数上,我只需要将引用 StartScreen 类的窗口的 SDL_GL_SwapWindow 引用 SDL_GL_SwapWindow(window) 更改为 SDL_GL_SwapWindow(SDL_GL_GetCurrentWindow())。我相信引用已经丢失,因为这个函数只是在其他类(Manager)中使用,所以这种方式在框架的实习生中是全局的

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 2010-11-09
    • 1970-01-01
    • 2015-12-21
    相关资源
    最近更新 更多