Home » Community » Forums » DirectX and XNA » xna renderstate settings for transparency
Intel sponsors gamedev.net search:
Control Panel Register Bookmarks Who's Online Active Topics Stats FAQ Search

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 xna renderstate settings for transparency
Post New Topic  Post Reply 
I'm trying to draw a texture with alpha = 1 onto a rendertarget buffer, then another texture onto it with alpha < 1. I want the result to be a typical transparent texture over an opaque one with the final alpha = 1.

The math for a single pixel for the second draw of the transparent(alpha < 1) texture should look like this then:

renderTarget.color' = renderTarget.color * (1-transparentTexture.alpha) + transparentTexture.color * transparentTexture.alpha;

renderTarget.alpha' = 1;

Simple, right? Well, for some reason I can't get it to work when drawing to this render target, then drawing the rendertarget to screen. Some setting in the renderstate is causing the final alpha of the rendertarget to be < 1, so that when I test this with a black images, some of the bluish color(what one sees if nothing fully opaque is drawn to screen) comes through.

Here's my code:

protected override void LoadContent() {
graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.Zero;
graphics.GraphicsDevice.RenderState.SourceBlend = Blend.One;
graphics.GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.InverseSourceAlpha;
graphics.GraphicsDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
squareTexture = new Texture2D(graphics.GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color);
Color[] colData = new Color[] { Color.Black };
squareTexture.SetData<Color>(colData);
buffer1 = new RenderTarget2D(graphics.GraphicsDevice, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight, 1, SurfaceFormat.Color);
}


protected override void Draw(GameTime gameTime) {
graphics.GraphicsDevice.SetRenderTarget(0, buffer1);
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);//layer-front:0, back:1
spriteBatch.Draw(squareTexture, Vector2.Zero, null, Color.White, 0f, Vector2.Zero, new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), SpriteEffects.None, .2f);
spriteBatch.Draw(squareTexture, Vector2.Zero, null, new Color(0, 0, 0, 125), 0f, Vector2.Zero, new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), SpriteEffects.None, .1f);
spriteBatch.End();
graphics.GraphicsDevice.SetRenderTarget(0, null);
spriteBatch.Begin();
spriteBatch.Draw(buffer1.GetTexture(), Vector2.Zero, new Color(255, 255, 255, 255));
spriteBatch.End();
}


At this point I'm almost reduced to asking someone to just make some sample barebones code. I think I understand what I want the logic to do, I just can't figure out how to set everything up in XNA.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link


Reviewing a sample of mine that does something similar (over here), it seems the alpha from the original image is indeed carried over when rendering the RenderTarget (RT) to the screen. Adding the following lines as the first thing within the Sprite.Begin and Sprite.End block when rendering to the RT seems to remove this issue for me:

// after sprite.Begin(...)

GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = true;
GraphicsDevice.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.One;

// Draw here
// sprite.End() goes here

// remember to add this line after you're done!
GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;


Basically this will tell the device you want the texture to have full alpha on the destination surface, so no alpha is carried over on the RT. You can remove the render states you set up in LoadContent, since these are overwritten by Sprite.Begin. This is why you need to include the lines above inside the Begin/End block.

Hope this helps :)



Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by remigius
<...>
Hope this helps :)



My hero!


 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: