我在OpenGL2.0中制作游戏,我想检查两个精灵是否有交集,但我不需要检查两个矩形之间的交集。我有两个带有纹理的精灵,纹理的一部分是透明的,另一部分不是。我只需要在非透明部分检查精灵之间的交集。
示例:https://i.stack.imgur.com/ywGN5.png
确定两个精灵之间相交的最简单方法是使用Bounding Box方法。
对象1边界框:
vec3 min1 = {Xmin, Ymin, Zmin}
vec3 max1 = {Xmax, Ymax, Zmax}
对象2边界框:
vec3 min2 = {Xmin, Ymin, Zmin}
vec3 max2 = {Xmax, Ymax, Zmax}
你必须通过遍历你的精灵的顶点缓冲数组来预先计算边界框。http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box
然后在每个渲染帧中检查边界框是否重叠(在CPU上计算)。
a)首先转换min &最大的世界空间。
min1WorldSpace = modelViewMatrix * min1
我只需要在非透明部分检查精灵之间的交集。
检查这个测试用例可能很复杂,这取决于你的场景。你可能需要将透明精灵分割成一个单独的精灵,并计算它们的边界框。
在你的例子中,看起来透明对象被封装在一个不透明对象中,所以很容易。只需计算两个边界框
我不认为在ES 2.0中有一种非常优雅的方式来做到这一点。ES 2.0是OpenGL的一个非常小的版本,你开始推动它所能做的界限。例如,在ES 3.0中,您可以使用查询,这将非常有助于有效地解决这个问题。
在ES 2.0中可以做的是以一种方式绘制精灵,以便只有在两者相交的像素最终产生颜色。这可以通过使用模板缓冲或混合(见下面的详细信息)来实现。但接下来你需要知道是否有像素被渲染了,在ES 2.0中我没有想到好的机制来做到这一点。我相信你几乎坚持读回结果,使用glReadPixels()
,然后检查CPU上的非黑色像素。
为了避免读取整个图像,我必须反复对其进行下采样,直到它达到1x1的大小。它最初会渲染到一个纹理,然后在每一步中,用线性采样对当前纹理进行采样,渲染到一半大小的纹理。我相信这将工作,但我不确定它是否会比只是读取整个图像更有效。
我不会提供建议的解决方案的完整代码,但是大纲看起来是这样的。这是使用混合只绘制在交叉点的像素。
- 设置带有RGBA纹理的FBO作为颜色缓冲。大小不一定要与屏幕分辨率相同。它只需要足够大,给你足够的交叉精度。
- 清除FBO,颜色为黑色。
-
渲染第一个精灵,只有alpha输出,没有混合。
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glDisable(GL_BLEND); // draw sprite 1
这将使精灵1的alpha值留在framebuffer的alpha值中。 用目标alpha混合渲染第二个精灵。透明像素需要在其RGB组件中有黑色才能正常工作。如果不是这样,改变片段着色器来创建预相乘的颜色(将
rgb
的输出乘以a
)。glColorMask(GL_TRUE GL_TRUE, GL_TRUE, GL_TRUE); glBlendFunc(GL_DST_ALPHA, GL_ZERO); glEnable(GL_BLEND); // draw sprite 2
这只会在sprite 1的alpha值不为零的地方呈现sprite 2的颜色输出。
- 使用
glReadPixels()
回读结果。被读取的区域需要至少覆盖两个精灵的边界框。 - 将所有读取的像素的RGB值相加。
- 如果生成的颜色不是黑色,则两个精灵之间存在重叠。