2014-11-18 2 views
0

현재 Windows에서 OpenGL, SDL2 및 GLEW를 사용하여 특정 주파수에서 사각형이 깜박이도록하려고합니다. 내가 직면하고있는 문제들은 내가 미친 짓을하게 만든다. 왜냐하면 내가 알 수 없기 때문에 내가 잘못하고있는 것을 - 나는 아직도 OpenGL 멍청이다.특정 주파수에서 사각형 깜박임/깜박임을 내 보냅니다.

내가 가진 문제는 특정 주파수에서 (모든 주파수가 화면 주사율보다 분명히 낮음) 사각형 깜박임이 "비틀어지기"시작하여 빈 화면이나 빈 화면이 여러 개있는 프레임에 반복 된 정지 이미지가 발생하기 때문입니다. 사각형을 볼 수 있습니다. 간단히 말해서, 나는 오랜 기간 동안 일정한 주파수에서 주기적으로 깜빡 거리지 않는다. 문제는 빈도가 증가함에 따라 크게 두드러집니다.

내가 시도한 것은 VSync를 활성화/비활성화하고 SDL을 사용하여 FPS를 수동으로 제한하며 다른 타이머 구현을 사용하는 것이 었습니다. 나는 또한 FPS를 측정했습니다. 제한적으로 FPS를 무제한으로 사용하면 가끔 + -1 지터로 일정한 60 FPS에 도달 할 때> 3000 FPS가됩니다. 나는이 문제의 이유가 정말로 타이밍 문제인지 또는 OpenGL에서 뭔가 잘못하고 있는지 확실하지 않습니다.

응축 된 코드가 아래에 있습니다 (오류 검사를 제거했지만 오류가 없음). 또한 변수를 변경하려고 시도한 주석을 일부 작성했습니다.

SDL_Init(SDL_INIT_EVERYTHING); 
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
_window = SDL_CreateWindow(...); 
SDL_GLContext glContext = SDL_GL_CreateContext(_window); 
GLenum error = glewInit(); 
SDL_GL_SetSwapInterval(1); //For vsync 
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 
_rect.init(-0.5,-0.5, 1.0f, 1.0f); 

내 게임 루프는 다음과 같이보고한다 :

while (1) 
{ 
    logic();  // process game logic 
    processInput(); // process input using sdl 
    drawGame();  // draw the game on screen 
} 

drawGame() 함수는 하나 개의 프레임을 그리기까지의 시간을 측정

내 시스템을 초기화하는 방법은 다음과 같다 다음 프레임, 그래서 사각형을 적절하게 전환 할 수 있습니다. 60Hz의의 화면 새로 고침 속도를 가정하고, 손떨림 :

void drawGame() 
{ 
    /* some declarations and initialization calls */ 
    double freq = 20; // frequency in hertz 
    double interval = 1.0/(2.0*freq)*1000.0; // half of the interval in ms, 
              // determines when to toggle 

    delta = SDL_GetTicks() - tick; // measurement of time delta 
    tick = SDL_GetTicks(); 

    delta_acc += delta; // accumulate the measurements 
    if (delta_acc > interval) 
    { 
     act = !act; 
     delta_acc = 0; // I've also tried delta_acc-=interval here to account for slightly 
         // overdue toggling, but it didn't help 
    } 

    // Now the actual rendering 
    glClearDepth(1.0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    if (act) _rect.draw(); 
    glFinish();     // Tried with and without glFinish(); 
    SDL_GL_SwapWindow(_window); 
} 

_rect 객체는 기본적으로이 샘플링 문제 같은 소리 나에게는이

Sprite::Sprite(void) 
{ 
    _vboID = 0; 
} 

void Sprite::init(float x, float y, float width, float height) 
{ 
    _x = x; 
    _y = y; 
    _height = height; 
    _width = width; 

    if (_vboID == 0) 
    { 
     glGenBuffers(1, &_vboID); 
    } 

    float vertexData[12]; 

    /* 
    ... setting vertices here 
    */ 

    glBindBuffer(GL_ARRAY_BUFFER, _vboID); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 
} 


void Sprite::draw() 
{ 
    glBindBuffer(GL_ARRAY_BUFFER, _vboID); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); 
    glDrawArrays(GL_TRIANGLES, 0, 6); 
    glDisableVertexAttribArray(0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
} 
+1

기술적으로 "실제 렌더링"이전의 모든 것은 논리적이어야하지만 문제가 변경되지는 않습니다. –

+0

물론 당신 말이 맞습니다. 나는 단지 코드를 압축하여 모든 것을 하나의 함수로 묶어서 무슨 일이 일어나는지 더 잘보고 싶었다. – lmNt

답변

0

과 같은 스프라이트 클래스입니다 20Hz의 속도. 이것은 우리가 1/40 초 동안 보이게하고 1/40 초 동안 보이지 않게하려는 것입니다. 이제 다음 Diagramm 사용보고 :

on  1/60  on  1/60  off  1/60 
|---------------------|---------------------|---------------------| Screen 

|--------------------------------|--------------------------------| Flicker 
      1/40 (on)      1/40 (off) 

우리는 경우에, 우리는 객체를 보여주는 2 개 프레임을 얻을 것이다 단 하나의 프레임이 표시되지 않는 것을 알 수있다. 내 생각 엔, 주파수/2가 화면 새로 고침 빈도의 배수가 될 때마다 알고리즘이 작동해야한다는 것입니다. (예 : frequency = [30, 15, ....])

참고 : vsynch를 사용 중지하면 더 많은 이미지가 화면에 표시되지 않고 백그라운드에서 더 많은 이미지가 렌더링됩니다.

+0

답변 해 주셔서 감사합니다. 나는 당신이 의미하는 바를 얻었고, 샘플링 문제라고 생각했습니다. 그러나 예를 들어 30 Hz는 20 Hz에 비해 말더듬이 더 심합니다. 주기적으로 깜박 거리지도 않습니다. 일반적으로 활성화 된 vsync를 사용하면 다시 그리기가 모니터 새로 고침 빈도와 동기화되어야하므로 모든 프레임에서 토글 링되므로 초당 60 회 이상 발생하므로 모든 것을 방해합니다. 그러나 그것은 전혀 작동하지 않으며 왜 나는 모릅니다. – lmNt

+0

모든 프레임을 전환하면 어떻게됩니까?(vsync가 활성화 된 상태에서) – BDL

+0

미안하지만, 프레임 기반 의사 결정을 시도했음을 잊어 버렸습니다. 그것은 문제를 줄이지 만, 어쨌든 여전히 때때로 말더듬을 계속합니다. – lmNt

관련 문제