Окно OpenGL с SDL не отображается - PullRequest
2 голосов
/ 10 декабря 2011

Я работаю над программой с OpenGL / SDL, но окно не будет рисоваться. Запись окна появляется на панели задач и в меню alt + tab, но миниатюра не отображается. Когда я нажимаю на нее, она помечается как активная, но на экране ничего не меняется.

Я могу убедиться, что glClear(GL_COLOR_BUFFER_BIT) и SDL_GL_SwapBuffers() вызываются из моего цикла рендеринга, и что SDL_SetVideoMode успешно выполняется, но он все равно не будет рендериться. Это не проблема общей библиотеки, так как другие приложения SDL / GL работают нормально.

Есть идеи?

EDIT:

Вот графическая инициализация:

void GraphicsManager::initGraphics() {
    // Access prefs
    PreferencesManager* prefMgr = PreferencesManager::getInstance();
    int width = prefMgr->getIntKey("res_width");
    int height = prefMgr->getIntKey("res_height");

    if(SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
        fprintf(stderr, "Cannot initialize SDL video!\n");
        exit(1);
    }

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);

    m_screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL);
    if(!m_screen) {
        fprintf(stderr, "Error: Invalid screen pointer\n");
        exit(2);
    }

    SDL_ShowCursor(SDL_DISABLE);

    // Setup OpenGL stuffs
    glDisable(GL_DEPTH_TEST); // We're only using 2D
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glViewport(0.0, 0.0, width, height);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, width, height, 0.0, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_TEXTURE_2D);
    glClear(GL_COLOR_BUFFER_BIT);
    SDL_GL_SwapBuffers();

    // Init FPS stuff
    m_avgFps = 60.0f;
    m_lastUpdate = SDL_GetTicks();
}

Вот мой основной цикл:

while(stateMgr->getState() != GS_QUIT) {
    // Process input events
    inputMgr->processEvents();

    // Update the current system mode
    stateMgr->update();

    // Update GUI state
    guiMgr->update();

    // Render
    gfxMgr->render();
    //char buf[16];
    //snprintf(buf, 16, "FPS: %4.2f", gfxMgr->getFramerate());
    //testWindow->getChild("TestRoot/Framerate")->setText(buf);
    SDL_Delay(10);
}

А вот функция рендеринга:

void GraphicsManager::render() {
    std::list<IRenderCallback*>::iterator rci;

    // Clear the screen
    glClear(GL_COLOR_BUFFER_BIT);

    // Run render callbacks
    /*for(rci=m_renderCallbacks.begin();rci != m_renderCallbacks.end();rci++) {
        (*rci)->preRender();
    }

    // Iterate through all renderables and render them
    std::list<Renderable*>::iterator i;
    for(i=m_renderables.begin();i != m_renderables.end();i++) {
        (*i)->render();
    }

    // Run render callbacks
    for(rci=m_renderCallbacks.begin();rci != m_renderCallbacks.end();rci++) {
        (*rci)->preFlip();
    }*/

    // Flip the buffers
    SDL_GL_SwapBuffers();

    // Update FPS stuff
    Uint32 now = SDL_GetTicks();
    Uint32 timeTaken = now - m_lastUpdate;
    m_lastUpdate = now;
    double seconds = (double)timeTaken / 1000.0f;
    m_avgFps = (1.0f / seconds);

    // Run render callbacks
    for(rci=m_renderCallbacks.begin();rci != m_renderCallbacks.end();rci++) {
        (*rci)->postRender();
    }
}

Ответы [ 2 ]

1 голос
/ 22 декабря 2011

Похоже, вы устанавливаете свои биты на пиксель равными 0.

m_screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL);

Обычно я думаю, что вы хотите 32 в вашем случае.

С учетом сказанного, если это не 'Чтобы решить вашу проблему, попробуйте позвонить:

m_screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL | SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER);

Это потребует аппаратной поверхности и двойной буферизации.

Я также не видел, чтобы вы звонили так:

glViewport(0, 0, width, height);

перед вашим первым вызовом glLoadIdentity.Возможно, вы делали это раньше - однако SDL_SetVideoMode может привести к сбросу контекста GL, что делает целесообразным переустановить все необходимые параметры OpenGL.

Есть еще одна проблема,тем не мение.Мы сосредоточены на вашем коде GL, но возможно SDL был испорчен до (или после) инициализации этой подсистемы. Я хотел бы предложить вам один раз вызвать SDL_GetError () перед входом в основной цикл, просто чтобы убедиться, что какая-то ошибка, которую вы не проверяли на обратном пути, не помешала.

Есть много других вещей, с которыми SDL может быть придирчив при использовании OpenGL.Моя следующая проблема заключается в том, что ваш поток кода может вызывать get_surface более одного раза ... попробуйте добавить статическую переменную в функцию следующим образом:

static int has_init = 0;

has_init++;
if (has_init > 1) {
    // Well that's odd isn't it
}
1 голос
/ 16 декабря 2011

Разбей это. Сделайте (в основном-иш) простейшую вещь, которая должна работать:

#include <SDL.h>
#include <SDL_opengl.h>
#include <cstdio>
#include <iostream>

using namespace std;

int main( int argc, char** argv )
{
    if(SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
        fprintf(stderr, "Cannot initialize SDL video!\n");
        exit(1);
    }

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);

    int width = 640;
    int height = 480;

    SDL_Surface* m_screen = SDL_SetVideoMode(width, height, 0, SDL_OPENGL);
    if(!m_screen) {
        fprintf(stderr, "Error: Invalid screen pointer\n");
        exit(2);
    }

    cout << "GL_VERSION  : " << glGetString(GL_VERSION) << endl;
    cout << "GL_VENDOR   : " << glGetString(GL_VENDOR) << endl;
    cout << "GL_RENDERER : " << glGetString(GL_RENDERER) << endl;

    SDL_ShowCursor(SDL_DISABLE);

    // Setup OpenGL stuffs
    glDisable(GL_DEPTH_TEST); // We're only using 2D
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glViewport(0.0, 0.0, width, height);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, width, height, 0.0, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //glEnable(GL_TEXTURE_2D);
    glClear(GL_COLOR_BUFFER_BIT);
    SDL_GL_SwapBuffers();

    float angle = 0;
    bool running = true;
    while( running )
    {
        // handle all pending events
        SDL_Event event;
        while( SDL_PollEvent(&event) )
        {
            switch (event.type)
            {
            case SDL_QUIT:  
                running = false; 
                break;
            default:        
                break;
            }
        }

        angle += 1;
        while( angle > 360 )
            angle -= 360;

        // Render
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glPushMatrix();
        glTranslatef( width/2, height/2, 0 );
        glScalef( 150, 150, 0 );

        glRotatef( angle, 0, 0, 1 );
        glColor3ub(255,0,0);
        glBegin(GL_TRIANGLES);
        glVertex2i(0,0);
        glVertex2i(1,0);
        glVertex2i(1,1);
        glEnd();

        glPopMatrix();

        // Flip the buffers
        SDL_GL_SwapBuffers();

        SDL_Delay(10);
    }

    SDL_Quit();
    return 0;
}

Если это работает, все, что вам нужно сделать (ха!), Это выяснить, чем отличается простой процесс выполнения программы от вашей большой программы. Если это не работает, ваша среда, вероятно, как-то глупа.

Что печатает чеки GL_VERSION/VENDOR/RENDERER в вашей системе?

...