7

I've a complex UI-system which allows a lot of stuff which also can be done with WPF but supports multiple plattforms ( iOS, Android, Windows, ... ). It's not completed yet and now i'm facing the following issue:

My designer wants rotating objects! Rotating objects are far more complex than simple axis aligned ones, which are the reason i can't use glScissor. A little graphic which might help to understand the problem:

Effect

You can see that i need to clip the object "Subcontainer" by the bounds of the "Parent Container". As far as i know there are few options:

  • Use the stencil buffer, in this case i got a problem because i have objects which are not visible and must also influence the stencil buffer because they are might mask the child object. Also i have to draw each object twice because i need to decrease the stencil buffer when going back in hierarchy.
  • Cut the plane ( triangulate; or any other ui model ) which is used to draw the UI-object, this seems to be a lot of afford because they might clipped at different points ( imagine a container in a rotated container in a rotated container... ) and also it's really hard to clip them correctly and it might be a source of performance issues

However both seem to cause a lot of different issues and might be a source for performance leaks. Is there any other way to archive what i want or is there any way to improve the both approaches above?

4

3 回答 3

5

I ended up with using the Stencil-Buffer, this generates more draw calls than the depth-approach but is much easier to implement.

Before i draw i wrote this code:

if (_Mask)
{
    if (Stage.StencilMaskDepth++ == 0)
        GL.Enable(EnableFlags.STENCIL_TEST);

    GL.ColorMask(false, false, false, false);
    GL.DepthMask(false);
    GL.StencilFunc(StencilFunction.ALWAYS, Stage.StencilMaskDepth, Stage.StencilMaskDepth);
    GL.StencilOp(StencilOp.INCR, StencilOp.INCR, StencilOp.INCR);

    // Draw rectangle
    DrawColor(Colors.Black);

    GL.ColorMask(true, true, true, true);
    GL.DepthMask(true);
    GL.StencilFunc(StencilFunction.EQUAL, Stage.StencilMaskDepth, Stage.StencilMaskDepth);
    GL.StencilOp(StencilOp.KEEP, StencilOp.KEEP, StencilOp.KEEP);
}

After all childs have been drawn this code is called:

if (_Mask)
{
    GL.ColorMask(false, false, false, false);
    GL.DepthMask(false);
    GL.StencilFunc(StencilFunction.ALWAYS, Stage.StencilMaskDepth, Stage.StencilMaskDepth);
    GL.StencilOp(StencilOp.DECR, StencilOp.DECR, StencilOp.DECR);
    // Draw rectangle
    DrawColor(Colors.Black);

    GL.ColorMask(true, true, true, true);
    GL.DepthMask(true);

    if (--Stage.StencilMaskDepth == 0)
        GL.Disable(EnableFlags.STENCIL_TEST);
}

Maybe i going to test some other approaches in a few month but currently this is the easiest to implement.

于 2013-03-05T00:11:42.947 回答
3

This is just an idea, but what about using depth buffer to do the masking?

  1. Enable depth buffer and set glDepthFunc(GL_LEQUAL);
  2. Render Container A and its frame at Z = 0
  3. Render Container A internal area / background (where other nested containers will be) at Z = 1
  4. Now you have a "depth stencil" with container frame at depth 0 and container internals at depth 1. That means that anything you render inbetween will be above internals, but below frame (and clipped by it)
  5. Now with next Container B, render its frame to Z = 0.5 (it will get clipped by parent container A on GPU)
  6. Render container B internal area at Z = 0.75
  7. Now anything you want to render within container B will have to go at Z = 0.75. It will overlay containers internal area, but will be clipped by both container A and B frames.
于 2012-12-06T11:46:47.130 回答
1

Maybe you could try rendering to texture. Create a parent texture. Then render all children to that texture. Then render the parent texture to the screen deforming and displacing it as desired. This solution may or may not have issues, depending on what do you want to achieve. Especially if you animate the containers scale or have a very complex tree of many nested containers you might have performance issues.

于 2012-12-06T12:53:45.343 回答