0

OpenGL ES 有 XOR 绘图模式吗?我想在那种模式下画一个立方体,然后画一个与立方体相交的球体,输出应该是立方体的一部分和球体的一部分,但有空的交点。

4

1 回答 1

3

鉴于您想要投影后两个对象的图像空间交集,而不是立方体与球体的实际几何交集(因为这绝对不是 OpenGL 的用途),您可以为此使用模板 缓冲区

首先确保你有一个模板缓冲区(取决于你的上下文创建框架,不知道 Cocos3D 是怎么做的,但是 OpenGL ES 1 本身支持模板测试)。然后当然在做立方体和球体之前启用模板,并在帧开始时清除模板缓冲区(可能与其他缓冲区一起):

glClear(... | GL_STENCIL_BUFFER_BIT);
...
glEnable(GL_STENCIL_TEST);

首先,我们仅将立方体渲染到模板缓冲区中,0为每个绘制的像素递增模板值(从 开始)。

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); //don't really draw anything
glStencilFunc(GL_ALWAYS, 0, -1);    //always pass the test (default anyway)
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);  //increment for each drawn pixel
//draw object

然后我们对球体做同样的事情。之后,模板缓冲区在1任何地方都有一个立方体像素或一个球体像素,以及一个2无处不在的立方体和一个球体像素。

然后我们只是正常绘制这两个东西,但只在没有模板缓冲区的2地方(或者1如果你想要的话),因此我们不在交叉点绘制任何东西:

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);  //draw something
glStencilFunc(GL_NOTEQUAL, 2, -1);      //draw everywhere except at intersection
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);    //leave the stencil buffer as is
//draw cube
//draw sphere

最后,完成后,我们再次禁用模板测试 ( glDisable(GL_STENCIL_TEST))。

这只是一个基本示例,但它应该让您开始使用非常强大的模板缓冲区。

目前,整个事情都取决于深度测试结果,这意味着它取决于您绘制对象的顺序。如果您希望它与深度无关(因此只考虑它们的 2D 屏幕投影),那么您可以要么在没有深度测试的情况下绘制你的对象,要么将第二个参数glStencilOp(这是模板测试通过但深度测试失败时执行的操作)GL_INCR也设置为 。

目前,它也仅在启用背面剔除时才有效,因为否则每个对象的模板值将增加两次(至少在忽略深度的情况下),并且对于非凸对象来说情况会更糟。也许您也可以使用其他模板操作来执行您的任务,但不幸的是,OpenGL ES 1 似乎不支持对模板值的二进制操作,也不支持包装操作(因此0再次递减0)。

编辑:好的,您真的想要 3D 对象之间的几何交集(或者说是看起来的差异)。那么OpenGL本身无法解决您的问题。OpenGL 不做任何其他事情,然后将简单的图元(点、线和三角形)绘制到屏幕上。它既不是场景管理系统,也不是几何库。您要实现的任务并不那么简单(尽管使用像立方体和球体这样的简单对象肯定会有所帮助),您可能需要寻找一些几何库来对生成的网格(或构造实体几何 (CSG))进行布尔运算适当的几何差异作为三角形网格,然后您可以像往常一样使用 OpenGL 绘制。

Another option, similar to your mentioned concept of a "3D stencil buffer" would be to discretize space using a regular grid and thus subdivide your objects into small voxels (3D pixels, think of small boxes). On those discrete finite voxel sets boolean operations are pretty easy. But of course this approach comes at the cost of introducing discretization error and performance overhead (operating on voxels means operating on large data sets, ok CSG isn't easy either, but has probably better complexity than O(n^3)). And you also have to recreate a renderable object from the voxel set again, either using some surface extraction method to get a mesh again, or just drawing small points or boxes.

In the end using a proper CSG library is probably your best bet, either way OpenGL doesn't have anything to do with it.

于 2013-02-27T15:01:59.780 回答