2011-01-19 32 views
0

私は、この奇妙なクリッピングのバグをアプリで並べ替えるのに非常に苦労しています。Windows OpenGL実装のバグ?

基本的に、何らかの理由で、OpenGLがglClear()呼び出しをクリッピング(シザーテストを使用)していますが、後で行うレンダリングではありません。

しかし、本当の問題は、ウィンドウのサイズを変更すると問題が消えてしまうことです。ウィンドウのサイズを変更してもアプリで何も変わったり、コードを実行したりすることはありません。それは非常に奇妙です。さらに悪いことに、単に私が代わりにまたはglDisable(ちょうど1つのコールを持つのシザーテストを、無効にする必要があり

glDisable(GL_SCISSOR_TEST); 
glDisable(GL_SCISSOR_TEST); 

)を置くこと問題を解決します。コードを一括して削除します(シーザーテストはすでにこのテストケースでは無効になっていますが、コードは前のコードで無効にしていないときに使用されています)。これは、問題を解決するためにも役立ちます。

glEnable(GL_SCISSOR_TEST); 
glDisable(GL_SCISSOR_TEST); 

私は考えることができるのは2つだけです。私は何とかUBを呼び出しています(OpenGLにはUB AFAIKがないので疑います)、またはglDisable()を同じパラメータで2回呼び出すと、一度呼び出すと同じでなければならないので、実装上のバグがあります。もし私が間違っていなければ。

ことが重要であるJUST包み、ここで問題が起こっされた機能は次のとおりです。

void gle::Renderer::setup3DCamera(gle::CameraNode& cam, gle::Colour bkcol, 
    int clrmask, int skymode, gle::Texture* skytex, bool uselight) { 
    // Viewport 
    Rectangle wr(cam.getViewport()?*cam.getViewport():Rectangle(0,0,1,1)); 
    if (cam.isRatioViewport()||(!cam.getViewport())) { 
     if (i_frameBind==NULL) 
      wr.scale(selectedWindow->getWidth(),selectedWindow->getHeight()); 
     else wr.scale(i_frameBind->getWidth(),i_frameBind->getHeight()); 
    } 
    gle::Rectangle_t<int> iport; iport.set(wr); 
    int winHei; 
    if (i_frameBind==NULL) 
     winHei = selectedWindow->getHeight(); 
    else 
     winHei = i_frameBind->getHeight(); 
    glViewport(iport.x1(),winHei-iport.y2(),iport.wid(),iport.hei()); 
    // Viewport Clipping 
    if (cam.isClipping()) { 
    /* This is never executed in the test case */ 
     glEnable(GL_SCISSOR_TEST); 
     glScissor(iport.x1(),winHei-iport.y2(),iport.wid(),iport.hei()); 
    } else { 
    /* This is where I disable the scissor test */ 
     glDisable(GL_SCISSOR_TEST); 
     glDisable(GL_SCISSOR_TEST); 
    } 
    float w=wr.wid()/2, h=wr.hei()/2; 
    // Projection 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    Projection proj = cam.getProjection(); 
    gluPerspective(proj.fov,proj.aspect*(w/h),proj.cnear,proj.cfar); 
    // Camera 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    float m[] = { 1,0,0,0, 0,0,-1,0, 0,1,0,0, 0,0,0,1 }; 
    glMultMatrixf(m); 
    static gle::Mesh *skyBox = NULL; 
    // Screen Clearing 
    switch (clrmask&GLE_CLR_COLOUR&0x00F?skymode:GLE_SKYNONE) { 
    case GLE_SKYNONE: 
     clear(clrmask&(~GLE_CLR_COLOUR)); break; 
    case GLE_SKYCOLOUR: 
     clearColour(clrmask,bkcol); break; 
    case GLE_SKYBOX: 
     glDisable(GL_DEPTH_TEST); 
     if (!(clrmask&GLE_CLR_DEPTH&0x00F)) glDepthMask(0); 
     float m = (cam.getProjection().cnear+cam.getProjection().cfar)/2.0f; 
     if (skyBox==NULL) skyBox = gle::createStockMesh(GLE_MESHSKYBOX,GLE_WHITE,0,m); 
     glEnable(GL_TEXTURE_2D); 
     glDisable(GL_CULL_FACE); 
     skytex->flush(); 
     glBindTexture(GL_TEXTURE_2D,skytex->getID()); 
     glDisable(GL_LIGHTING); 
     glPushMatrix(); 
     float m3[16]; 
     Orientation::matrixSet(m3,cam.pos().getMatrix(GLE_ROTMATRIX)); 
     Orientation::matrixTranspose(m3); 
     glMultMatrixf(m3); 
     if (i_reflectionOn) glMultMatrixf(Orientation::matrixGet3x3(i_reflectionTransform)); 
     renderMesh(*skyBox,NULL,1); 
     glPopMatrix(); 
     glDisable(GL_TEXTURE_2D); 
     if (clrmask&GLE_CLR_DEPTH) glClear(GL_DEPTH_BUFFER_BIT); 
     else glDepthMask(1); 
     glAble(GL_DEPTH_TEST,depthmode!=GLE_ALWAYS); 
     break; 
    } 
    // Camera 
    glMultMatrixf(cam.getAbsInverseMatrix()); 
    if (i_reflectionOn) glMultMatrixf(i_reflectionTransform); 
    // Lighting 
    i_lightOn = uselight; 
    glAble(GL_LIGHTING,i_lightOn); 
} 
+0

[Mesa](http://www.mesa3d.org/)ソフトウェアラスタライザを使用して再現できますか? – genpfault

+2

グラフィックスカードは何ですか? NVidia以外の誰かからWindowsのOpenGLドライバはかなり吸う - インテルのドライバが最悪です。 –

+0

私にバグのように見えます。あなたのハードウェアの最新版にあなたのGLドライバを更新します。 – Bahbar

答えて

0

これは私には、ドライバのバグのように見えます。しかし、実際にコード内にバグがあるケースが2つあります。

最初に、glDisable()を呼び出すときにglBegin()/ glEnd()ブロックの真ん中にいて、何らかのエラーが発生してブロックが終了し、glDisable() 。これはglBegin()/ glEnd()を使った馬鹿げた例であることに注意してください。OpenGLエラーがキャッチされている可能性があります。 glGetError()をコード全体に挿入してください。私の推測では、glDisable()への最初の呼び出しはGL_INVALID_OPERATIONを生成します。

第2に、はさみテストではありませんが、同じ値でglViewport()を呼び出しています。これは、NVIDIA上で反対の効果(クリップglClear()とクリップの描画ではありません)を持っていますが、他のドライバ/ GL実装では逆になることがあります。