[SOLVED] Drawing a texture over a mask texture

Hi,

How can I draw a texture over another texture serving as a mask without using shaders?

Here’s an example of what I want. Note that instead the black background I want it to be transparent.

I’m working in 2D game.

Thank you.

You can use the stencil buffer and AlphaTestEffect. Check out the example here: http://gamedev.stackexchange.com/a/38150

2 Likes

That’s when I see these kind of things I realize how much I still need to learn on graphics programming.
thanks for sharing =)

What about blend states?

Maybe this will help. Its a link to a discussion here on the forum, with code and examples from Jjagg and myself… link.

1 Like

I’ve read all of it, all I see is that nothing stops you @monopalle :slight_smile:

1 Like

Hi,

I’ve read the article but I don’t know how to translate this statement to MonoGame

hr = m_pRenderTarget->CreateBitmapBrush(
        m_pFernBitmap,
        propertiesXClampYClamp,
        &m_pFernBitmapBrush);

And I don’t see how to translate this statement

    m_pRenderTarget->FillOpacityMask(
        m_pBitmapMask,
        m_pFernBitmapBrush,
        D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
        &rcBrushRect
        );

Would you please tell me how to translate these statements to MonoGame?

Thank you.

I shall defer to @kosmonautgames or @KonajuGames or @Tom for that :slight_smile:

EDIT
Or perhaps @Jjagg [Hard to remember that name…]

The article @MrValentine linked is about Direct2D. MonoGame doesn’t expose direct alternatives to that. Have you tried using the stencil buffer? It should suffice for what you’re trying to do.

1 Like

Can we not use Platform Invoke to make that connection?

I would link some articles on MSDN but the site seams to be overloaded tonight…

What I managed to grab hold of was an old bit of stuff:
https://msdn.microsoft.com/en-us/library/aa446536.aspx
https://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx

Not waiting three minutes for every page to load so, just going to throw that out there…

But take a look for it on http://www.codeplex.com/

and this site might be helpful…

http://www.pinvoke.net/

Let us know if you get it working or if anybody knows if it is possible with MonoGame…

Sure you could use Direct2D, but only on Windows. EDIT: I think UWP too

I dont know if you saw my earlier post, but is the link I gave you not exactly what you are asking for?

@MrValentine Thank you for the links, they’re very useful but I want to use as much as possible MonoGame API. I’ll use PInvoke() if there’s no alternatives.

@monopalle Yes I saw your post but I wanna explore all alternatives, beside I need to read about how the blending states work because you’re using it in an advanced way.

1 Like

@Jjagg Yesterday I tried your solution with stencils and it works but I’m facing an issue now

I’ve a white texture and I need to draw it over the mask twice the first time in DarkOrange and the second time Orange.

What’s happening is that the texture is rendered always white ignoring the tint color in the SpriteBatch.Draw().

I did another test and I created two new textures: one with DarkOrange color and the other with Orange color when I draw both over the mask they’re rendered with their color.

What I want is to have only one white texture and draw it using the tint parameter of the SpriteBatch.Draw() so I’ve only one texture.

How can I get it working?

Here’s my code

private DepthStencilState stencil1;
private DepthStencilState stencil2;
private AlphaTestEffect alphaTestEffect;

var projectionMatrix = Matrix.CreateOrthographicOffCenter(0,
	graphicsDevice.PresentationParameters.BackBufferWidth,
	graphicsDevice.PresentationParameters.BackBufferHeight,
	0, 0, 1
);

alphaTestEffect = new AlphaTestEffect(graphicsDevice)
{
	Projection = projectionMatrix
};

stencil1 = new DepthStencilState
{
	StencilEnable = true,
	StencilFunction = CompareFunction.Always,
	StencilPass = StencilOperation.Replace,
	ReferenceStencil = 1,
	DepthBufferEnable = false,
};

stencil2 = new DepthStencilState
{
	StencilEnable = true,
	StencilFunction = CompareFunction.LessEqual,
	StencilPass = StencilOperation.Keep,
	ReferenceStencil = 1,
	DepthBufferEnable = false,
};

graphicsDevice.Clear(
	ClearOptions.Target | ClearOptions.Stencil,
	Color.Black,
	0,
	0);

// Draw the mask
Game1.spriteBatch.Begin(
	SpriteSortMode.Immediate,
	BlendState.AlphaBlend,
	SamplerState.LinearClamp,
	stencil1,
	RasterizerState.CullCounterClockwise,
	alphaTestEffect);

   Game1.spriteBatch.Draw(maskTexture, new Vector2(200, 100), Color.White);

Game1.spriteBatch.End();

// Draw over the mask
Game1.spriteBatch.Begin(
	SpriteSortMode.Immediate, 
	BlendState.AlphaBlend, 
	SamplerState.LinearClamp, 
	stencil2, 
	RasterizerState.CullCounterClockwise, 
	alphaTestEffect);

   Game1.spriteBatch.Draw(myTexture, new Vector2(offset + (i * 13), 100), Color.White);

Game1.spriteBatch.End();

That seems wrong. Maybe this is a bug in MG. Do you have XNA installed so you can test if it works there?
EDIT: Oh, actually this makes sense. The AlphaTestEffect is used for the pixel shader. Try setting the diffuse color in the effect instead of passing the color to spritebatch

Yes I’ve it installed but not here at work. I’ll test it tonight and let you know tomorrow.

I didn’t do such a test because I thought it was my error.

Would you please write the statement to set the diffuse color in the effect because I don’t know what effect is that.

Thank you

You can just set the DiffuseColor property in AlphaTestEffect to the desired color. For example

alphaTestEffect.DiffuseColor = Color.Orange.ToVector3();

It works now :grinning:

Obviously I don’t know how it works so maybe what I’ll suggest isn’t possible but I think (if possible) the tint color in the SpriteBatch.Draw() should work in this case because right now I’ve to draw two textures over the mask so I’ve to use two SpriteBatch.Begin() with two different AlphaTest what I think is a waste of time.

What do you think guys?

Once again thank you @Jjagg for your quick response.

You don’t have to use to different AlphaTest instances, you can use the same one. Since you are using SpriteSortMode.Immediate you can just change the DIffuseColor property before calling SpriteBatch.Draw to give it a specific color.

There’s no elegant way to do this. We could check explicitly if the effect is an AlphaTestEffect, but that’s lame. I think the solution I mentioned above is the best for now.

1 Like

Once again you’re right!

I’ve tested changing the DiffuseColor before drawing over the mask with only one SpriteBatch.Begin() and it works!

Thank you.

1 Like