GlScissor () call inside another glScissor ()

I use glScissor() in my application and it works correctly, but I ran into a problem: I have a Window object for which the drawing area is set to glScissor() and inside this area, I draw a ListView object for which the drawing area should also be specified with glScissor() , since I don't want to draw all of this.

In code, I could represent it as:

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

But, of course, in this situation, allowing / disabling calls is not so:

 glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST); 

If I delete these internal calls to glEnable / glDisable (those listed in the ListView), I would somehow encounter two calls to glScissor (), which also seem to be incorrect.

EDIT

I would like to achieve both effects of scissors somehow, I mean that Window should draw only a region with scissors in it and the internal ListView also only in the scissored area.

As you can see in the picture, with the red rectangle, I have the scissor area for Window marked, which is WORKS, and with the blue rectangle, I selected the area on which I would like to draw my ListView . That is why I tried to use nested scissors, but I know that it is useless. So basically my question is: what could be the best approach to achieve this?

enter image description here

+7
source share
3 answers

Since OpenGL is a state machine, and scissor rect, like any other state, is overwritten the next time glScissor called, you must correctly restore the scissor rect window after drawing the list. This can be done simply by letting the window control this:

 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 scissor glDisable(GL_SCISSOR_TEST); } 

But it may be more flexible to allow individual components to independently restore the condition of the scissors, especially if they are used in such a hierarchical manner. To do this, you can use the obsolete glPush/PopAttrib to save and restore the scissor rect cutting tool:

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

Or you yourself save and restore the condition of the scissors:

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

This, of course, can be automated with the beautiful RAII wrapper, but it's free for you.

+7
source

edited : general case.

Each time you set the scissor state with glScissor , you set the scissor state. It does not nest and it does not stack, so you cannot "subscissor" with nested glScissor calls. You will have to manually calculate the rectangular intersection of your ListView and your Window bounding boxes, and then attach the ListView to the scissor.

In the general case, you will manually maintain a stack of rectangles with scissors. As you draw each subitem, you intersect the subitem bounding the rectangle against the current top of the stack, and use this as a scissor for this subitem. Insert a new snapshot onto the stack as you draw the children and pop it when you revert the hierarchy.

If you draw other content before Window , you will also need to properly handle the redundant image; either by adjusting Z-ordering and turning on depth buffering, or by turning off depth buffering and then coloring the contents. Scissoring does not help you mask Window contents behind a ListView , since scissors can only be rectangular areas.

+3
source

OpenGL is a state machine. You can call glScissor, glEnable and glDisable as often as you would like. They do not act as open-close brackets that must be matched. If your challenges stack up like that, that's not a problem. Just don't expect one shear to merge with another; it will just change / overwrite the previous settings.

+1
source

All Articles