1

假设我有一个正方形'S'。我需要让一个圆圈“C”穿过它,这样 S 会裂开,C 会穿过它。虽然我需要给它一个 3D 效果,但 2D 也可以(至少我会抢先一步)。有没有办法使用一些内置功能来做到这一点,或者可以转换单个像素或对象的一部分?我不确定您如何在对象内映射一个孔,但是您可以使用背景颜色制作具有孔形状的对象,使其看起来像一个孔,对吗?但真正的问题是如何让正方形裂开?(两半会以某种方式分开然后重新加入)。

4

1 回答 1

2

好的,因为“您希望圆圈随着时间的推移(从一帧到另一帧)移动,而正方形在圆圈所在的地方和曾经的地方消失”,它只是 2D 的,你可以为此使用模板缓冲区。

模板缓冲区基本上为每个像素存储一个整数值,并允许您更改此值并将其与新绘制的像素进行比较,以便从绘制中排除像素。所以我们要做的就是将圆形绘制到模板缓冲区中(在圆形像素所在的地方将其设置为 1),然后在没有绘制圆形像素的地方绘制正方形(在模板缓冲区为 0 的地方)。与“通常”的唯一区别模板方法是,我们不会清除帧之间的模板缓冲区,因此无论圆曾经是什么,它都会保留圆的值。因此,当您随着时间的推移在屏幕上扫过圆圈时,将不会在圆圈像素曾经所在的任何地方绘制正方形(当然,与绘制像素相同的时间离散化错误,例如圆圈应该在的地方,但不是因为它在帧之间移动得太快)。

因此,首先我们将圆圈绘制到模板缓冲区中(如果您只想将圆圈用于模板而不在屏幕上绘制实际的圆圈,您可以使用 禁用颜色写入glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);,但不要忘记之后重新启用颜色写入):

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   //but don't clear stencil

glEnable(GL_STENCIL_TEST);    //use stenciling

glStencilFunc(GL_ALWAYS, 1, -1);    //draw everywhere, use 1 as ref value
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);   //set pixels to ref value (1)
//draw circle

glStencilFunc(GL_NOTEQUAL, 1, -1);    //draw wherever not 1 (no circle pixels)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);    //leave stencil values unchanged
//draw square

这只是一个基本的例子。您也可以将模板缓冲区用于其他用途。目前,无论它是否位于另一个已绘制对象的后面,圆圈都会更改模板值,但这可以通过更改值来微调glStencilOp(根据模板测试是否失败,配置如何更改模板值,成功和深度测试失败,或两者都成功),同时glStencilFunc控制要执行什么测试以及针对哪个参考值(新绘制对象的值)。但是这个例子和链接的文档应该让你开始处理这个问题。

但请记住,模板缓冲区实际上是用于“即时”图像空间模板操作。如果这变得更加复杂并且您需要对对象执行实际的几何操作,或者如果这需要在 3D 中完成(关键字:Constructive Solid Geometry (CSG)),那么 OpenGL 不是该工作的正确工具,并且在在这种情况下,一个实际的几何库将是最好的主意。OpenGL 所做的只是在屏幕上绘制简单的东西(如点、线或三角形),仅此而已。它既不是场景管理,也不是几何图形,也不是图像处理库(尽管对于后者来说它可能被“误用”并不那么困难)。

于 2013-04-15T11:30:13.037 回答