【问题标题】:Transparency issues with 3d particles and 3d models, libgdx3d 粒子和 3d 模型、libgdx 的透明度问题
【发布时间】:2015-07-24 07:58:31
【问题描述】:

我在透明度和 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 而不扩展它,以防我在那里做了一些事情,但效果会更糟。所有启用混合的模型都出现在粒子效果的前面,即使它们站在粒子效果的后面。

【问题讨论】:

  • 你确定先画模型吗?看起来粒子是先绘制的,它们在深度缓冲区中设置了较高的 Z 值,之后您的角色将不再呈现在粒子后面。
  • 我只是仔细检查了一下,我先渲染模型,然后在渲染粒子系统的模型之后,使用相同的模型批次。此外,如果您在视频的开头看到,您可以看到在火/粒子效果中可以看到一个木制棺材。该模型没有任何混合属性集。因此,只有设置了 blending 属性且距离不远的模型才会出现问题。
  • 在两者之间调用 flush() 或实现您的自定义 RenderableSorter。
  • flush() 工作,非常感谢。我可以问为什么这有帮助吗?另外,与使用 flush() 相比,编写自定义 renderalbe 排序器是否会获得很多性能?请做出回答,以便我给你信用

标签: libgdx transparency alphablending depth-testing


【解决方案1】:

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

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

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 2012-06-30
    相关资源
    最近更新 更多