glScissor()调用另一个glScissor()

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.这就是我试图使用嵌套剪刀的原因,但我知道它没用.基本上我的问题是,实现这一目标的最佳方法是什么?

在此输入图像描述

Chr*_*ica 7

由于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包装自动化,但是你可以自由地进行锻炼.