3

我正在尝试使用点精灵来实现烟花,然后通过将烟花渲染到两个不同的纹理来绘制轨迹,然后每隔一次将它们相互拉回,并将 alpha 设置为 < 1,从而使之前的每次绘制逐渐消失。

它看起来不错,并且取决于我在绘制先前渲染的纹理时使用的 alpha,轨迹会变长或变短,正如预期的那样。但是,在大多数设备(不是全部)上,这些轨迹永远不会完全消失。在它们应该消失之后,它们会留下非常透明但仍然引人注目的痕迹。

这就是我目前所做的:

根据名为 second 的布尔值,我将帧缓冲区设置为渲染到名为 buff1 和 buff2 的两个纹理之一。

((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, myFBO.get(0));
if (second){
    ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, buff2.texture.textureId, 0);
} else {
    ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, buff1.texture.textureId, 0);
}
gl.glViewport(0, 0, bufferSize, bufferSize);
gl.glClearColor(0, 0, 0, 0);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

然后我在当前的纹理上渲染之前绘制的纹理,使用的 alpha 值 < 1。buff 对象只是绘制带有纹理的四边形的助手。draw 函数将 alpha 预乘到其他颜色通道。

// a = alpha, higher value = longer trails = more distinct leftovers
if (second){
    buff1.setColor(1, 1, 1, a);
    buff1.draw(gl);
    second = false;
else {
    buff2.setColor(1, 1, 1, a);
    buff2.draw(gl);
    second = true;
}

之后我绘制点精灵烟花。还使用预乘 alpha 和 gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

最后,我重置了帧缓冲区,并让我的新纹理包含了旧轨迹的褪色和顶部的当前烟花以 100% 的 alpha 绘制。然后我使用这个纹理与烟花纹理后面和前面的所有其他对象一起绘制到我的场景中。

正如我所说,几乎一切都在工作,除了那些几乎透明的痕迹在痕迹应该已经消失后留下。绘制前一个缓冲区的 alpha 值越高,永久保留的痕迹“剩余物”就越明显。

我一直在尝试不同的混合模式,预乘而不是预乘 alpha 等。但由于这是一个 android opengl es 1.1,我认为混合应该是 GL_ONE 和 GL_ONE_MINUS_SRC_ALPHA,因为默认情况下所有位图都是预乘的。

我究竟做错了什么?有一个更好的方法吗?

感谢您的帮助,安德斯

4

1 回答 1

2

我究竟做错了什么?

您对缩小(在它们的值中)图像求和的方式实际上是一个幂级数,可以将您的 alpha 值指数化。这样的幂级数将渐近为零,但永远不会达到它。

有一个更好的方法吗?

其实这是正确的做法。您刚刚忘记了最后一步:您希望添加一些阈值,以便将低于某个 alpha 值的值限制为零。最容易做到这一点的是添加 GL_GREATER alpha 测试,阈值略高于您想要删除的轨迹的 alpha 值。

于 2012-07-05T11:19:28.440 回答