深度缓冲和Alpha问题

时间:2014-09-07 04:51:32

标签: c# xna .net-4.5

我已经在这里玩了近10个小时,试图让Alpha透明度与深度缓冲区一起工作。我相当肯定导致我的问题的是我需要根据它们与相机的接近程度从后到前绘制我的透明模型,但我似乎永远不会让它正常工作。任何帮助将不胜感激,但请不提供与订单无关的透明度

它的外观图像:http://i.imgur.com/2zV99HN.png

正如你所看到的,左边的球体正在通过观察球体流出,右边的球体正在混合。首先绘制右侧球体,第二次绘制观察,最后绘制左侧绘制。

代码剪辑:

每个实体都拥有自己的绘图功能,如下所示:

public void Draw()
{
    var worldMatrix = Transform *  MathConverter.Convert(entity.WorldTransform);

    model.CopyAbsoluteBoneTransformsTo(boneTransforms);
    foreach (ModelMesh mesh in model.Meshes)
    {
        foreach (BasicEffect effect in mesh.Effects)
        {
            effect.Alpha = alpha;

            //If we have a texture enable it and set it, then remove colour
            if (texture != null)
            {
                effect.TextureEnabled = true;

                //Texture2D ModifiedTexture = new Texture2D()
                effect.Parameters["Texture"].SetValue(texture);

                //But only if colour isn't set
                if (colour == null)
                    effect.AmbientLightColor = Color.White.ToVector3();
            }
            else
            {
                effect.TextureEnabled = false;
                effect.AmbientLightColor = Color.Brown.ToVector3();
            }

            //If colour is set and isn't what we want, thrn set it to the lighting of the model
            if (colour != null && effect.AmbientLightColor != colour.ToVector3())
                effect.AmbientLightColor = colour.ToVector3();

            effect.World = boneTransforms[mesh.ParentBone.Index] * worldMatrix;
            effect.View = MathConverter.Convert((Game as Game1).camera.ViewMatrix);
            effect.Projection = MathConverter.Convert((Game as Game1).camera.ProjectionMatrix);
        }
        mesh.Draw();
    }
}

从Draw主函数中调用绘图:

foreach (EntityModel mdl in Globals.MainObjects)
{
    if (mdl.alpha >= 1)
    {
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        GraphicsDevice.BlendState = BlendState.Opaque;

        mdl.Draw();
    }
    else
    {
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        GraphicsDevice.BlendState = BlendState.AlphaBlend;

        mdl.Draw();
    }
}

要绘制的实体的LinkedList当前的排序方式如下:

if (MainObjects.Count() >= 1)
    MainObjects = new LinkedList<EntityModel>(MainObjects.OrderByDescending(i => i.alpha).ThenBy(l => l.entity.InstanceId));

TL; DR 我需要根据相机的深度对模型进行排序,但不知道该怎么做,我正在寻找需要做什么的帮助以及如何它可以完成或原始代码可以做到这一点。

编辑:目前在面临不同问题方面取得了少量进展。 按DepthIndex排序(见下文)会根据相机的角度导致某种形式的裁剪。

DepthIndex = Microsoft.Xna.Framework.Vector3.Transform(MathConverter.Convert(entity.Position), MathConverter.Convert((Game as Game1).camera.ViewMatrix * (Game as Game1).camera.ProjectionMatrix)).Z;

每一列都是同一帧,其中一个块是透明呈现的,或者根本不呈现。当有透明度的时候会有一些被剪掉,但是当没有透明度的时候会出现这种情况。

edit2:按要求提供源项目:(已删除)

它是用VS2013 XNA4.0 .NET-4.5编写的。

1 个答案:

答案 0 :(得分:1)

首先绘制不透明模型并忘记排序,dephtbuffer将管理它:

GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque;

foreach (EntityModel mdl in Globals.MainObjects.Where(m => m.alpha>=1)
{
    mdl.Draw();
}

使用depthstate.Read for draw transparent:

GraphicsDevice.DepthStencilState = DepthStencilState.Read;
GraphicsDevice.BlendState = BlendState.AlphaBlending;

foreach (EntityModel mdl in Globals.MainObjects
      .Where(m => m.alpha < 1 && m.alpha > 0)
      .OrderBy(m => m.DepthIndex))
        {
            mdl.Draw();
        } 

EntityModel.cs / Update方法

var worldMatrix = Transform * MathConverter.Convert(entity.WorldTransform);

var camera = (Game as Game1).camera;

DepthIndex = Matrix.Multiply(worldMatrix,MathConverter.Convert(camera.ViewMatrix))
                   .Translation.Z;
相关问题