Question

I am using XNA, implementing the HLSL shader and i have a problem with transparency

in the shader; When rendering two models and they are facing each other the model behind is seen only

when it is first rendered

Let me explain...

blue cone = vector3(0,0,0) - first target

green cone = vector3(50,0,50) - second target

here rendering blue first and then the green and blue cone is seen

can see

now the other way before the green then blue and you do not see

cannot see

As long as they are two cones I can calculate the distance from the camera and render

before the most distant (the only solution I found by searching on the net), but if I

have several models and sizes, it can happen that a model A is most distant of a model B

but that its size may lead him to hide the model B.

Here put some code i use

.fx file

float4x4 World;
float4x4 View;
float4x4 Projection;

float3 Color;
texture ColorTexture : DIFFUSE ;

sampler2D ColorSampler = sampler_state {
    Texture = <ColorTexture>;
    FILTER = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};  

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float3 UV       : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float3 UV       : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    float4 projPosition = mul(viewPosition, Projection);

    output.Position = projPosition;
    output.UV = input.UV;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 map = tex2D(ColorSampler,input.UV);
    return float4(map.rgb * Color, map.a);
}

technique Textured
{
    pass Pass1
    {
        ZEnable = true;
        ZWriteEnable = true;
        AlphaBlendEnable = true;
        DestBlend = DestAlpha;
        SrcBlend=BlendFactor;

        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}

draw code in XNA project

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.DarkGray);

        for (int i = 0; i < 2; i++)
        {
            ModelEffect.Parameters["View"].SetValue(this.View);
            ModelEffect.Parameters["Projection"].SetValue(this.Projection);
            ModelEffect.Parameters["ColorTexture"].SetValue(this.colorTextured);

            ModelEffect.CurrentTechnique = ModelEffect.Techniques["Textured"];
            Vector3 Scala = new Vector3(2, 3, 1);

            if (i == 0)
            {
                World = Matrix.CreateScale(Scala) * Matrix.CreateWorld(FirstTarget, Vector3.Forward, Vector3.Up);
                ModelEffect.Parameters["Color"].SetValue(new Vector3(0, 0, 255));// blu
            }
            else
            {
                World = Matrix.CreateScale(Scala) * Matrix.CreateWorld(SecondTarget, Vector3.Forward, Vector3.Up);
                ModelEffect.Parameters["Color"].SetValue(new Vector3(0, 255, 0));// verde
            }
            ModelEffect.Parameters["World"].SetValue(World);

            foreach (ModelMesh mesh in Emitter.Meshes)
            {
                foreach (ModelMeshPart effect in mesh.MeshParts)
                {
                    effect.Effect = ModelEffect;
                }
                mesh.Draw();
            }
        }

        base.Draw(gameTime);
    }

the for cycle I need for chage sort rendering...

Is there any procedure to be able to work around this problem? I hope I explained myself, I think we should work on the file .fx ...or not? I'm on the high seas :)

Was it helpful?

Solution

This is a classic computer graphics problem -- what you'll need to do depends on your specific model and need, but transparency is as you've discovered order dependent -- as Nico mentioned, if you sort entire meshes back-to-front (draw the back ones first) for each frame, you will be okay, but what about curved surfaces that need to draw sometimes in front of themselves (that is, they are self-occluding from the camera's point of view)? Then you have to go much farther and sort the polys within the mesh (adios, high performance!). If you don't sort, chances are, the order will look correct on average 50% or less of the time (unless your model is posed just right).

If you are drawing transparent cones, as they rotate to different views they will look correct sometimes and wrong other times, if two-sided rendering is enabled. Most of the time wrong.

One option is to just turn off depth-write buffering during the pass(es) where you draw the transparent items. Again, YMMV according to the scene's needs, but this can be a useful fix in many cases. Another is to segment the model and sort the meshes.

In games, many strategies have been followed, including re-ordering the models by hand, forcing the artists to limit transparency to certain passes only, drawing two passes per transparent layer (one with transparent color, and another with opaque but no color write to get the Z buffer correct), sending models back for a re-do, or even, if the errors are small or the action is fast, just accepting broken transparency.

There have been various solutions proposed to this general problem -- "OIT" (Order Independent Transparency) is a big enough topic to get its own wikipedia page: http://en.wikipedia.org/wiki/Order-independent_transparency

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top