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

Ste*_*veL 1 opengl opengl-es opengl-es-2.0 libgdx

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

我想要的是绘制多边形黑色之外的所有东西.或者,当然只在多边形内绘制东西.

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

在此输入图像描述

Ret*_*adi 8

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

OpenGL有另一种机制,适用于这些用例:模板缓冲区.您可以在红皮书中使用模板缓冲区绘制填充,凹面多边形下找到此方法的说明.主要思想是您可以绘制具有任意原点和多边形顶点的三角形扇形.然后,多边形内部的像素将被绘制奇数次,而多边形外部的像素将被绘制偶数次.模板缓冲区用于跟踪每个像素的绘制次数的奇数/偶数.

概述主要步骤:

  1. 在设置上下文和绘图表面时,请确保使用模板缓冲区请求配置.
  2. 在绘图过程中,清除模板缓冲区和颜色缓冲区,并启用模板测试.

    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glEnable(GL_STENCIL_TEST);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 设置渲染过程的状态,计算像素是否呈现奇数/偶数次.请注意,这只能写入模板缓冲区,因此禁用了颜色写入.关键部分是GL_INVERT模板操作,它在每次渲染一个像素时翻转模板值,给出奇数/偶数.

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

    (0.0f, 0.0f), p1, p2, ... , pN, p1
    
    Run Code Online (Sandbox Code Playgroud)

    您可以为此过程使用一个简单的着色器,因为甚至没有写入颜色值.

  5. 再次启用颜色写入,并设置模板测试属性以仅渲染在上一次传递中呈现奇数次数的像素.

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glStencilFunc(GL_EQUAL, 1, 1);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    
    Run Code Online (Sandbox Code Playgroud)
  6. 绘制整个内容.仅渲染多边形轮廓内的零件,其余部分通过模板测试消除.