I'm stuck for several days now. What I'm trying to achieve shouldn't be that hard, but I cannot figure it out.
I want to blend two sprites together and only get the overlapping part as a result (the blue part in the image). The limitation that I have is it must be under the Reach-profile (limited blending options and no shaders). Because of that I cannot figure out how to blend both sprites to get the result.
I do have stencilmasks for both sprites and the white in the image is transparent (and should also be transparent in the resulting image).
This is the code I have so far:
//Set the render target
spriteBatch.GraphicsDevice.SetRenderTarget(rtFinal);
//Clear the renderTarget
spriteBatch.GraphicsDevice.Clear(Color.Transparent); //I need transparent result
//Clear the stencil's buffer
spriteBatch.GraphicsDevice.Clear(ClearOptions.Stencil, Color.White, 0, 0);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive); //Adding the two sprites together
spriteBatch.Draw((rtCutOut as Texture2D), Vector2.Zero, Color.White); //Unsure about this color
spriteBatch.Draw(ent.StencilTex, Vector2.Zero, Color.Blue); //Using the other stencil
spriteBatch.End();
This code results in (not what I want):
I do understand why I get this result (because it's just an additive render), but I don't know how to get it right (cutting of the non-overlapping parts).
I can also get the following result:
But that's with one of the stencils using a white background instead of a transparent one.
Please help, before I lose my sanity...
Related
This may be a strange question, but I'm trying to find a way to render sprites only inside a specific allowed area rather then the entire buffer/texture.
Like so:
Basically allowing me to draw to the buffer or texture2D as I normally would, but with actual drawing happening only inside this specified area and remaining pixels outside of it remaining untouched.
Why this is needed - I'm building my own UI system and I would like to avoid using intermediary buffers as it is quite slow when there are many UI components on the screen (and each has to draw to their own buffer to prevent child elements being drawn outside of parent bounds).
And just to clarify - this is all for simple 2D rendering, not 3D.
If your UI is actually drawn with SpriteBatch you can use ScissorRectangle
GraphicsDevice.RasterizerState.ScissorTestEnable = true;
spriteBatch.GraphicsDevice.ScissorRectangle = ...
In 3D, you can render to a texture and draw just a portion of it - or with a shader (you could actually just send in the dimensions as parameter and set it to black in PixelShader if the Pixel is outside that Rectangle (or whatever you want to accomplish)
You can use:
spriteBatch.Draw(yourTexture,
//where and the size of what you want to draw on screen
//for example, new Rectangle(100, 100, 50, 50)//position and width, height
destinationRectangle,
//the area you want to draw from the original texture
//for example, new Rectangle(0, 0, 50, 50)//position and width, height
sourceRectangle,
Color.White);
Then it will only draw the area that you chose before. Hope this helps!
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.
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
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
Right now I'm tiling a Texture2D with 2 for-loops similar to an example from the MonoGame samples.
I was doing some reading, and I was seeing that using power of two textures (2, 4, 8, 16, 32, etc. on width & height) can be tiled with one SpriteBatch.Draw call.
Is this supported with MonoGame on iOS?
I gave it several tries, and no matter what it merely stretches the image instead of tiling it.
I am using SamplerState.LinearWrap on my SpriteBatch.Begin(), and tried using a 2048x128 png and tried it 1/4 size at 512x32, but with no luck. (Using large sizes, b/c our game runs at 2400xSomething zoomed out, b/c you can zoom in with the camera by 2.5 multiplication)
You can use the SourceRectangle parameter in the draw method. To define what part of the Texture you want to display. Lets say you have a 128x128 Texture. If you supply Rect(0, 0, 128, 128) you tell the draw method to use the whole texture, the same if you would pass null to the draw method. If you supply Rect(0, 0, 64, 64) you would use the upper left part of the texture. Your sprite will display this portion, no matter how big the sprite itself is. So if your sprite is drawn with the size of 128x128 the 64x64 texture part would be scaled.
Now you can use that for animations. If you store in your texture a sequence of animation like this, you just need to recalc the source rectangle everytime you want to display the next image in your sequence.
Besides that, you could pass in a bigger value, than your source texture. XNA now needs to wrap or clamp your texture. That way you can achieve a simple tiling. If you need more than that my guess is you need to use a manual approach, like your foreach loops.
Please note that Wrap is only supported if you use power of two textures.