C# 深度缓冲和Alpha问题

C# 深度缓冲和Alpha问题,c#,xna,.net-4.5,C#,Xna,.net 4.5,我已经做了将近10个小时了,一直在绕圈,试图让Alpha透明度与深度缓冲区一起工作。我很确定是什么导致了我的问题,因为我需要根据透明模型离相机的距离从后到前绘制它们,但我似乎无法让它正常工作。任何帮助都将不胜感激,但请不要提供与订单无关的透明度 其外观的图像: 如您所见,左侧的球体正在通过观察球体流血,右侧的球体正在按其应有的方式混合。首先绘制右侧球体,然后绘制观察球体,最后绘制左侧球体 代码片段: 每个实体都有自己的绘图功能,如下所示: public void Draw() { var

我已经做了将近10个小时了,一直在绕圈,试图让Alpha透明度与深度缓冲区一起工作。我很确定是什么导致了我的问题,因为我需要根据透明模型离相机的距离从后到前绘制它们,但我似乎无法让它正常工作。任何帮助都将不胜感激,但请不要提供与订单无关的透明度

其外观的图像:

如您所见,左侧的球体正在通过观察球体流血,右侧的球体正在按其应有的方式混合。首先绘制右侧球体,然后绘制观察球体,最后绘制左侧球体

代码片段:

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

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();
    }
}
从主绘图函数调用绘图:

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));
每一列都属于同一帧,其中包含一个以透明方式渲染或完全不渲染的块。当有透明度时,一些会被切割,但当没有透明度时,所有会被切割

edit2:请求源项目:(已删除)


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

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

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

foreach (EntityModel mdl in Globals.MainObjects.Where(m => m.alpha>=1)
{
    mdl.Draw();
}
使用depthstate。读取以绘制透明:

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();
        } 

谢谢,不过我已经试过了。它会导致某些模型在透明墙上绘制。(图:)由于没有排序,我又回到了原来的问题。(图:)但是有些模型是在透明的墙上吗?你确定图像不对吗?我认为当你混合模型时,顺序并不重要,因为像素最终颜色将是每个模型中两个像素的混合。您只需先绘制不透明,填充深度缓冲区,然后在读取模式下使用深度缓冲区在末尾绘制透明模型,以隐藏不透明模型后面的像素。不使用上述代码的任何排序形式,就会发生这种情况:如您所清楚看到的,右侧的球体应该位于中心球体后面,但它是在顶部渲染的。
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();
        } 
var worldMatrix = Transform * MathConverter.Convert(entity.WorldTransform);

var camera = (Game as Game1).camera;

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