我在我的应用程序中使用 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 包装器自动完成,但您可以免费练习。