4
\$\begingroup\$

In XNA, is it possible to merge two alpha blended sprites so they look like one contiguous shape, eliminating the merge of colour at the overlap? At the moment when I try, the intersection is quite visible:

two circles with overlap

I'd like it to look more like this mockup:

two merged circles

This is the drawing code for this example, but it's similar to what's being used in the actual game:

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

        spriteBatch.Begin(SpriteSortMode.FrontToBack, null, SamplerState.PointClamp, null, null);

        for (int x = 10; x <= 1000; x += 10)
            for (int y = 10; y <= 1000; y += 10)
                spriteBatch.Draw(Content.Load<Texture2D>("dot"), new Vector2(x, y), null, Color.Gray, 0, Vector2.Zero, 1, SpriteEffects.None, 0.1f);

        spriteBatch.Draw(Content.Load<Texture2D>("circle"), new Vector2(200, 200), null, Color.FromNonPremultiplied(255, 255, 255, 50), 0, Vector2.Zero, 1, SpriteEffects.None, 0.5f);
        spriteBatch.Draw(Content.Load<Texture2D>("circle"), new Vector2(300, 200), null, Color.FromNonPremultiplied(255, 255, 255, 50), 0, Vector2.Zero, 1, SpriteEffects.None, 0.5f);

        spriteBatch.End();

        base.Draw(gameTime);
    }

I suspect the answer is somehow combining the textures before passing them to the spritebatch to be drawn, but I'd prefer to avoid that if at all possible.

Thanks for any help!

\$\endgroup\$
  • \$\begingroup\$ from your definition it is not defined how you want to blend in the colors. You can already get what you showed in your images by disabling alpha blending and set the color of your circle to a dark blue. \$\endgroup\$ – Arne Jan 30 '14 at 0:40
  • 3
    \$\begingroup\$ @Arne but then you can't see the dots, which from the layers in the code above are drawn behind the circles. \$\endgroup\$ – Kieran Jan 30 '14 at 0:49
  • \$\begingroup\$ in opengl there is a command glBlendFunc that is basically what you would need to use if you would use opengl, try searching the XNA equivalent. \$\endgroup\$ – Arne Jan 30 '14 at 0:55
  • \$\begingroup\$ @Arne can you tell which combination of blend functions will result in that behavior? \$\endgroup\$ – Ali1S232 Jan 30 '14 at 9:22
  • \$\begingroup\$ I am sorry, I thought about it, and it is quite limited what you can do with the blend function. It looks like glBlendEquation(GL_MAX) would do what is on the image, but I am not sure weather it also works as you want it to work on other images. \$\endgroup\$ – Arne Jan 30 '14 at 22:52
2
\$\begingroup\$

You can try drawing on a texture in memory without alpha and then draws the result with the desired value of alpha.

This link tells you how to draw texture memory: http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series3/Render_to_texture.php

\$\endgroup\$
1
\$\begingroup\$

This is when I'd bust out the stencil buffer. It's like the depth buffer in that it's a per-pixel mask you can exploit for various effects. Your particular scenario is exceptionally well suited for its use.

When creating your GraphicsDeviceManager, you can configure the depth stencil format to request a format with some number of bits allocated for stencil operations. Once you have that, the rendering process is, at a high level, this:

  1. Enable the stencil test and clear the stencil buffer to all 0.
  2. Configure the stencil test to only accept new pixels where the stencil values are 0 AND to increment the stencil buffer value when a new pixel is accepted.
  3. Draw all the shapes you want to mask this way.
  4. Disable the stencil test.

What this does is prevent you from drawing to the same pixel twice because the stencil buffer will fail it.

I don't have code off hand but this answer seems to be a decent quick sample of using the stencil buffer. The other good resource for this is going to be the DepthStencilState documentation which exposes all the options for stencil tests.

Now there are some issues that will crop up with transparent sprites since the transparent pixels will still pass through the stencil test (thus your stencil will really be a rectangle, not the circle you see). The example code I linked uses an alpha test effect which should take care of that by discarding any transparent pixels, though I've not actually tried it myself.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.