代码之家  ›  专栏  ›  技术社区  ›  SteveL

将多边形外部的所有内容涂黑

  •  1
  • SteveL  · 技术社区  · 11 年前

    我有一张地图,为了简单起见,让我们假设它只是一个纹理。在这张地图的顶部,我有一个多边形,它指示用户必须遵循的路线。

    我想要的是把多边形外面的所有东西都画成黑色。或者,当然,只在多边形内绘制对象。

    为了更好地解释,我拍了一张照片。蓝色线定义多边形,每个角都是多边形中的一个点。带黄线的红色是我想在图片中涂黑的部分,只留下带紫线的红色。多边形从A开始,到B结束。

    enter image description here

    1 回复  |  直到 11 年前
        1
  •  8
  •   Reto Koradi    11 年前

    这里的主要挑战是需要绘制一个非凸多边形,OpenGL不直接支持该多边形。绘制它的一种方法是将其分解为三角形。根据您对多边形形状的了解程度以及多边形的约束程度,这可能相当容易。对于一般的非凸多边形,这有点痛苦。但如果你搜索“多边形三角剖分”之类的关键词,你可以找到一些算法。

    OpenGL还有另一种机制可以很好地处理这类用例:模板缓冲区。您可以在以下红皮书中找到这种方法的解释 Drawing Filled, Concave Polygons Using the Stencil Buffer 。主要思想是可以绘制具有任意原点和多边形顶点的三角形扇形。然后,多边形内部的像素将被绘制奇数次,而多边形外部的像素将绘制偶数次。模板缓冲区用于跟踪每个像素绘制次数的奇数/偶数计数。

    概述主要步骤:

    1. 在设置上下文和绘图面时,请确保请求使用模具缓冲区进行配置。
    2. 绘制期间,清除模板缓冲区和颜色缓冲区,并启用模板测试。

      glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
      glEnable(GL_STENCIL_TEST);
      
    3. 设置渲染过程的状态,该状态在像素渲染奇数/偶数次时计数。请注意,这只能写入模具缓冲区,因此颜色写入被禁用。关键部分是 GL_INVERT 对于模板op,它在每次渲染一个像素时都会翻转模板值,为我们提供奇数/偶数计数。

      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glStencilFunc(GL_ALWAYS, 0, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
      glStencilMask(1);
      
    4. 以任意点(例如(0.0,0.0)作为第一个顶点,以多边形角作为其余顶点,渲染三角形扇形。多边形必须闭合,因此第一个和最后一个多边形角必须相同。如果p1,p2,pN是多边形的角 GL_TRIANGLE_FAN 绘制调用是:

      (0.0f, 0.0f), p1, p2, ... , pN, p1
      

      您可以在该过程中使用一个普通的着色器,因为颜色值甚至没有写入。

    5. 再次启用颜色写入,并将模具测试属性设置为仅渲染在上一个过程中渲染奇数次的像素。

      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
      
    6. 绘制整个内容。只有多边形轮廓内的部分将被渲染,其余部分将通过模板测试消除。