Android OpenGL2.0两个纹理之间的交集

时间:2014-07-19 21:04:15

标签: android opengl-es opengl-es-2.0

我在OpenGL2.0中制作游戏并且我想检查两个精灵是否有交集,但我不需要检查两个矩形之间的交叉点。我有两个带纹理的精灵,一些纹理的一部分是透明的,有些则不是。我需要检查sprite之间的交集仅在不透明的部分。

示例:http://i.stack.imgur.com/ywGN5.png

2 个答案:

答案 0 :(得分:0)

确定两个精灵之间交集的最简单方法是使用Bounding Box方法。

对象1边界框:

vec3 min1 = {Xmin, Ymin, Zmin} 
vec3 max1 = {Xmax, Ymax, Zmax}

对象2边界框:

vec3 min2 = {Xmin, Ymin, Zmin} 
vec3 max2 = {Xmax, Ymax, Zmax}
  1. 您必须通过遍历精灵的顶点缓冲区数组来预先计算边界框。 http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box

  2. 然后在每个渲染帧期间检查边界框是否重叠(在CPU上计算)。

    a)首先转换Mins&最大的世界空间。

    min1WorldSpace = modelViewMatrix * min1

    b)然后检查它们的重叠。

  3.   

    我需要检查精灵之间的交叉点,而不仅仅是在没有透明的部分。

    根据您的场景,检查此测试用例可能很复杂。您可能必须将透明精灵分割为单独的精灵并计算其边界框。

    在您的示例中,透明对象看起来像是封装在不透明对象内部,因此很容易。只需计算两个边界框。

答案 1 :(得分:0)

我不认为使用ES 2.0有一种非常优雅的方式。 ES 2.0是OpenGL的一个非常小的版本,你开始突破它可以做的事情的界限。例如,在ES 3.0中,您可以使用查询,这对于很好地有效地解决这个问题非常有帮助。

在ES 2.0中可以做的是以某种方式绘制精灵,以便只有两个交叉点中的像素最终产生颜色。这可以通过使用模板缓冲区或混合来实现(请参阅下面的详细信息)。但是你需要找出是否有任何像素被渲染,并且ES 2.0中没有任何好的机制我可以想到这样做。我相信你几乎坚持使用glReadPixels()读取结果,然后检查CPU上的非黑色像素。

我必须避免回读整个图像的一个想法是反复下采样直到它达到1x1的大小。它最初将渲染到纹理,然后在每个步骤中,使用线性采样对当前纹理进行采样,渲染为一半大小的纹理。我相信这会有效,但我不确定它是否比回读整个图像更有效。

我不会提供建议解决方案的完整代码,但大纲如下所示。这是使用混合仅绘制交叉点中的像素。

  1. 设置一个附有RGBA纹理的FBO作为颜色缓冲区。大小不一定必须与屏幕分辨率相同。它只需要足够大,以便为您的交叉点提供足够的精度。
  2. 用明确的黑色清除FBO。
  3. 渲染第一个只有alpha输出的sprite,而不是混合。

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
    glDisable(GL_BLEND);
    // draw sprite 1
    

    这将精灵1的alpha值保留在帧缓冲区的alpha中。

  4. 使用目标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
    

    只有精灵1的alpha值非零时,才会使精灵2呈现颜色输出。

  5. 使用glReadPixels()回读结果。被读取的区域至少需要覆盖两个精灵的边界框。
  6. 添加已读取像素的所有RGB值。
  7. 如果产生的颜色不是黑色,则两个精灵之间会有重叠。