C++ OpenGL SDL屏幕问题

3
我又回来了,这次需要解决一个小问题。在我的OpenGL/SDL之旅中,我似乎无法解决它。

这个程序会出现一个640x480像素的SDL屏幕,但是里面什么都没有,甚至没有背景,它只是透明的呈现出屏幕后面的内容。我不确定为什么会这样,可能是因为又犯了一个愚蠢的错误。

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

SDL_Event event;

int main (int argc, char **argv)

{

bool quit = false;

init();
draw_square(0,0,0);

while (quit == false)

    {

        if( event.type == SDL_QUIT )

            {

                quit = true;

            }

    }

SDL_Quit();

return 0;

}

void init ()

{

SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(640,480,32,SDL_OPENGL);
SDL_WM_SetCaption( "OpenGL Test", NULL );

glClearColor( 0, 0, 0, 0 );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0, 0 , 640 , 480, 0, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

}

void draw_square (int x, int y, int z)

{

glTranslatef(x,y,z);

glColor4f(1.0,1.0,1.0,1.0);

glBegin(GL_QUADS);

    glVertex3f(0, 0 ,0);
    glVertex3f(50,0 ,0);
    glVertex3f(50,50,0);
    glVertex3f(0, 50,0);

glEnd();

glPushMatrix();

}

非常感谢~ Michael

3个回答

4
您没有清除屏幕,尽管设置了清除颜色。您需要调用类似于glClear(GL_COLOR_BUFFER_BIT)的函数来实际清除。

此外,如果您想执行除静态绘图之外的任何操作,则最好在循环内持续进行渲染...这可能是因为它希望您以双缓冲绘图的方式处理并需要您交换缓冲区才能在屏幕上看到结果。通常,在完成所有绘制调用后每次通过循环进行此操作。我相信您可以使用SDL_GL_SwapBuffers实现此操作。


啊,谢谢!我完全忘记了这些函数的存在... 对我来说重新开始吧! - user969416
我很高兴能够帮助解决这个问题。OpenGL 可能会让人感到困惑 - 再加上 SDL 层,它就变得更加令人困惑了... - jheriko

0
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

SDL_Event event;

int main (int argc, char **argv)
{
    bool quit = false;

你应该在这里真正调用SDL_Init,而不是将其委托给某个初始化函数。否则,某人(可能是你自己)可能会更改init的调用时间并破坏你的程序。实际上,你的主函数就是你的初始化函数。窗口创建应该发生在一个名为create_window或类似名称的函数中。
    init();

从技术上讲,在事件循环之外调用draw_square或任何绘图函数都会引起麻烦。你看到的效果:如果窗口被暴露(最初显示),但任何通知程序需要更新内容的事件,因为它们被覆盖了,都没有效果。始终从事件循环内部调用绘图函数。对于静态绘制以响应绘制事件,对于动画场景则在空闲部分中进行。
    draw_square(0,0,0);

    while (quit == false) {
        if( event.type == SDL_QUIT ) {
            quit = true;
        }
    }

    SDL_Quit();

    return 0;
}

void init ()    
{

    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_SetVideoMode(640,480,32,SDL_OPENGL);
    SDL_WM_SetCaption( "OpenGL Test", NULL );

这是最常见的新手误解,即OpenGL已经“初始化”。以下调用旨在用于场景设置,即在绘图函数开始时。

您还缺少:

  • 设置视口
  • 实际清除场景(glClearColor仅告诉要清除到哪种颜色,在实际清除调用时;从技术上讲,它只是设置了一些“寄存器”,但不执行)。

因此,这些不应在此处调用

    glClearColor( 0, 0, 0, 0 );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( 0, 0 , 640 , 480, 0, 1 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

void draw_square (int x, int y, int z) {

    glTranslatef(x,y,z);

    glColor4f(1.0,1.0,1.0,1.0);

    glBegin(GL_QUADS);

        glVertex3f(0, 0 ,0);
        glVertex3f(50,0 ,0);
        glVertex3f(50,50,0);
        glVertex3f(0, 50,0);

    glEnd();

下一行是一个很大的WTF?!
    glPushMatrix();

每个矩阵堆栈推送操作都必须与一个弹出操作(glPopMatrix)相平衡。然而,仅在进行一些变换后才推送矩阵是有意义的。但实际上并没有进行任何变换。如果您在循环中调用draw_square函数,则会在32到128次迭代之间耗尽最大矩阵堆栈深度(更可能是较低的数字)。
}

谢谢您的回复。不用担心,我知道我缺少视口,并且我知道在名为“draw_square”的函数末尾放置glPushMatrix是不好的,没有glPopMatrix。我只是在这个程序中进行试验和测试。感谢您对循环内绘图的解释,这有助于我的理解。但我还需要额外的事件处理程序吗? - user969416
SDL 提供了"窗口事件" http://wiki.libsdl.org/moin.cgi/SDL_WindowEvent 绘制应在响应 SDL_WINDOWEVENT_EXPOSED 时发生。 - datenwolf

0

在调用glClearColor时,您将alpha设置为0。请尝试使用“1”。

这会使整个屏幕变成透明的。我其实没想到它真的能工作,所以这是个好消息。 :)


我已经修改了代码,但仍然没有屏幕输出。运行后,我想知道这是否是问题所在:进程以状态-1073741510(0分钟,15秒)终止。我相当确定while循环不会有问题,但它可能是问题的原因吗? - user969416
为了使其正常工作,您需要获取一个带有alpha通道和合成窗口管理器的帧缓冲配置。 - datenwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接