【问题标题】:SDL2 OpenGL3 How to initialize SDL inside a functionSDL2 OpenGL3 如何在函数内初始化 SDL
【发布时间】:2012-12-11 18:22:19
【问题描述】:

我正在试验新的 SDL2 测试版和 OpenGL3 上下文,但遇到了一个奇怪的问题:

如果我在 main() 函数中运行 SDL 初始化代码,它可以正常工作,但我希望将此代码放在单独的 init_sdl() 函数中。

如果我把初始化代码放在一个单独的init_sdl()函数中,然后从main()中调用这个函数,背景色就永远画不出来,程序开始疯狂消耗我系统的所有资源。

有人能指出一个在单独函数中初始化 SDL 的工作示例吗?我似乎找不到...也许这是不可能的?我想我隐约记得 SDL 1.2 也有类似的问题,但自从我使用它已经有几年了,我想我还没有找到解决方案。事实上,这可能是我选择改用 SFML 的原因。

我真的很想使用 SDL2 而不是 SFML,因为它可以在更多平台上运行,但不能将事物分成小函数对我来说是个大问题。这应该很容易,我是否遗漏了一些明显的东西?

编辑:

这行得通:

#include <iostream>
#include <GL/glew.h>
#include <SDL.h>
#define PROGRAM_NAME "SDL2 OpenGL3 Example"

int main(int argc, char** argv)
{
    SDL_Window* sdl2_window = 0;
    SDL_GLContext opengl3_context;

    SDL_Init(SDL_INIT_VIDEO);

    // set the opengl context version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    // turn on double buffering set the depth buffer to 24 bits
    // you may need to change this to 16 or 32 for your system
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    // create the sdl2 window
    sdl2_window = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED,
            SDL_WINDOWPOS_CENTERED, 512, 512,
            SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    // create the opengl3 context
    opengl3_context = SDL_GL_CreateContext(sdl2_window);

    GLenum status = glewInit();
    if (status != GLEW_OK)
    {
        std::cerr << "GLEW Error: " << glewGetErrorString(status) << "\n";
        exit(1);
    }

    // sync buffer swap with monitor's vertical refresh rate
    SDL_GL_SetSwapInterval(1);

    // set background color
    glClearColor( 1.0, 0.0, 0.0, 1.0 );

    while (true)
    {
        int status = 0;

        glClear( GL_COLOR_BUFFER_BIT );

        SDL_GL_SwapWindow(sdl2_window);

        SDL_Event event;

        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_KEYDOWN:
                break;
            case SDL_KEYUP:
                // if escape is pressed, quit
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    status = 1; // set status to 1 to exit main loop
                break;
            case SDL_QUIT:
                status = 1;
                break;
            }
        }

        if (status == 1) // if received instruction to quit
            break;
    }

    // delete opengl3 context, destroy sdl2 window, and shut down sdl subsystems
    SDL_GL_DeleteContext(opengl3_context);
    SDL_DestroyWindow(sdl2_window);
    SDL_Quit();

    return 0;
}

这不起作用:

#include <iostream>
#include <GL/glew.h>
#include <SDL.h>
#define PROGRAM_NAME "SDL2 OpenGL3 Example"

void init_sdl(SDL_Window* sdl2_window, SDL_GLContext& opengl3_context)
{
    SDL_Init(SDL_INIT_VIDEO);

    // set the opengl context version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    // turn on double buffering set the depth buffer to 24 bits
    // you may need to change this to 16 or 32 for your system
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    // create the sdl2 window
    sdl2_window = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED,
            SDL_WINDOWPOS_CENTERED, 512, 512,
            SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);

    // create the opengl3 context
    opengl3_context = SDL_GL_CreateContext(sdl2_window);
}

int main(int argc, char** argv)
{
    SDL_Window* sdl2_window = 0;
    SDL_GLContext opengl3_context;

    init_sdl(sdl2_window, opengl3_context);

    GLenum status = glewInit();
    if (status != GLEW_OK)
    {
        std::cerr << "GLEW Error: " << glewGetErrorString(status) << "\n";
        exit(1);
    }

    // sync buffer swap with monitor's vertical refresh rate
    SDL_GL_SetSwapInterval(1);

    // set background color
    glClearColor( 1.0, 0.0, 0.0, 1.0 );

    while (true)
    {
        int status = 0;

        glClear( GL_COLOR_BUFFER_BIT );

        SDL_GL_SwapWindow(sdl2_window);

        SDL_Event event;

        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_KEYDOWN:
                break;
            case SDL_KEYUP:
                // if escape is pressed, quit
                if (event.key.keysym.sym == SDLK_ESCAPE)
                    status = 1; // set status to 1 to exit main loop
                break;
            case SDL_QUIT:
                status = 1;
                break;
            }
        }

        if (status == 1) // if received instruction to quit
            break;
    }

    // delete opengl3 context, destroy sdl2 window, and shut down sdl subsystems
    SDL_GL_DeleteContext(opengl3_context);
    SDL_DestroyWindow(sdl2_window);
    SDL_Quit();

    return 0;
}

【问题讨论】:

标签: c++ opengl sdl sdl-2 opengl-3


【解决方案1】:
void init_sdl(SDL_Window* sdl2_window, SDL_GLContext& opengl3_context)

你的第一个参数也应该是一个参考。否则当你回到main()sdl2_window 仍然为零。

【讨论】:

  • 谢谢!所以一个指针引用,嗯?我没有意识到指针和指针引用之间有区别。
  • 没问题!这就是我喜欢 SSCCE 的原因 :)
  • @Defcronyke,当您按值发送变量(到函数)时,您复制其内容并且函数将无法更改该变量。如果该变量恰好是一个指针,那也是一样的。您正在“按值”传递指针,这意味着 init_sdl 有一个地址(它可以更改它指向的位置),但不能更改保存该地址的原始变量。这就是为什么您需要通过引用发送它,这样您就可以更改指针本身。
  • 感谢 Shahbaz 的澄清。我原以为拥有一条数据的地址就是写入该地址所需的全部内容,但是如果我理解您的意思,则传递给指针的函数只能读取在该地址找到的数据。
  • 我刚才说的好像不太对,这里解释的很好:markgodwin.blogspot.ca/2009/08/c-reference-to-pointer.html根据那篇博文,当指针按值传递给函数时,可以修改找到的数据在指针的地址,但你不能改变它指向的地址,因为你实际上只是改变了指针的本地副本指向的地址。
【解决方案2】:

你确定上下文没有错吗:

int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_SHOWN;
win = SDL_CreateWindow("3Doodle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 768, flags);
SDL_assert(win != NULL);

context = SDL_GL_CreateContext(win);
SDL_assert(context != NULL);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 2022-01-26
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多