为什么在尝试旋转此立方体时屏幕会闪烁?

时间:2016-07-12 16:29:04

标签: c++ opengl sdl

undefined method `object_desc_link' for #<MyService:0x007f8cb3584840>

我正在学习openGL和SDL。我设法得到了这个&#34; cube&#34;显示,但它看起来像一个红色矩形。我想旋转立方体以确保我的代码实际上是制作一个立方体,但是当我旋转然后交换窗口时,立方体只会闪烁。看起来第二个缓冲区窗口只是黑色,但是当它再次切换时,它总是相同的红色矩形。为什么我不能旋转我的立方体,为什么我的第二个缓冲区窗口变黑?

2 个答案:

答案 0 :(得分:3)

你不能只绘制一个图像,然后继续调用旋转,并期望它旋转你之前渲染的所有内容。这不是它的工作原理。 OpenGL本来可以这样工作,但事实并非如此。

在渲染当前绘制的零件之前,需要调用变换函数(旋转,缩放,平移);对于多物体场景(想想所有在不同位置的2个立方体以及彼此独立地移动/旋转),您将重置 - 变换 - 绘制 - 变换 - 绘制等。可以把它想象成你正在移动画笔,而不是你拍摄照片的相机。

所以你应该在每一帧(你的循环内)中不断重新绘制这个形状,并且通常你应该在渲染之前将每个帧的视图重置为单位矩阵(或者如果你对它感到满意则推/弹矩阵)

main loop:
    reset view
    render
    swap buffers

至于双缓冲......

每当你画画时,你都在画一个缓冲区。您不绘制到两个缓冲区,一次绘制到一个缓冲区。如果您是双重(或更多)缓冲,则在完全渲染图像后交换缓冲区。您正在绘制的图像将交换到显示在显示器上的管道中,之前显示在显示器上的图像现在是您图像下一帧的绘图空间。现在画上那个(可能在绘制之前首先删除它上面的所有东西,这是glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);的用途),当你完成绘制下一帧时,你再次交换它们。这就是你正在做(或应该做)循环。你一次只能绘制一张图像,但是你一直在绘图,交换(在另一张图纸上绘图),绘图,交换,绘图,交换等。

关于重置矩阵,请尝试glLoadIdentity();。请查看有关glLoadIdentity和矩阵模式here的问题,以便进一步阅读。在这里的特定实例中,只需在每个循环开始时调用glLoadIdentity即可,但如果您打算进一步了解此主题,则应掌握投影模式。

至于在你的情况下使用glLoadIdentity,请记住我说你应该继续旋转循环的每个实例,每一帧?请记住,循环的每次迭代通常都会绘制图像,使其在动画的该帧中看起来如何。在帧之间,您实际上是在重置以绘制新图片,即下一帧。想象glLoadIdentity就像艺术家把手放回自己重新开始。如果你每帧继续旋转,它会越来越多地旋转。与缩放和翻译相同。现在我考虑一下,对于你的具体情况,你可能真的想要它,但一般情况下你不这样做。例如,如果你继续进行转换为(1,2,0)和旋转(0.5,0.5,0),那么“画笔”将继续移动并旋转每一帧,你很少得到你的结果期待着。

关于“重置”事物的另一个注意事项:有时您可能需要在重新绘制图片的过程中“重置”。例如,绘制两个彼此无关的对象,在绘制第一个对象之后,你可能会glLoadIdentity重置一些东西,这样你就可以“在你的手前把你的画笔拿回来”。同一个缓冲区上的第二个对象。或者你可以glClear重置深度缓冲区,如果你需要一个效果,其中一个对象总是被绘制在另一个对象之上而不管距离。

查看旋转立方体here的具体示例。

以下示例中的片段 - 注意它是如何从一些“重置视图”类型代码开始的(有时你需要更多,取决于你正在做什么),然后转换(包括几个旋转),然后渲染,然后增加一个保持角度的变量来绘制旋转中使用的立方体。

另请注意,在示例中,代码段只是函数体,但可以是主循环中调用的函数,或者函数体可以直接用作循环体。

// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

glTranslatef(0.0f, 0.0f,-7.0f); // Translate Into The Screen 7.0 Units
glRotatef(rotqube,0.0f,1.0f,0.0f);  // Rotate The cube around the Y axis
glRotatef(rotqube,1.0f,1.0f,1.0f);
glBegin(GL_QUADS);      // Draw The Cube Using quads
glColor3f(0.0f,1.0f,0.0f);  // Color Blue
glVertex3f( 1.0f, 1.0f,-1.0f);  // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f,-1.0f);  // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f);  // Bottom Left Of The Quad (Top)
glVertex3f( 1.0f, 1.0f, 1.0f);  // Bottom Right Of The Quad (Top)
glColor3f(1.0f,0.5f,0.0f);  // Color Orange
glVertex3f( 1.0f,-1.0f, 1.0f);  // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f, 1.0f);  // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f,-1.0f);  // Bottom Left Of The Quad (Bottom)
glVertex3f( 1.0f,-1.0f,-1.0f);  // Bottom Right Of The Quad (Bottom)
glColor3f(1.0f,0.0f,0.0f);  // Color Red    
glVertex3f( 1.0f, 1.0f, 1.0f);  // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f);  // Top Left Of The Quad (Front)
glVertex3f(-1.0f,-1.0f, 1.0f);  // Bottom Left Of The Quad (Front)
glVertex3f( 1.0f,-1.0f, 1.0f);  // Bottom Right Of The Quad (Front)
glColor3f(1.0f,1.0f,0.0f);  // Color Yellow
glVertex3f( 1.0f,-1.0f,-1.0f);  // Top Right Of The Quad (Back)
glVertex3f(-1.0f,-1.0f,-1.0f);  // Top Left Of The Quad (Back)
glVertex3f(-1.0f, 1.0f,-1.0f);  // Bottom Left Of The Quad (Back)
glVertex3f( 1.0f, 1.0f,-1.0f);  // Bottom Right Of The Quad (Back)
glColor3f(0.0f,0.0f,1.0f);  // Color Blue
glVertex3f(-1.0f, 1.0f, 1.0f);  // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f,-1.0f);  // Top Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f,-1.0f);  // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f, 1.0f);  // Bottom Right Of The Quad (Left)
glColor3f(1.0f,0.0f,1.0f);  // Color Violet
glVertex3f( 1.0f, 1.0f,-1.0f);  // Top Right Of The Quad (Right)
glVertex3f( 1.0f, 1.0f, 1.0f);  // Top Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f, 1.0f);  // Bottom Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f,-1.0f);  // Bottom Right Of The Quad (Right)
glEnd();            // End Drawing The Cube

rotqube +=0.9f;         // Increase Angle

答案 1 :(得分:1)

  • 清除帧缓冲区&amp;每次通过while(running)循环重新绘制多维数据集。 现在你只需要在帧缓冲区和你的立方体之间交替使用它和空白帧。
  • OpenGL isn't a scenegraph
  • 如果您要使用glBegin()等删除功能,请不要申请Core context。不能上班。
  • 使用SDL_PollEvent() / SDL_WaitEvent()抽取事件循环以保持操作系统满意

所有在一起:

#include <cstdio>
#include <cstdlib>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

int main( int argc, char* args[] )
{
    SDL_Window* window = NULL;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        return EXIT_FAILURE;
    }

    //Create window
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    window = SDL_CreateWindow
        (
        "SDL Tutorial",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH, SCREEN_HEIGHT,
        SDL_WINDOW_OPENGL
        );
    if( window == NULL )
    {
        printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        return EXIT_FAILURE;
    }

    //creating new context
    SDL_GLContext ctx = SDL_GL_CreateContext(window);
    SDL_GL_SetSwapInterval(1);

    bool running = true;
    while( running )
    {
        SDL_Event ev;
        while( SDL_PollEvent( &ev ) )
        {
            if( ( SDL_QUIT == ev.type ) ||
                ( SDL_KEYDOWN == ev.type && SDLK_ESCAPE == ev.key.keysym.sym ) )
            {
                running = false;
                break;
            }
        }

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();

        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        static float angle = 0.0f;
        angle += 1;
        glRotatef( angle, 0.2, 0.3, 0.1 );

        //cube front
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(-.5, .5, -.5);
        glVertex3f(.5, .5, -.5);
        glVertex3f(.5, -.5, -.5);
        glVertex3f(-.5, -.5, -.5);
        glEnd();

        //cube top
        glBegin(GL_POLYGON);
        glColor3f(1.0,0.0,0.0);
        glVertex3f(-.5,.5,-.5);
        glVertex3f(.5, .5, -.5);
        glVertex3f(.5, .5, .5);
        glVertex3f(-.5, .5, .5);
        glEnd();

        //cube bottom
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(-.5,-.5,-.5);
        glVertex3f(.5, -.5, -.5);
        glVertex3f(.5, -.5, .5);
        glVertex3f(-.5, -.5, .5);
        glEnd();

        //cube right
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(.5, -.5, -.5);
        glVertex3f(.5, -.5, .5);
        glVertex3f(.5, .5, .5);
        glVertex3f(.5, .5, -.5);
        glEnd();

        //cube left
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(-.5, -.5, -.5);
        glVertex3f(-.5, .5, -.5);
        glVertex3f(-.5, .5, .5);
        glVertex3f(-.5, -.5, .5);
        glEnd();

        //cube back
        glBegin(GL_POLYGON);
        glColor3f(1.0, 0.0, 0.0);
        glVertex3f(-.5, .5, .5);
        glVertex3f(-.5, -.5, .5);
        glVertex3f(.5, -.5, .5);
        glVertex3f(.5, .5, .5);
        glEnd();

        SDL_GL_SwapWindow(window);
        SDL_Delay( 16 );
    }

    SDL_GL_DeleteContext(ctx);
    SDL_DestroyWindow( window );
    SDL_Quit();

    return 0;
}