1

我遇到了一些关于透明度和 3d 粒子的奇怪问题。一个简短的视频来说明: https ://youtu.be/ZHKI1X3MjhY 如您所见,我有一个 3d 粒子效果,火焰燃烧。里面是一个没有 alpha 混合的 3 模型,它显示得很好。然后在远处有一个小骨架(混合和alphatest打开),它在火中也显示得很好。然后我转动相机,看着战士骷髅,它就消失了,你看到的是他身后的东西。我再次转动相机,法师骨架也消失了,但你可以在更远的地方看到树木,它们具有完全相同的混合和 alpha 测试设置。如果我将角色移动到 20 码外,它也会开始通过火焰效果显示出来。

所以它似乎与3d粒子效果的距离有关......

3d 粒子批处理是一个扩展的 BillboardParticleBatch,如下所示:

protected Renderable allocRenderable(){

         BlendingAttribute ba=new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE,1f);

         Renderable r = super.allocRenderable();
         r.material = new Material(   ba,
//               new DepthTestAttribute(GL20.GL_LEQUAL, 0.0f, 0.5f, true),
//                r.material.set(new FloatAttribute(FloatAttribute.AlphaTest, 0.0f),
               TextureAttribute.createDiffuse(texture));

         return r;
   }

所有角色和树都是使用以下属性创建的:

if (alpha) {
         FloatAttribute floatAttribute = new FloatAttribute(FloatAttribute.AlphaTest, 0.5f);
         BlendingAttribute blendingAttribute = new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, 1f);
         for (int i = 0; i < bulletEntity.modelInstance.materials.size; i++){
               bulletEntity.modelInstance.materials.get(i).set(blendingAttribute);
               bulletEntity.modelInstance.materials.get(i).set(floatAttribute);
         }

      }

先绘制模型然后绘制粒子,我尝试更改顺序但没有区别。我已经为 alphatest、depthtest 和 blendingattribute 尝试了很多不同的设置,但找不到任何有效的设置。

编辑 我从 3d 模型中删除了 Blending 属性,现在它看起来应该与粒子效果有关。但是我需要我的角色模型上的大多数材料来设置混合..

当我启用混合时,任何人都知道为什么会发生这种情况?

我还尝试使用 BillboardParticleBatch 而不扩展它,以防我在那里做了什么,但效果更糟。所有启用混合的模型都出现在粒子效果的前面,即使它们站在粒子效果的后面。

4

1 回答 1

0

ModelBatch对您的渲染调用进行排序(检查此链接,真的,这是必读的),以避免不正确的行为(正如您所遇到的那样)。实际的排序/渲染发生在调用ModelBatch#end. 默认情况下,它使用DefaultRenderableSorter,这是默认实现。当然,由于该实现不了解您的场景,因此它可能不完全符合您的需求。

DefaultRenderableSorter尝试根据每个模型的变换矩阵猜测每个模型的位置。根据该位置和相机的位置,它将对它们进行排序,以便:

  • 首先,所有不透明对象都是从前到后渲染的(因为不透明对象后面的任何东西都是不可见的,因此减少了对片段着色器的不必要调用)。
  • 其次,所有透明对象都是从后到前渲染的(因为一旦渲染了透明对象,之后渲染的以及在其后面的所有内容都将不可见)。

要确定对象是否透明,使用BlendingAttribute#blended成员。(因此,如果您真的愿意,可以将该成员设置为 false 以强制将其视为(排序),就好像它是不透明的一样)

因此,您调用ModelBatch#render的顺序不一定是它们实际执行的顺序。如果您想强制渲染您添加到批处理中的任何内容,请调用ModelBatch#flush(). 当然,这样做一开始就违背了 ModelBatch 的某些目的。

相反,您可以实现自己的RenderableSorter,它对您的场景有更多的了解,因此可以比默认实现更好地进行排序。(但是,如果flush()对您有用并且没有其他问题,那么flush对您来说可能是最简单的解决方案)。

也就是说,您还可以尝试其他各种解决方案。例如,粒子的区域是完全透明的,因此片段着色器不妨将它们一起丢弃。尝试将FloatAttribute.AlphaTest值添加0.5f到粒子。如果这与您的混合混乱,则逐渐将值降低到 eg 0.05f

此外,您可以添加一个设置为( )的DepthTestAttribute 。这将阻止粒子写入深度缓冲区。(但也可能导致其他东西显示在粒子前面)。depthMaskfalsenew DepthTestAttribute(false)

于 2015-07-26T20:15:12.027 回答