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



我在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}
  1. 你必须通过遍历你的精灵的顶点缓冲数组来预先计算边界框。http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box

  2. 然后在每个渲染帧中检查边界框是否重叠(在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的大小。它最初会渲染到一个纹理,然后在每一步中,用线性采样对当前纹理进行采样,渲染到一半大小的纹理。我相信这将工作,但我不确定它是否会比只是读取整个图像更有效。

我不会提供建议的解决方案的完整代码,但是大纲看起来是这样的。这是使用混合只绘制在交叉点的像素。

  1. 设置带有RGBA纹理的FBO作为颜色缓冲。大小不一定要与屏幕分辨率相同。它只需要足够大,给你足够的交叉精度。
  2. 清除FBO,颜色为黑色。
  3. 渲染第一个精灵,只有alpha输出,没有混合。

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
    glDisable(GL_BLEND);
    // draw sprite 1
    
  4. 这将使精灵1的alpha值留在framebuffer的alpha值中。
  5. 用目标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的颜色输出。

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

最新更新