XNA透明纹理渲染问题

时间:2018-02-21 14:30:53

标签: c# xna rendering transparency alpha

以前曾经有过这个问题的一两个问题,但是我再也找不到了,所以我走了。

使用BasicEffect渲染具有部分透明纹理的模型时,基本解决方案是按照距离相机的距离对所有内容进行排序,然后从后向前绘制它们以获得正确的图像。然而,当模型彼此交叉时,较近的一部分将落后于另一部分,并且透明度将呈现不完整。

示例:

Render issue

两个相交的项目只有一个带纹理的矩形模型。 由于游戏最终将包含必须具有更多3维形状并且必须穿过其他物体的指示器,这对我来说是一个大问题,我找不到解决方案。

请帮助。谢谢,

zoliking

编辑:这是非常基本的,但为了完整起见,这里是绘图代码(减去不相关的绒毛):

private void sortDrawables()
        {
        float[] distances = new float[drawables.Length];

        for (int i=0; i<drawables.Length; i++)
            {
            if (drawables[i] is Character)
                {
                distances[i] = Vector3.Distance(cameraPosition, ((Character) drawables[i]).marker.position);
                }
                else if (drawables[i] is FixObject)
                {
                distances[i] = Vector3.Distance(cameraPosition, ((FixObject) drawables[i]).marker.position);
                }
                else if (drawables[i] is PositionSpike)
                {
                distances[i] = Vector3.Distance(cameraPosition, ((PositionSpike) drawables[i]).position);
                }
            }

        for (int i=0; i<drawables.Length; i++)
            {
            int largestIndex = i;
            float largestDistance = -1f;

            for (int j=i; j<drawables.Length; j++)
                {
                if (drawables[j] is Character)
                    {
                    if (Vector3.Distance(((Character) drawables[j]).marker.position, cameraPosition) > largestDistance)
                        {
                        largestDistance = Vector3.Distance(((Character) drawables[j]).marker.position, cameraPosition);
                        largestIndex = j;
                        }
                    }
                    else if (drawables[j] is FixObject)
                    {
                    if (Vector3.Distance(((FixObject) drawables[j]).marker.position, cameraPosition) > largestDistance)
                        {
                        largestDistance = Vector3.Distance(((FixObject) drawables[j]).marker.position, cameraPosition);
                        largestIndex = j;
                        }
                    }
                }

            float tempDistance = distances[i];
            distances[i] = distances[largestIndex];
            distances[largestIndex] = tempDistance;

            Object tempCharacter = drawables[i];
            drawables[i] = drawables[largestIndex];
            drawables[largestIndex] = tempCharacter;
            }
        }

    protected override void Draw(GameTime gameTime)
        {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        sb.GraphicsDevice.BlendState = BlendState.AlphaBlend;

        foreach (ModelMesh mesh in board.Meshes)
            {
            foreach (BasicEffect be in mesh.Effects)
                {
                UniversalLighting.MatchEffect(be);

                be.View = view;
                be.Projection = projection;
                be.World = Matrix.CreateTranslation(new Vector3(0, 0, 0));
                }
            mesh.Draw();
            }

        sortDrawables();

        foreach (Object c in drawables)
            {
            if (c is Character)
                {
                ((Character) c).Draw(projection, view, cameraPosition, animMatrix, sources);
                }
                else if (c is FixObject)
                {
                ((FixObject) c).Draw(projection, view, cameraPosition, sources, Matrix.Identity);
                }
                else if (c is PositionSpike)
                {
                ((PositionSpike) c).Draw(projection, view, orangePixel);
                }
            }

Character和FixObject类调用的绘图代码:

public void Draw(Matrix projection, Matrix view, Texture2D texture, Texture2D[] frontLights, Texture2D[] backLights, LightSource[] sources, GraphicsDevice gd, Vector3 cameraPosition, Matrix animMatrix, float rotation = 0f, Texture2D otherSide = null)
        {
        foreach (ModelMesh m in model.Meshes)
            {
            foreach (BasicEffect be in m.Effects)
                {
                UniversalLighting.MatchEffect(be);

                be.TextureEnabled = true;
                be.Texture = texture;

                be.View = view;
                be.Projection = projection;
                be.World =  Matrix.CreateScale(new Vector3(stretch.X*-1, stretch.Y*-1, 1)) *
                            Matrix.CreateRotationY(rotation) *
                            animMatrix *
                            Matrix.CreateTranslation(position - new Vector3(0, stretch.Y/-2*MODEL_SIZE, 0) + rotNormal * 0.0005f * orderify);
                }
            m.Draw();
            }

        if (otherSide != null)
            {
            foreach (ModelMesh m in model.Meshes)
                {
                foreach (BasicEffect be in m.Effects)
                    {
                    UniversalLighting.MatchEffect(be);

                    be.TextureEnabled = true;
                    be.Texture = otherSide;

                    be.View = view;
                    be.Projection = projection;
                    be.World =  Matrix.CreateScale(new Vector3(stretch.X, stretch.Y*-1, 1)) *
                                Matrix.CreateRotationY(rotation + (float) Math.PI * 2) *
                                animMatrix *
                                Matrix.CreateTranslation(position - new Vector3(0, stretch.Y/-2*MODEL_SIZE, 0) + rotNormal * -0.0005f * orderify);
                    }
                m.Draw();
                }
            }
        }

编辑2:所以我刚刚发现了一篇文章,它解决了这个问题,因为它不能通过排序(duh)来解决,但必须有某种渲染技巧才能允许这样做。图形应用程序在编辑器窗口中实时渲染这样的情况,任何使用纹理平面模型的3D粒子效果都必须处理这个问题。

基本上所有需要做的就是检测冲突像素的位置(如必须在已经绘制透明度的对象后面绘制的东西),并且在重叠区域中执行较慢的基于光线的方法来确定像素颜色。如果内置任何内容,我会很乐意手动编写,但我不知道如何深入了解渲染细节。

0 个答案:

没有答案