我在我的应用程序中使用 glScissor() 并且它工作正常,但我遇到了一个问题:
我有我的 Window 对象,它的绘图区域由 glScissor() 指定,在这个区域内,我正在绘制我的 ListView 对象,它的绘图区域也应该用 glScissor() 指定,因为我不想全部绘制。
在代码中,我可以将其表示为:

Window::draw()
{
   glEnable(GL_SCISSOR_TEST);
    glScissor(x, y, width, height);
        // Draw some components...
        mListView.draw(); // mListView is an object of ListView type
   glDisable(GL_SCISSOR_TEST);
}

ListView::draw()
{
  glEnable(GL_SCISSOR_TEST);
    glScissor(x, y, width, height);
        // Draw a chosen part of ListView here
   glDisable(GL_SCISSOR_TEST);
}
但当然在这种情况下启用/禁用调用是错误的:
glEnable(GL_SCISSOR_TEST);
   glEnable(GL_SCISSOR_TEST);
   glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
如果我删除那些内部 glEnable/glDisable 调用(ListView 中的那些),无论如何我都会以两个 glScissor() 调用结束,这似乎也是错误的。
编辑
我想以某种方式实现两种剪刀效果,我的意思是 - Window 应该只在它的剪裁区域中绘制,而内部 ListView 也只能在它的剪裁区域中绘制。
正如你在图片中看到的,我用红色矩形标记了 Window 的剪刀区域,我用蓝色矩形标记了一个我想在其上绘制 ListView 的区域。这就是为什么我试图使用嵌套剪刀,但我知道它没用。所以基本上我的问题是,实现这一目标的最佳方法是什么?

最佳答案

由于OpenGL是状态机,并且下次调用glScissor时,剪刀矩形与其他任何状态一样都会被覆盖,因此您必须在绘制 ListView 后正确还原窗口的剪刀矩形。这可以通过让窗口管理它来完成:

Window::draw()
{
    // draw some components with their own scissors
    mListView.draw(); // mListView is an object of ListView type

    glScissor(x, y, width, height);
    glEnable(GL_SCISSOR_TEST);
        // draw other stuff using window's scissor
    glDisable(GL_SCISSOR_TEST);
}

但是让各个组件自己恢复剪刀状态可能会更灵活,特别是如果以这种分层方式使用。为此,您可以使用已弃用的 glPush/PopAttrib 函数来保存和恢复剪刀矩形:
ListView::draw()
{
    glPushAttrib(GL_SCISSOR_BIT);
    glEnable(GL_SCISSOR_TEST);
    glScissor(x, y, width, height);
        // Draw a chosen part of ListView here
    glDisable(GL_SCISSOR_TEST);
    glPopAttrib();
}

或者你自己保存和恢复剪刀状态:
ListView::draw()
{
    // save
    int rect[4];
    bool on = glIsEnabled(GL_SCISSOR_TEST);
    glGetIntegerv(GL_SCISSOR_BOX, rect);

    glEnable(GL_SCISSOR_TEST);
    glScissor(x, y, width, height);
        // Draw a chosen part of ListView here

    // restore
    glScissor(rect[0], rect[1], rect[2], rect[3]);
    if(!on)
        glDisable(GL_SCISSOR_TEST);
}

这当然可以使用一个不错的 RAII 包装器自动完成,但您可以免费练习。

10-04 12:59