Pio*_*cki 7 c++ opengl user-interface
我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);
}
Run Code Online (Sandbox Code Playgroud)
但当然在这种情况下启用/禁用调用是错误的:
glEnable(GL_SCISSOR_TEST);
glEnable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
Run Code Online (Sandbox Code Playgroud)
如果我删除那些内部glEnable/glDisable调用(ListView中的调用),我最终会得到两个glScissor()调用,这似乎也是错误的.
我想以某种方式实现两种剪刀效果,我的意思是 - Window应该只在它的剪切区域中绘制,内部ListView也只在它的剪切区域中绘制.
正如你在图片中看到的那样,红色矩形我标记了剪刀区域,Window其中有一个蓝色矩形,我标记了一个我想要绘制的区域ListView.这就是我试图使用嵌套剪刀的原因,但我知道它没用.基本上我的问题是,实现这一目标的最佳方法是什么?

由于OpenGL是一个状态机,而剪切矩形与任何其他状态一样,glScissor在下次调用时会被覆盖,因此在绘制列表视图后必须正确恢复窗口的剪切矩形.这可以通过让窗口管理它来完成:
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);
}
Run Code Online (Sandbox Code Playgroud)
但是让单个组件自己恢复剪刀状态可能更灵活,特别是如果以这种分层方式使用.为此,您可以使用已弃用的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();
}
Run Code Online (Sandbox Code Playgroud)
或者您自己保存并恢复剪刀状态:
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);
}
Run Code Online (Sandbox Code Playgroud)
这当然可以通过一个漂亮的RAII包装自动化,但是你可以自由地进行锻炼.