5

I have been reading articles about clipping now for hours now but I dont seem to find a solution for my problem.

This is my scenario:

Within an OpenGL ES environment (IOS,Android) I am having a 2D scene graph consisting of drawable objects, forming a tree.

Each tree node has its own spatial room with it's own transformation matrix, and each node inherits its coordinate space to its children. Each node has a rectangular bounding box, but these bounding boxes are not axis aligned.

This setup works perfect to render a 2D scene graph, iterating through the tree, rendering each object and then it's children.

Now comes my problem: I am looking for a way enable clipping on a node. With clipping enabled, children of a node should be clipped when leaving the area of the parent's bounding box.

For example I wand to have a node containing a set of text nodes as children, which can be scrolled up and down withing it's parents bounding box, and should be clipped when leaving the area of the parent's bounding box.

Since bounding boxes are not axis aligned, I cannot use glScissor, which would be the easiest way.

I was thinking about using the stencil buffer and draw the filled bounding rectangle into it, when clipping is enabled and then enable the stencil buffer. This might workd but leads to another problem: What happens if a child inside a clipped node has clipping again ? - The stencil mask would have to be setup for the child, erasing the parents stencil mask.

Another solution I was thinking of, is to do the clipping in software. This would be possible, because within each node, clipping could be done relative easily in it's own local coordinate space. The backdraw of this solution would be that clipping has to be implemented for each new node type that is implemented.

Can anybody here point me into the right direction? What I am looking for is something like the functionality of glscissor for clipping non axis aligned rectangular areas.

NULL
  • 353
  • 3
  • 13

1 Answers1

5

The scissor box is a simple tool for simple needs. If you have less simple needs, then you're going to have to use the less simple OpenGL mechanism for clipping: the stencil buffer.

Assuming that you aren't using the stencil buffer for anything else at present, you have access to 8 stencil bits. By giving each level in your scene graph a higher number than the last, you can assign each level its own stencil mask. Of course, if two siblings at the same depth level overlap, or simply are too close, then you've got a problem.

Another alternative is to assign each node a number from 1 to 255. Using a stencil test of GL_EQUAL, you will be able to prevent the overlap issue above. However, this means that you can have no more than 255 nodes in your entire scene graph. Depending on your particular needs, this may be too much of a restriction.

You can of course clear the stencil (and depth. Don't try to clear just one of them) when you run out of bits via either method. But that can be somewhat costly, and it requires that you clear the depth, which you may not want to do.

Another method is to use the increasing number and GL_EQUAL test only for non-axis-aligned nodes. You use the scissor box for most nodes, but if there is some rotation (whether on that node or inherited), then you use the stencil mask instead, bumping the mask counter as you process the graph. Again, you are limited to 256 nodes, but at least these are only for rotated nodes. Depending on your needs and how many rotated nodes there are, that may be sufficient.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I still don't get the idea with increasing numbers. Imagine the first node that has clipping enabled draws a rectangle with 1s into the stencilbuffer, his siblings will be perfectly clipped. Now comes another sibling that has clipping enabled. It draws a rectangle filled with 2s into the stencil buffer, replacing the 1s where the 2 rectangles overlap. – NULL Sep 24 '11 at 19:21
  • The siblings will also be perfectly clipped because they are tested agains 2. Now we go to the first node, that has to be stencil tested against 1. The test will fail here because we test against 1 and some parts of the first rectangle have been overwritten with 2s. Please correct me if I got your idea wrong! – NULL Sep 24 '11 at 19:22
  • @NULL Each node should always draw its own stuff contents before drawing the children. As such, this issue will only matter if two siblings under the same parent overlap. And if they do, then the proper thing will happen: one of the overlaps win and the other loses. Siblings should clip one another, and therefore, one of them has to win. Siblings under a node, just as with a GUI hierarchy, have a Z-order. You simply need to maintain this order and draw them appropriately. – Nicol Bolas Sep 24 '11 at 19:41
  • @NULL Also, you can use GL_LEQUAL on stencil tests to ensure that clipping happens above a certain point, but below others. As long as all parents are assigned a stencil value smaller than their children, this will work fine. – Nicol Bolas Sep 24 '11 at 19:44
  • @NICOLAS BOLAS Thank you for your inputs. I have sucessfully implemented the case where nodes and ancestors are axis aligned. I need some more help with the stencil version. I almost got it working, but I need a different algorithm. I have edited the original post and described my algorithm and the problems I am having there. – NULL Sep 27 '11 at 06:32
  • @NULL: It is important to understand that Stack Overflow is not a forum; it is a Q&A site. You ask a question, and you get an answer. If that answer leads you to write some code that you later have a question about, the general practice is to simply ask a new question. If you need to reference the old one, just link to it. – Nicol Bolas Sep 27 '11 at 06:41
  • @NICOLAS BOLAS Thank you for the hint - I have put the new question into a new posting. Thank you very much for your helpfull inputs, I have really come far with my implementation. – NULL Sep 27 '11 at 13:47