C++ OpenGL SDL 屏幕问题

Posted

技术标签:

【中文标题】C++ OpenGL SDL 屏幕问题【英文标题】:C++ OpenGL SDL Screen Trouble 【发布时间】:2011-10-07 23:30:56 【问题描述】:

我又回来了,可能是我在进行 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();


非常感谢~迈克尔

【问题讨论】:

【参考方案1】:

尽管设置了清除颜色,但您并没有清除屏幕。你需要一个像 glClear(GL_COLOR_BUFFER_BIT); 这样的电话。实际进行清理。

另外,如果你想做静态绘图以外的任何事情,最好在循环内部连续渲染......你可能什么都看不到,因为它希望你在考虑到这一点的情况下进行双缓冲绘图,并且需要您交换缓冲区才能在屏幕上查看结果。通常,这是在所有绘制调用完成后每次通过循环完成的。我相信你可以通过SDL_GL_SwapBuffers 做到这一点

【讨论】:

啊,谢谢!我完全忘记了这些功能的存在......回到我的绘图板! 我很高兴能够帮助解决这个问题。 OpenGL 可能会令人困惑 - 添加 SDL 层,它变得更加混乱......【参考方案2】:

您在对glClearColor 的调用中为 alpha 传递了 0。试试“1”。

这使整个屏幕透明。不过,我没想到它会真正起作用,很高兴知道。 :)

【讨论】:

我改了,还是没有屏幕。运行它后,我想知道这是否可能是问题:进程以状态-1073741510(0分钟15秒)终止。我相当肯定 while 循环不会有问题,但可能吗? 为此,您需要获取带有 Alpha 通道和合成窗口管理器的帧缓冲区配置。【参考方案3】:
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

SDL_Event event;

int main (int argc, char **argv)

    bool quit = false;

您真的应该在这里调用 SDL_Init,而不是将其委托给某个 init 函数。否则,当 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 次迭代之间耗尽最大矩阵堆栈深度(更可能在较小的数字上)。


【讨论】:

感谢您的回复。别担心,我知道我错过了视口,而且我知道如果没有 glPopMatrix,在名为“draw_square”的函数末尾有 glPushMatrix 是不好的。我只是在这个程序中玩耍和测试。感谢您对循环内绘图的解释,这有助于我的理解。我需要额外的事件处理程序吗? SDL 提供“窗口事件”wiki.libsdl.org/moin.cgi/SDL_WindowEvent 绘图应该发生以响应 SDL_WINDOWEVENT_EXPOSED

以上是关于C++ OpenGL SDL 屏幕问题的主要内容,如果未能解决你的问题,请参考以下文章

我的 C++ OpenGL SDL 程序没有按预期工作

c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?

OpenGL C++ SDL 2D 阴影

C++ - SDL/OpenGL 加载图像的颜色被反转

将 SDL 示例移植到 OpenGL 和 C++

C++ OpenGL/SDL 2.0 无法加载纹理