【问题标题】:How to force openGL to draw a non-convex filled polygon如何强制openGL绘制非凸填充多边形
【发布时间】:2014-10-14 21:08:42
【问题描述】:

多边形绘制成凸形似乎是标准。请参阅stackoverflow.com/questions/15556929/open-gl-polygon 但是,如果我选择填充它不适合我。如何在保持我定义的形状的同时填充我的多边形?

void drawFloor(){
    // White
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // GL_LINE works the way I want it too
    //glDisable(GL_POLYGON_SMOOTH); // has no effect :(
    glBegin(GL_POLYGON);
    glColor3f(1.0, 1.0, 1.0);
    glVertex3f(0, 0, 0); //0
    glVertex3f(2*boxSize, 0, 0); //1
    glVertex3f(2 * boxSize, -boxSize, 0); //2
    glVertex3f(5 * boxSize, -boxSize, 0); //3
    glVertex3f(5 * boxSize, 4 * boxSize, 0); //4
    glVertex3f(6 * boxSize, 4 * boxSize, 0); //5
    glVertex3f(6 * boxSize, 6 * boxSize, 0); //6
    glVertex3f(0 * boxSize, 6 * boxSize, 0); //7
    glVertex3f(0 * boxSize, 2 * boxSize, 0); //8
    glVertex3f(1 * boxSize, 2 * boxSize, 0); //9
    glVertex3f(1 * boxSize, 4 * boxSize, 0); //10
    glVertex3f(2 * boxSize, 4 * boxSize, 0); //11
    glVertex3f(2 * boxSize, 3 * boxSize, 0); //12
    glVertex3f(3 * boxSize, 3 * boxSize, 0); //13
    glVertex3f(3 * boxSize, 2 * boxSize, 0); //14
    glVertex3f(2 * boxSize, 2 * boxSize, 0); //15
    glVertex3f(2 * boxSize, 1 * boxSize, 0); //16
    glVertex3f(0, 1 * boxSize, 0); //17

    glEnd();
}

这段代码导致:

http://postimg.org/image/o4wt9ij33/ 与 GL_LINE http://postimg.org/image/l31fltgkf/ 带有 GL_FILL

我只想要填充多边形的内部,保持版本的形状与 GL_LINE。没想到GL_FILL的输出会有这么大的不同。

我想要的(用 MS Paint 创建): http://postimg.org/image/d3gbf613d/

我正在使用 Win7+ Visula studio express2013+ Renderer Intel HD Graphics 版本:3.1.0 - Bulid 8.15.10.2509+ GLSL 版本 1.40

【问题讨论】:

  • 那不是convex,而是concave。您需要将多边形拆分为凸子多边形
  • 同意,它是凹的。有没有办法在一个凹多边形中定义它?

标签: c opengl drawing polygon


【解决方案1】:

注意:此答案与我最近在此处对类似问题的回答共享内容:Black out everything outside a polygon。我没有将这些问题指定为重复问题,因为它们听起来不同,并且可能有不同的答案,尽管这个问题恰好是相同的。

绘制非凸多边形的一种方法是将它们分解为三角形。有许多算法可以做到这一点,可以通过搜索“多边形三角剖分”等关键字找到。

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,它在每次渲染像素时翻转模板值,最终将奇数/偶数计数存储在模板缓冲区中。

    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. 绘制覆盖整个多边形区域的几何图形,甚至可能更多。例如,这可以是步骤 4 中的三角形扇形,或多边形的边界框。只渲染多边形轮廓内的部分,其余部分通过模板测试消除。

【讨论】:

  • 这看起来对绘制单个多边形很有用,但如果填充多个多边形,每个多边形都有自己的颜色,我认为这不是采用的方法。可能改为使用一些“多边形三角剖分”算法,然后告诉 GL 绘制三角形。
猜你喜欢
  • 2011-04-21
  • 2014-01-27
  • 2011-01-04
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
相关资源
最近更新 更多