2012-12-11 13 views
7

sto sperimentando con la nuova versione beta SDL2 e un contesto OpenGL3, e sto avendo un problema strano:SDL2 OpenGL3 Come inizializzare SDL all'interno di una funzione

Se faccio funzionare il codice di inizializzazione SDL nel mio principale (), funziona, ma voglio avere questo codice in una funzione init_sdl() separata.

Se inserisco il codice di inizializzazione in una funzione init_sdl() separata e richiama questa funzione da main(), il colore di sfondo non viene mai disegnato e il programma inizia a consumare follemente tutte le risorse del mio sistema.

Qualcuno potrebbe indicarmi un esempio funzionante in cui SDL è inizializzato in una funzione separata? Non riesco a trovarne uno ... Forse non è possibile? Penso che mi ricordo vagamente di avere un problema simile con SDL 1.2, ma sono passati alcuni anni da quando l'ho usato, e non penso di aver mai trovato una soluzione. In realtà, questo potrebbe essere il motivo per cui ho scelto di passare a utilizzare SFML.

Voglio davvero usare SDL2 invece di SFML perché funziona su più piattaforme, ma non essere in grado di separare le cose in piccole funzioni è un rompicapo per me. Questo dovrebbe essere facile, mi manca qualcosa di ovvio?

Edit:

Questo funziona:

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

Questo non funziona:

#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; 
} 
+1

[SSCCE] (http://sscce.org/) tempo. – genpfault

+0

Ho aggiunto esempi di codice – Defcronyke

risposta

3
void init_sdl(SDL_Window* sdl2_window, SDL_GLContext& opengl3_context) 

Il tuo primo argomento dovrebbe essere un riferimento troppo. Altrimenti, quando torni a main()sdl2_window è ancora zero.

+0

Grazie! Quindi un riferimento al puntatore, eh? Non mi rendevo conto che c'era una differenza tra un puntatore e un riferimento di puntatore. – Defcronyke

+0

Nessun problema! Questo è il motivo per cui mi piacciono gli SSCCE :) – genpfault

+1

@Defcronyke, quando si invia una variabile (a una funzione) in base al valore, si copia il suo contenuto e le funzioni non avranno alcun modo per modificare tale variabile. Se quella variabile sembra essere un puntatore, è la stessa cosa. Stai passando il puntatore "by-value", che significa che "init_sdl" ha un indirizzo (che può cambiare dove punta), ma non può cambiare la variabile originale che contiene quell'indirizzo. Ecco perché è necessario inviarlo per riferimento, in modo da poter cambiare il puntatore stesso. – Shahbaz

0

Sei sicuro contesto non è la colpa:

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); 
Problemi correlati