2016-07-12 2 views
1
#include <iostream> 
#include <SDL2/SDL.h> 
#include <SDL2/SDL_opengl.h> 
#include <stdio.h> 
#include <OpenGL/gl.h> 
#include <string.h> 
using namespace std; 


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


bool SetOpenGLAttributes() 
{ 

    // SDL_GL_CONTEXT_CORE gives us only the newer version, deprecated functions are disabled 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 


    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 

    return true; 
} 



    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()); 
     } 
     else 
     { 
      //Create window 
      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()); 
      } 
      else 
      { 



       //creating new context 
       SDL_GL_CreateContext(window); 

       SetOpenGLAttributes(); 
       SDL_GL_SetSwapInterval(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(); 

       glFlush(); 

       SDL_GL_SwapWindow(window); 

       bool running = true; 
       while(running){ 
        glRotatef(1, 1, 0, 0); 
        glFlush(); 
        SDL_GL_SwapWindow(window); 
        SDL_Delay(100); 

       } 


      } 
     } 


     //Destroy window 
     //SDL_DestroyWindow(window); 

     //Quit SDL subsystems 
     //SDL_Quit(); 

     return 0; 
} 

Я изучаю openGL и SDL. Мне удалось отобразить этот «куб», но он просто выглядит как красный прямоугольник. Я хочу повернуть куб, чтобы убедиться, что мой код фактически создает куб, однако, когда я поворачиваюсь и затем меняю окна, куб только мерцает. Похоже, что второе окно буфера просто черное, но когда оно снова переключается, это всегда один и тот же красный прямоугольник. Почему я не могу повернуть мой куб и почему мое второе окно буфера черного?Почему мой экран мерцает при попытке повернуть этот куб?

ответ

3

Вы не можете просто нарисовать изображение, а затем сохранить вызова вращаться после этого и ожидать, что она вращается все, что вы ранее делали. Это не так, как это работает. OpenGL можно было заставить работать таким образом, но это не так.

Перед визуализацией части, которую вы сейчас рисуете, вам нужно вызвать функции преобразования (вращение, масштабирование, перевод); для сцен с несколькими объектами (думайте, что кубики 2+ все в разных местах и ​​перемещаются/вращаются независимо друг от друга), вы можете выполнить сброс-преобразование-draw-transform-draw-etc. Подумайте об этом, как будто вы перемещаете кисть, а не камеру, с которой вы фотографируете.

Таким образом, вы должны постоянно перерисовывать эту фигуру в каждом кадре (внутри вашей петли), и обычно вам следует переустанавливать представление на единицу матрицы каждый кадр перед рендерингом (или нажимать/поп-матрицы, если вам удобно с этим).

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 
+0

Как я могу это сделать в SDL или openGL? Если я повернусь, а затем снова нарисую куб, будет ли он автоматически рисоваться в неактивном буфере? Что вы понимаете, перезагрузившись в единую матрицу? Как мне это сделать? – user2905256

+0

@ user2905256 Я обновил его, чтобы уточнить лучше. Нет, вы никогда не обращаетесь к неактивному буферу. Вы нажимаете на активный, а затем меняете их, чтобы активный стал неактивным и неактивным становится активным. Хотя назвать его «неактивным» может быть обманом, если вы не понимаете, что происходит. Он все еще используется, просто не для рисования; он отображается на мониторе. – Aaron

+0

Что касается SDL, я не использую это или, по крайней мере, не недавно, поэтому я не могу много комментировать аспекты SDL. Однако, я думаю, ваша проблема связана с OpenGL. – Aaron

1
  • Очистить фреймбуфера & перерисовать кубе каждый раз через петлю while(running). Прямо сейчас вы просто чередуете фреймбуфер с кубиком в нем и пустым.
  • OpenGL isn't a scenegraph и т.д.
  • Не запрашивать Core context, если вы собираетесь использовать снятую функциональность как glBegin(). Не собирается работать.
  • Pump цикл событий с помощью SDL_PollEvent()/SDL_WaitEvent() держать OS счастливым

Все вместе:

#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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^