在OpenGL中绘制剪切UI元素的最佳方法

Fel*_* K. 6 c# opengl

我有一个复杂的UI系统,允许很多东西,也可以用WPF完成,但支持多个平台(iOS,Android,Windows,...).它还没有完成,现在我面临以下问题:

我的设计师想要旋转物体!旋转对象远比简单的轴对齐复杂,这是我不能使用glScissor的原因.一个可能有助于理解问题的小图形:

影响

您可以看到我需要通过" 父容器 " 的边界剪切对象" Subcontainer ".据我所知,几乎没有选择:

  • 使用模板缓冲区,在这种情况下我遇到了一个问题,因为我有不可见的对象,还必须影响模板缓冲区,因为它们可能会掩盖子对象.此外,我必须绘制每个对象两次,因为我需要在返回层次结构时减少模板缓冲区.
  • 切割用于绘制UI对象的平面(三角形;或任何其他ui模型),这看起来很有代价,因为它们可能会在不同的点处剪切(想象一个旋转容器中旋转容器中的容器). ..)也很难正确剪辑它们,它可能是性能问题的根源

然而,两者似乎都会导致许多不同的问题,并可能成为性能泄漏的来源.有没有其他方式来存档我想要的或有什么方法来改善上述两种方法?

Fel*_* K. 5

我最终使用了 Stencil-Buffer,它比深度方法产生更多的绘制调用,但更容易实现。

在我画画之前,我写了这段代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

在绘制完所有孩子之后,调用此代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

也许我会在几个月内测试其他一些方法,但目前这是最容易实现的。