c++ - 去除 OpenGL 橡皮筋伪影

标签 c++ windows opengl rubber-band

我正在使用一些用于科学可视化的 OpenGL 代码,但在较新的硬件上使其橡皮筋正常工作时遇到问题。该代码在现有场景上绘制一个“缩放窗口”,其中“缩放窗口”的一个角位于存储的左键单击位置,另一个角在鼠标移动时位于鼠标下方。第二次左键单击时,场景会放大到所选窗口。

当鼠标在场景中移动时我看到的症状是:

  1. 出现橡皮筋伪影,它们是用于创建“缩放窗口”的线条,未通过第二个“RenderLogic” channel 从缓冲区中删除(请参见下面的代码)
  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

最佳答案

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

但我理解,您可能想避免这种情况。因此,通常的方法是在绘制第一个橡皮筋之前首先复制纹理中的前缓冲区。然后,对于每个橡皮筋,通过绘制带有纹理的帧缓冲区填充四边形来重新绘制“重置”图像。

关于c++ - 去除 OpenGL 橡皮筋伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8966771/

相关文章:

c++ - 基准可变参数模板函数调用

windows - 描述操作系统大小的词?

windows - 不能在 VS2015 中包含 DirectX header

OpenGL - 如何将对象渲染为 3D 纹理作为体积广告牌

c++ - OpenGL 引用系

c++ - 如何检测 DLL 的#import?

c++ - 什么样的 C++ 函数可以放在 C 函数指针中?

c++ - LNK2001:未解析的外部符号,当试图从另一个 DLL 调用对象的方法时

r - 为什么 file.exists 尽管位于 list.files 中却返回 FALSE?

c++ - wglBindTexImageARB 上的访问冲突;由于 WGL_FRONT_LEFT_ARB 未定义所有包含 wglext.h 的内容?