RenderTarget2D not preserving transparent background - c#

I'm working on a project. All 2D using spriteBatch.
I'm having things like explosions use custom effects that do not apply to the rest of the image. So here is my flow so far:
1)Clear the Background
2)Draw all the explosion sprites
3)Capture that image and implement my effects into a separate RenderTarget2D
4)Draw my Background
5)Draw the RenderTarget2D created in step 3
6) Draw everything else
The problem I'm running into is the RenderTarget2D created is not transparent in the areas not drawn on. As a result, the background drawn in step 4 is not shown.
I have tried GraphicsDevice.Clear(Color.Transparent) following any calls to SetRenderTarget(null). However, I am still getting that purple background.
Any ideas?
I'd post code, but there's too much for you all to have to parse through.

if you follow this flow it should work;
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.Transparent);
// Draw stuff to texture
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(BackgroundColor); // Important to clear here
// Draw background
// Draw texture
// Draw stuff

Related

Getting rid of black background when using a render target

What I am trying to do is use a spritesheet to create a blended terrain, save that as a texture, and then pass it into a shader for additional effects. However, I am having some issues with the render target:
RenderTarget2D someNewTexture = new RenderTarget2D(GraphicsDevice, 256, 256);
GraphicsDevice.SetRenderTarget(someNewTexture);
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
{
// draw some stuff
}
spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
Obviously, this creates a black background with my texture on top of it. However, when I actually draw that texture onto my main scene, I don't want the background, only the texture (if I don't use clear, I get the default purple color instead). How do I fix this?
Use a transparent clear color:
GraphicsDevice.Clear(Color.TransparentBlack);
If you handle blending correctly, it will result in transparent pixels not to be drawn.

Drawing a second RenderTarget2D to the back buffer overwrites the first one

