2

我正在使用一些用于科学可视化的 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 - 下图

缩放窗口中的人工制品

4

3 回答 3

2

使用 OpenGL,如果有任何变化,重新绘制整个视口是规范的。考虑一下:现代系统以超过 30 FPS 的速度绘制复杂场景的动画。

但我明白,你可能想避免这种情况。所以通常的方法是在绘制第一个橡皮筋之前先复制纹理中的前端缓冲区。然后为每个橡皮筋重绘“重置”图像,方法是使用纹理绘制一个填充四边形的帧缓冲区。

于 2012-01-23T09:37:43.497 回答
1

我知道我要发布一个半年前的问题,但以防其他人遇到这个问题。

我自己也遇到过这种情况,因为您试图从错误的缓冲区中删除行。例如,您在缓冲区 A 调用 swapBuffer 上绘制矩形,然后尝试从缓冲区 B 中删除矩形。您想要做的是跟踪 2 个“缩放窗口”矩形,同时为缓冲区 A 绘制一个矩形和一个对于缓冲区 B,然后跟踪哪个是最新的。

于 2013-07-26T15:02:19.570 回答
0

如果您使用的是 Vista/7 和 Aero,请尝试切换到 Classic 主题。

于 2012-01-23T05:32:03.983 回答