2012-01-23 3 views
2

Я работаю с некоторым кодом OpenGL для научной визуализации, и у меня возникают проблемы с его резинкой, работающей на более новом оборудовании. Код рисует «окно масштабирования» поверх существующей сцены с одним углом «окна масштабирования» в сохраненном месте щелчка левой кнопкой мыши, а другой под мышью при перемещении. Во втором щелкнув левой кнопкой мыши, сцена увеличивает масштаб в выбранном окне.Удаление артефактов резиновой ленты OpenGL

Симптомы Я вижу, как мышь перемещается по сцене являются:

  1. Rubber облицовывания артефакты, появляющиеся, которые линии используются для создания «Zoom Window» не удаляется из буфера с помощью второго «RenderLogic» проходит (см код ниже)
  2. я могу ясно видеть содержимое предыдущего буфера мигает и исчезают, как буфера меняются местами

Указанная проблема не происходит на низких конечных аппаратных средства, такие, как интегрированная графика s на нетбуке у меня есть. Кроме того, я не могу вспомнить эту проблему ~ 5 лет назад, когда этот код был написан.

Вот соответствующие участки кода, отделанные вниз, чтобы сосредоточиться на соответствующем OpenGL:

// Called by every mouse move event 
// Makes use of current device context (m_hDC) and rendering context (m_hRC) 
void MyViewClass::DrawLogic() 
{ 
    BOOL bSwapRv = FALSE; 

    // Make the rendering context current 
    if (!wglMakeCurrent(m_hDC, m_hRC)) 
     // ... error handling 

    // Perform the logic rendering 
    glLogicOp(GL_XOR); 
    glEnable(GL_COLOR_LOGIC_OP); 
    // Draws the rectangle on the buffer using XOR op 
    RenderLogic(); 
    bSwapRv = ::SwapBuffers(m_hDC); 
    // Removes the rectangle from the buffer via a second pass 
    RenderLogic(); 
    glDisable(GL_COLOR_LOGIC_OP); 

    // Release the rendering context 
    if (!wglMakeCurrent(NULL, NULL)) 
     // ... error handling 
} 

void MyViewClass::RenderLogic(void) 
{ 
    glLineWidth(1.0f); 
    glColor3f(0.6f,0.6f,0.6f); 
    glEnable(GL_LINE_STIPPLE); 
    glLineStipple(1, 0x0F0F); 
    glBegin(GL_LINE_LOOP); 
     // Uses custom "Point" class with Coords() method returning double* 
     // Draw rectangle with corners at clicked location and current location 
     glVertex2dv(m_pntClickLoc.Coords()); 
     glVertex2d(m_pntCurrLoc.X(), m_pntClickLoc.Y()); 
     glVertex2dv(m_pntCurrLoc.Coords()); 
     glVertex2d(m_pntClickLoc.X(), m_pntCurrLoc.Y()); 
    glEnd(); 
    glDisable(GL_LINE_STIPPLE); 
} 

// Setup code that might be relevant to the buffer configuration 
bool MyViewClass::SetupPixelFormat() 
{ 
    PIXELFORMATDESCRIPTOR pfd = { 
     sizeof(PIXELFORMATDESCRIPTOR), 
     1,      // Version number (?) 
     PFD_DRAW_TO_WINDOW  // Format must support window 
     | PFD_SUPPORT_OPENGL // Format must support OpenGL 
     | PFD_DOUBLEBUFFER,  // Must support double buffering 
     PFD_TYPE_RGBA,   // Request an RGBA format 
     32,      // Select a 32 bit colour depth 
     0, 0, 0, 0, 0, 0,  // Colour bits ignored (?) 
     8,      // Alpha buffer bits 
     0,      // Shift bit ignored (?) 
     0,      // No accumulation buffer 
     0, 0, 0, 0,    // Accumulation bits ignored 
     16,      // 16 bit Z-buffer 
     0,      // No stencil buffer 
     0,      // No accumulation buffer (?) 
     PFD_MAIN_PLANE,   // Main drawing layer 
     0,      // Number of overlay and underlay planes 
     0, 0, 0     // Layer masks ignored (?) 
    }; 
    PIXELFORMATDESCRIPTOR chosen_pfd; 

    memset(&chosen_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); 
    chosen_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 

    // Find the closest match to the pixel format 
    m_uPixelFormat = ::ChoosePixelFormat(m_hDC, &pfd); 

    // Make sure a pixel format could be found 
    if (!m_uPixelFormat) 
     return false; 
    ::DescribePixelFormat(m_hDC, m_uPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosen_pfd); 

    // Set the pixel format for the view 
    ::SetPixelFormat(m_hDC, m_uPixelFormat, &chosen_pfd); 

    return true; 
} 

Любые указатели о том, как удалить артефакты будут оценены.

@Krom - изображение ниже

Artefacts from Zoom Window

+0

Вы можете публиковать скриншот PLZ? – Kromster

ответ

2

С OpenGL канонически перерисовать весь видовой экран, если что-то изменится. Рассмотрим это: Современная система рисования оживляет сложные сцены на более чем 30 FPS.

Но я понимаю, что вы можете этого избежать. Таким образом, обычный подход заключается в том, чтобы сначала скопировать фронтбуфер в текстуру, прежде чем рисовать первую резиновую ленту. Затем для каждой резинкой перерисовывайте «сброс» изображения, рисуя фреймбуфер, заполняющий квадрат текстурой.

+1

«перерисовать весь видовой экран, если что-то изменится» - вот что я предлагаю, просто потому, что он не оставляет никаких сомнений. Тем не менее это потрясающе, что 'a^b^b! = A'. Вышеприведенный код выглядит так, как будто он работает. Если «Point :: Coords» не является функцией 'const', или OP забыл упомянуть, что какой-то другой поток изменяет, например, 'm_pntCurrLoc' ... – Damon

+0

Спасибо за предложение перерисовать всю сцену - я согласен, что XOR не является необходимым в наши дни, и мне, возможно, придется немного обработать рефакторинг, чтобы удалить логическую операцию. Я пытался избежать этого, получив старый код для работы с минимальными изменениями. – mcdave

+0

@ Дамон - да, похоже, что он должен работать ...и он отлично работает на наших машинах с интегрированной графикой Intel, а не на наших картах ATI или NVIDIA! Это заставляет меня думать, что может быть какая-то тройная буферизация или что-то напуганное. Мой OpenGL работоспособен, но далеко не продвинутый. Я мог бы либо экспериментировать больше, либо просто рефакторировать, чтобы удалить операцию XOR. – mcdave

0

Если вы используете Vista/7 и Aero, попробуйте переключиться на классическую тему.

+0

Спасибо за предложение - я просто попытался переключиться, и артефакты все еще там. – mcdave

1

Я знаю, что публикую вопрос на год и половину старого вопроса, но на случай, если кто-то еще столкнется с этим.

У меня это случилось со мной, потому что вы пытаетесь удалить строки с неправильного буфера. Например, вы нарисуете свой прямоугольник в буфере. Вызовите swapBuffer, а затем попытайтесь удалить прямоугольник из буфера B. То, что вы хотели бы сделать, это отслеживать два прямоугольника «масштабирования окна», когда вы делаете рисунок один для буфера A и один для буфера B, а затем отслеживать, какой из них является самым последним.