My problem is that I'm trying to get two different RenderTarget2Ds drawn to the screen, but only the last-drawn one is shown. The code is similar to the following, and gets called twice, once by each instance of a class that needs to be drawn with the Draw method:
public override void Draw()
{
gfxDevice.SetRenderTarget(myRenderTarget);
gfxDevice.Clear(Thistle);
//pseudocode
foreach (something in a list)
{ spritebatch.begin();
spritebatch.DrawString(something);
spritebatch.end();
}
//reset to the backbuffer
gfxDevice.SetRenderTarget(null);
gfxDevice.Clear(backgroundColor) //Here is what I thought the offending line was
//draw the RenderTarget to backbuffer
spriteBatch.Begin();
spriteBatch.Draw(myRenderTarget, rect, this.backgroundColor);
spriteBatch.End();
What I thought would be the solution is to stop clearing the graphicsDevice each time the Draw() method gets called, but if I don't, everything but the freshly drawn rendertarget gets drawn an ugly purple. Like this:
The purple results from End()ing the spritebatch, I think, thanks to this question
What do I need to change in order for both RenderTargets get drawn properly, meaning both widgets get drawn, along with the proper Color.Thistle background?
Ideally, the screen would look like a combination of both: and
You're correct that you need to remove the gfxDevice.Clear(backgroundColor) call. If you draw to the backbuffer, and then clear the backbuffer, then obviously anything you drew before clearing isn't going to show up!
You want to clear the backbuffer before rendering anything, i.e. at the beginning of the frame.
EDIT
After taking a more thorough look at the source code provided, I think I know what's actually going on here--it's one of the tricky things about using render targets.
The weird purple you're seeing is not, in fact, caused by SpriteBatch.End(). That's the color that render targets are automatically cleared to when XNA resets their memory.
When does XNA clear out a render target's memory? Whenever that render target is set onto the graphics device as an active target. So whenever you call SetRenderTarget(null), XNA is obliterating the backbuffer's memory and resetting it to that lovely purple.
To avoid this, you need to draw all of your render targets before drawing anything to the backbuffer. Then, set the backbuffer as your active render target, and draw all of the render targets you updated previously in a single pass.

Cut holes in a Texture2D

I want to know how to remove part of a Texture from a Texture2D.
I have a simple game in which I want to blow up a planet piece by piece, when a bullet hits it "digs" into the planet.
The physics are already working but I am stuck on how to cut the texture properly.
I need to create a function that takes a Texture2D a position and a radius as input and returns the new Texture2D.
Here is an example of the Texture2D before and after what I want to accomplish.
http://img513.imageshack.us/img513/6749/redplanet512examplesmal.png
Also note that i drew a thin brown border around the crater hole. If this is possible it would be a great bonus.
After doing alot of googling on the subject it seems the best and fastest way to achieve the effect i want is to use pixel shaders.
More specifically a shader method called 'Alpha mapping'. Alpha mapping is done by using the original texture and another greyscale texture that defines what parts are visible or not.
The idea of the shader is to go through each pixel in the original texture and check how black each pixel in the greyscale image is at the same coordinate. The blacker the pixel in the greyscale picture is the higher the alpha value (more visible) the pixel in the original texture becomes. Since all this is done on the GPU it is lightning fast and leaves the CPU ready to do the actual logic for the game.
For my example I will create a black image to use as my greyscale image and then draw white circles on this corresponding to the parts i want to remove.
I've found a MSDN examples with working source code for XNA 4 that does this (the cat example):
http://create.msdn.com/en-US/education/catalog/sample/sprite_effects
EDIT:
I got this to work quite nicely. Created a small tutorial with source code here: http://syntaxwarriors.com/2012/xna-alpha-mapping-with-pixel-shaders/
A good way of doing this is to render a "hole texture" using alphablend on top of your planet texture. Think of it like drawing an invisibility circle over your original texture.
Take a look at this thread for a few nice links worms-style-destructible-terrain.
To achieve your brown edges I'd guess you'd need to take a similar approach. First render the hole to your terrain with say radius 10px. Then you render another circle from the same origin point but with a slightly larger radius, say 12px. You'd then need to set this circle to a blendmode that results in a brown color.
look at my class here:
http://www.codeproject.com/Articles/328894/XNA-Sprite-Class-with-useful-methods
1.Simply create an object of Sprite class for your planet
Sprite PlanetSprite = new Sprite(PlanetTexture2D , new Vector2(//yourPlanet.X, //yourPlanet.Y));
2.when the bullet hits the planet, make a circle texure2d by the center of collision point using "GetCollisionPoint(Sprite b)" method
-you can have a Circle.png with transparent corners
-or you can create a Circle using math(which is better if you want to have bullet power)
3.then create an Sprite object of your circle
4.now use the "GetCollisionArea(Sprite b)" to get the overlapped area
5.now use the "ChangeBatchPixelColor(List pixels, Color color)" where pixels is the overlapped area and color is Color.FromNonPremultiplied(0, 0, 0, 0)
-note you don't need to draw your circle at all, after using it you can destroy it, or leave it for further use

Changing RenderTarget Results in Purple Screen?

I'm attempting to change RenderTargets at runtime, so I can draw some elements at runtime, manipulate them and then finally draw the texture to the screen. Problem is, the screen turns purple if I change the RenderTarget at runtime. Here's the code I've got in Draw:
RenderTarget2D tempTarget = new RenderTarget2D(GraphicsDevice, 128, 128, 1,
GraphicsDevice.DisplayMode.Format, GraphicsDevice.PresentationParameters.MultiSampleType,
GraphicsDevice.PresentationParameters.MultiSampleQuality, RenderTargetUsage.PreserveContents);
GraphicsDevice.SetRenderTarget(0, tempTarget);
GraphicsDevice.Clear(ClearOptions.Target, Color.SpringGreen, 0, 0);
GraphicsDevice.SetRenderTarget(0, null);
It doesn't seem to matter how I create the RenderTarget, if I do it at runtime (and I do need to create in-memory textures at runtime and draw on them with SpriteBatch) it results in an entirely purple screen. What can I do to fix this?
It looks like the best option is to create the RenderTarget somewhere other than Draw, draw to it during Update, save the resulting texture (and manipulate as necessary) then draw that texture during Draw.
I know this is late, but the solution is to write to the RenderTarget BEFORE you clear the screen and beginning drawing your other items.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(_renderTarget);
//...
//Perform Rendering to the specified target
//...
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.CornflowerBlue);
//...
//Code that draws to the users screen goes here
//...
}
This should prevent you from rendering in the Update method as suggested by others, which is counter-intuitive in many aspects.
When spritebatch.End() is called objects are written to the backbuffer or in your case to tempTarget. To make the texture,
change the target
call begin
call all of the draws
end the spritebatch
set target back to null
then use the render2d

Direct3d/C# - Blur area under a rectangle drawn on a sprite

Any idea how to do it? I am drawing a rectangle that is supposed to be a half-transparent window. I managed to do the transparency by drawing a half-transparent texture, but I also want to blur whatever is under the window.
Normally (eg. using GDI) I would create a bitmap of the area, blur it and paint it as the background of my window. With Direct3D I don't even know how to get the area with whatever is already rendered on it. Or even there can be a different approach, can't it. Please help.
The D3D way is to use a pixel shader to "blur" the area underneath your rect.
This link shows you how to use a pixel shader in C#.
And this link has a guassian blur pixel shader.
It DOES require having your backbuffer as a texture. You can then render the whole thing to a NEW texture and blur the relevant part before putting your semi-trans window over the new texture.
Edit: AFAIK you can't use the Draw function inside a shader. You will need to write your own sprite renderer. The Begin and Draw set up a whole load of states that will break your usage of a vertex shader.

Categories