0

For an academic project I'm trying to write a code for drawing billboards from scratch; now I'm at the point of making them translucent. I've managed to make them look good against the background but they still may cover each other with their should-be-transparent corners, like in this picture:

I'm not sure what I'm doing wrong. This is the effect file I'm using to draw the billboards. I've omitted the parts related to the vertex shader, which I think is irrelevant right now.

//cut

texture Texture;
texture MaskTexture;

sampler Sampler = sampler_state
{
    Texture = (Texture);

    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Point;

    AddressU = Clamp;
    AddressV = Clamp;
};

sampler MaskSampler = sampler_state
{
    Texture = (MaskTexture);

    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Point;

    AddressU = Clamp;
    AddressV = Clamp;
};

//cut

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float4 Color : COLOR;
    float2 TexCoord : TEXCOORD0;
};

//cut

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 result = tex2D(Sampler, input.TexCoord) * input.Color;
    float4 mask = tex2D(MaskSampler, input.TexCoord);
    float alpha = mask.r;
    result.rgb *= alpha;
    result.a = alpha;
    return result;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();

        AlphaBlendEnable = true;
        SrcBlend = SrcAlpha;
        DestBlend = InvSrcAlpha;
    }
}

I've got two textures, named Texture and MaskTexture, the latter being in grayscale. The billboards are, most likely, in the same vertex buffer and are drawn with a single call of GraphicsDevice.DrawIndexedPrimitives() from XNA.

I've got a feeling I'm not doing the whole thing right.

kamilk
  • 3,829
  • 1
  • 27
  • 40
  • Have you enabled GL_BLEND ? Look at the GL_BLEND section here http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml – Ani Jun 13 '12 at 18:49
  • @ananthonline Sorry, I have hidden the info that the project is in XNA, not OpenGL, somewhere at the end of the post. Well, actually the only thing I've done (or at least can remember doing) to enable blending is adding `AlphaBlendEnable = true;` to the `pass` block. Isn't it enough? – kamilk Jun 13 '12 at 18:54
  • I can't actually see anything wrong with your HLSL, try changing your pixel shader to just return the value taken from your mask texture to makes sure that it's being used in the way that you intended.Also what is your backbuffer format? – Andy Jun 13 '12 at 21:28

2 Answers2

0

You have to draw them in order. From farthest to closest.

Steve H
  • 5,479
  • 4
  • 20
  • 26
0

I have found a solution. The shaders are fine, the problem turned out to be in the XNA code, so sorry for drawing your attention to the wrong thing.

The solution is to enable a depth stencil buffer (whatever it is) before drawing the billboards:

device.DepthStencilState = DepthStencilState.DepthRead;

It can be disabled afterwards:

device.DepthStencilState = DepthStencilState.Default;
kamilk
  • 3,829
  • 1
  • 27
  • 40