【问题标题】:Issue with transparent texture on 3D primitive, XNA 4.03D 基元 XNA 4.0 上的透明纹理问题
【发布时间】:2011-01-13 17:18:03
【问题描述】:

我需要绘制一大组立方体,每边都有(可能)独特的纹理。一些纹理还具有部分透明度。透明纹理后面的立方体应该通过透明纹理显示。但是,似乎我绘制立方体的顺序决定了透明度是否有效,这是我想要避免的。看这里:

cubeEffect.CurrentTechnique = cubeEffect.Techniques["Textured"];

Block[] cubes = new Block[4];
cubes[0] = new Block(BlockType.leaves, new Vector3(0, 0, 3));
cubes[1] = new Block(BlockType.dirt, new Vector3(0, 1, 3));
cubes[2] = new Block(BlockType.log, new Vector3(0, 0, 4));
cubes[3] = new Block(BlockType.gold, new Vector3(0, 1, 4));


foreach(Block b in cubes) {
    b.shape.RenderShape(GraphicsDevice, cubeEffect);
}

这是 Draw 方法中的代码。它产生这个结果:

如您所见,叶子立方体后面的纹理在另一侧不可见。当我在数组中反转索引 3 和 0 时,我得到这个:

很明显,绘制顺序正在影响立方体。我怀疑这可能与混合模式有关,但我不知道从哪里开始。

【问题讨论】:

    标签: c# xna textures


    【解决方案1】:

    您依靠深度缓冲来实现遮挡。此技术仅适用于不透明对象。

    为包含透明对象的场景实现正确的遮挡:

    1. 设置 DepthBufferEnable 和 DepthBufferWriteEnable 为真

    2. 绘制所有不透明的几何体

    3. 将 DepthBufferEnable 设置为 true, 但将 DepthBufferWriteEnable 更改为 假的

    4. 按 Alpha 混合对象排序 与相机的距离,然后绘制 它们按从后到前的顺序排列

    摘自 Shawn Hargreaves 的 Depth sorting alpha blended objects

    【讨论】:

      【解决方案2】:

      正确绘制透明对象比普通对象更难。原因是在默认情况下渲染面部时,它会将所有像素标记为在特定深度绘制,结果后面的像素根本不会被绘制。我建议你买一本关于 3d 渲染的书,并仔细阅读以了解更多细节。

      您已经找到的最简单的方法 - 在不透明对象之后绘制透明对象。适用于透明和半透明对象。请注意,透明对象需要排序才能正确绘制(与非透明对象不同)。

      在您的特定情况下(非半透明),您可以将纹理渲染更改为不为透明部分渲染任何内容。

      【讨论】:

      • 如果您只有实体或“非实体”的对象,那么您可以维护两个列表并首先呈现实体。然后,非实体可以在最后渲染并对其进行排序,因此您首先渲染最远的对象。如果您的对象混合了可以是实心/非实心的多边形,您可能最好考虑实现某种形式的多通道系统,在该系统中您传递给您的渲染代码,然后您可以过滤多边形那时关于你是否在这个过程中渲染(你仍然需要排序)。
      【解决方案3】:

      如果对象上没有半透明像素,您也许可以使用它。它要么完全渲染,要么不会写入 Z-Buffer。 如Riemers Alpha Testing

      【讨论】:

      • 这可能适用于 XNA 3.1,但不幸的是,4.0 不支持 AlphaTest 功能。
      • 我目前使用 XNA 本身的经验非常有限,但是现在 XNA 4 中似乎有一个内置的 AlphaTestEffect,我不确定它是否存在使其适用于所有 3 个平台和隐藏魔法,或者您是否也可以了解它在内部的作用。它现在可能也足以满足您的需求。
      • 我发现了 AlphaTestEffect,并尝试使用它,但我一定在某个地方搞砸了,因为结果完全错误。我将在实体块之后绘制透明块。
      【解决方案4】:

      XNA(以及 DirectX 和所有主要的 3D 库)考虑了名为 culling 的东西。尽管从您的代码中我无法确定,但从图像中我认为这是您的问题。您看不到的多边形的顶点顺序错误。如果这是问题所在,您有两种解决方案:

      • 要么关闭剔除(device.RenderState.CullMode = CullMode.None;,如果我没记错的话)
      • 应用纹理两次,多边形的点按顺时针和逆时针顺序排列

      【讨论】:

      • 我知道剔除是什么,我认为这不是问题所在。正如我在示例中所展示的,通过反转立方体的数组索引,它显示后面的纹理,没问题。我认为问题在于首先绘制了叶子立方体,并且该纹理中的 alpha 与背景混合(没有其他立方体)。之后,绘制其他立方体,但叶子纹理没有与这些立方体混合。这只是一个理论,但我认为它是正确的。
      • 另外,如果我将相机移动到叶子立方体内,我可以看到其他立方体的纹理。
      • 我明白了。然后我认为您需要发布更多代码,例如您的效果是什么样的以及 Block 如何启动和绘制顶点。
      • @Andrei Pana - 你可以在这里找到:stackoverflow.com/questions/4674804/…
      • 效果是在 Reimers XNA 教程中找到的。
      猜你喜欢
      • 2014-11-25
      • 2012-01-24
      • 1970-01-01
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多