【问题标题】:OpenGL window with SDL not showing未显示 SDL 的 OpenGL 窗口
【发布时间】:2011-12-22 07:12:33
【问题描述】:

我正在使用 OpenGL/SDL 开发一个程序,但窗口不会绘制。窗口的条目出现在任务栏和 alt+tab 菜单中,但不显示缩略图。当我单击它时,它被标记为活动,但屏幕上没有任何变化。

我可以验证 glClear(GL_COLOR_BUFFER_BIT)SDL_GL_SwapBuffers() 正在从我的渲染循环中被调用,并且 SDL_SetVideoMode 正在成功,但它仍然不会渲染。这不是共享库问题,因为其他 SDL/GL 应用程序运行良好。

有什么想法吗?

编辑:

这是图形初始化:

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();
    }
}

【问题讨论】:

  • 特别是您的窗口创建和主循环。
  • 好的,我添加了主循环,渲染代码,渲染初始化

标签: c linux opengl graphics sdl


【解决方案1】:

打破它。做应该工作的(大部分是)最简单的事情:

#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 支票在您的系统上打印什么?

【讨论】:

    【解决方案2】:

    看起来您将每像素的位数设置为 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() 一次,以确保您没有检查返回的某些错误没有受到干扰。 p>

    在使用 OpenGL 时,SDL 可能会挑剔很多事情。我的下一个问题是您的代码流可能不止一次调用 get_surface...尝试向函数中添加静态变量,如下所示:

    static int has_init = 0;
    
    has_init++;
    if (has_init > 1) {
        // Well that's odd isn't it
    }
    

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多