2012-01-23 8 views
2

私は科学的な視覚化のためにいくつかのOpenGLコードで作業しています。コードは、保存された左クリック位置に「ズームウィンドウ」の1つのコーナーがあり、マウスが移動すると、その下にもう1つのコーナーがある既存のシーン上に「ズームウィンドウ」を描画しています。 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 -

Artefacts from Zoom Window

+0

スクリーンショットplzを投稿できますか? – Kromster

答えて

2

OpenGLでは、何か変更があった場合、ビューポート全体を再描画することが標準的です。これを考慮してください:現代のシステム描画は、30FPSを超える複雑なシーンをアニメーション化します。

しかし、私はあなたがこれを避けたいと考えていることを理解しています。そのため、最初のラバーバンドを描画する前に、まずテクスチャでフロントバッファをコピーするのが通常の方法です。次に、各ラバーバンドの描画では、フレームバッファにテクスチャを塗りつぶしてイメージを「リセット」します。

+1

「何かが変更された場合は、ビューポート全体を再描画します」 - これは私があまりにも示唆していることですが、単に疑う余地がないからです。それでも 'a^b^b!= a'というのは素晴らしいです。上のコードは本当にうまくいくように見えます。 'Point :: Coords'が' const'関数でないか、OPが他のスレッドが他のスレッドを変更するなどしているのを忘れた場合を除きます。 'm_pntCurrLoc' ... – Damon

+0

シーン全体を再描画することを提案してくれてありがとう - 最近XORは必要ではないと私は同意しますが、私はロジックを削除するためにリファクタリングを少ししなければならないかもしれません。私はこれを避けるために、古いコードをできるだけ変更することなく動作させようとしていました。 – mcdave

+0

@Damon - はい、動作するはずです...また、ATIまたはNVIDIAカードではなく、インテグレーテッドグラフィックスを搭載したマシンでも完全に動作します。これは、トリプルバッファリングやファンキーなことが起こっているかもしれないと思っています。私のOpenGLは、遠くから進歩しています。私は、XOR操作を削除するために、より多くの実験をすることも、リファクタリングだけを行うこともできます。 – mcdave

0

下の画像あなたはVistaの/ 7とエアロを使用している場合、クラシックテーマに切り替えてみてください。

+0

提案してくれてありがとう - 私はちょうど切り替えを試み、アーティファクトはまだそこにあります。 – mcdave

1

私は1年半前の質問に投稿していることを知っていますが、他の誰かがこの問題に遭遇した場合に備えています。

間違ったバッファの行を削除しようとしているため、これは自分自身に起こりました。たとえば、バッファAのswapBufferを呼び出して長方形を描画し、バッファBから四角形を取り除こうとします。バッファAの描画とバッファAの描画の2つの「ズームウィンドウ」の四角形を追跡します。どのバッファが最新バッファであるかを把握しておく必要があります。