3d粒子和3d模型的透明度问题,libgdx

时间:2015-07-24 07:58:31

标签: libgdx transparency alphablending depth-testing

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

所以它似乎与距离三维粒子效果有关...

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和blendattribute尝试了很多不同的设置,但找不到任何有效的设置。

修改的 我从3d模型中删除了Blending属性,现在看起来应该关于粒子效果。但是我需要在我的角色模型上使用大多数材料进行混合设置..

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

我还尝试使用BillboardParticleBatch而不延长它,以防我在那里做了什么,但效果更糟。所有具有混合功能的模型都会出现在粒子效果的前面,即使它们位于它后面。

1 个答案:

答案 0 :(得分:0)

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

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

  • 首先,所有不透明对象都是从前到后渲染的(因为无论如何,不​​透明对象后面的任何内容都是不可见的,因此减少了对片段着色器的不必要调用。)
  • 其次,所有透明对象都是从后向前渲染的(因为只要呈现透明对象,那么之后呈现的所有内容都将在其后面显示,将无法显示。)

要确定对象是否透明,请使用BlendingAttribute#blended成员。 (所以如果你真的想,可以将该成员设置为false以强制它被处理(排序),就像它是不透明的一样)

因此,您调用ModelBatch#render的顺序不一定是它们实际执行的顺序。如果您想强制渲染您在中间添加到批处理中的任何内容,请调用ModelBatch#flush()。当然,这样做很多事情首先会破坏ModelBatch的一些目的。

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

也就是说,您可以尝试其他各种解决方案。例如。粒子的区域是完全透明的,因此片段着色器也可以将它们全部丢弃。尝试将FloatAttribute.AlphaTest的值0.5f添加到粒子中。如果这与你的混合混淆,那么逐渐减少到例如0.05f

此外,您可以添加DepthTestAttribute depthMask设置为falsenew DepthTestAttribute(false))。这将防止粒子写入深度缓冲区。 (但也可能导致其他事物出现在粒子前面。)