Удаление артефактов резиновой обвязки OpenGL - PullRequest
2 голосов
/ 23 января 2012

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

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

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

Вышеупомянутая проблема не возникает на оборудовании низкого уровня, таком как встроенная графика на моем нетбуке. Кроме того, я не могу вспомнить эту проблему ~ 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

Ответы [ 3 ]

2 голосов
/ 23 января 2012

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

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

1 голос
/ 26 июля 2013

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

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

0 голосов
/ 23 января 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...