Ошибка реализации Windows OpenGL? - PullRequest
0 голосов
/ 19 января 2011

Мне очень трудно разобраться с этой странной ошибкой отсечения в моем приложении.

По какой-то причине OpenGL обрезает (используя тест ножниц) мой вызов glClear (), но нерендеринг, который я делаю потом.

Однако реальная проблема заключается в том, что проблема исчезает, когда я изменяю размер окна.Я могу гарантировать, что изменение размера окна ничего не изменит в моем приложении и не выполнит какой-либо код.Это очень странно.Что еще хуже, просто поместив

glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);

там, где мне нужно отключить тест ножниц, вместо одного вызова glDisable (), чтобы решить эту проблему.То же самое можно сказать и об удалении кода (тест ножниц уже отключен в этом тестовом примере, но код существует, когда он не был отключен в предыдущем коде).Это даже решает проблему:

glEnable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);

Есть только два объяснения, которые я могу придумать.Либо я как-то вызываю UB (в чем я сомневаюсь, потому что opengl не имеет UB AFAIK), или есть ошибка реализации, потому что вызов glDisable () дважды с одним и тем же параметром последовательно ДОЛЖЕН быть тем же, что и вызов его один раз ...если я не ошибаюсь.

ПРОСТО, если это представляет интерес, вот функция, для которой происходит проблема:

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);
}

1 Ответ

0 голосов
/ 13 февраля 2012

Для меня это похоже на ошибку драйвера.Однако в двух случаях это может быть ошибкой в ​​вашем коде.

Во-первых, вы можете оказаться в середине блока glBegin () / glEnd () при вызове этого glDisable (), вызывая некоторыеошибка, а также завершение блока, что делает второй вызов glDisable () легальным и эффективным.Обратите внимание, что это глупый пример с glBegin () / glEnd (), это может быть практически любой случай ошибки OpenGL.Вставьте вызовы glGetError () в ваш код, чтобы быть уверенным.Я предполагаю, что первый вызов glDisable () генерирует GL_INVALID_OPERATION.

Во-вторых, вы не тестируете ножницами, но вы все еще вызываете glViewport () с теми же значениями.Это будет иметь противоположный эффект (не клип glClear () и рисование клипов) на NVIDIA, но вполне может быть, что он делает противоположное в некоторых других реализациях драйвера / GL.

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