I got some problem with texture transparency, I hope ya can help.
Details:
XNA 4.0
Texture source is BMP, what I make transparent by code:
public void Feketealapú(string Azonosító)
{
//textúra megállapítása
Texture2D Textúra = Textúrák[TextúraSzáma(Azonosító)];
//adatok lekérése
Color[] buffer = new Color[Textúra.Width * Textúra.Height];
Textúra.GetData<Color>(buffer);
//adatok módosítása
for (int i = 0; i < buffer.Length; i++)
{
Color szín = buffer[i];
szín.A = ((byte)((szín.R + szín.B + szín.G) / 3));
buffer[i] = szín;
}
//adatok visszaírása
Textúra.SetData<Color>(buffer);
}
I use the following before I start drawing 3d stuff:
public void Rajzolj()
{
GStatic.Játék.GrafikaiCsatorna.BlendState = BlendState.AlphaBlend;
GStatic.Játék.GrafikaiCsatorna.DepthStencilState = DepthStencilState.Default;
GStatic.Játék.GrafikaiCsatorna.RasterizerState = RasterizerState.CullCounterClockwise;
GStatic.Játék.GrafikaiCsatorna.SamplerStates[0] = SamplerState.LinearWrap;
..etc.
If I use BlendState.Opaque I get no transparent textures.
I get into the following trouble: http://youtu.be/ZiPzyk7AWu8
Edit: Bit more detail about the problem is: the problem is with the transparent texture, what simulates a fire effect. The fire is from several rectangles with these transparent textures. If I see the fire from an angle, I should see another fire effect's rectangle through the transparent texture, what is also transparent. The problem is that instead of this, I see the floor's texture behind the model instead.
So could someone help me out a bit?
Thanks in advance:
Péter
Never mind I don't think the transparency is the issue. I think that whats happening is the first thing in the Z-Buffer is being draw and nothing else behind it.
http://blogs.msdn.com/b/shawnhar/archive/2009/02/18/depth-sorting-alpha-blended-objects.aspx
The most import part being the where he specifies how best to order your scene and manipulate the DepthBuffer.
Set DepthBufferEnable and DepthBufferWriteEnable to true
Draw all opaque geometry
Leave DepthBufferEnable set to true, but change DepthBufferWriteEnable to false
Sort alpha blended objects by distance from the camera, then draw them in order from back to front
This is neither a transparency issue or an ordering issue that you can solve.
The nature of your layout has all 4 quads overlapping each other so that each quad needs to be both in front of and behind another quad at the same time.
So setting draw order won't help because half of quad A needs to be drawn before quad B and the other half of quad A needs to be drawn after quad B.
It may get a little bit better if you divide it into 8 quads that all meet in the middle and sort/draw by depth from the camera. But if you go this route, 3 quads may be sufficient.
Related
I'm having a lot of trouble googling for this because I don't really know the terminology for it. This HAS to be a common problem though. I want to iterate through a sprite sheet, but I want it to IGNORE the transparent background around the sprite and not include that as part of what's displayed.
For example, if I have a few frames, I want to iterate through each frame and load that image. Then, in that frame, I want to narrow it down by drawing a rectangle around the image itself, not the extra "background". This would probably be accomplished by finding the corners of the sprite which are non-transparent pixels (Not sure how this part works).
Does this make sense? Again, not sure exactly which words to use here...let me know if this is unclear.
The goal here is loading sprites that are exactly square with other frames, so they won't wobble or bounce unintentionally.
Thanks much!!
I am working on my first game as well and I had a similar problem with the transparent areas around my sprites, in this case for collisions.
What I did was set it up so that each sprite has a position, a height, a width and Padding for X and Y.
Vector2 position = new Vector2(100,100);
int frameHeight = 48;
int frameWidth = 48;
int paddingX = 4;
int paddingY = 3;
With that info you can get what you need, for instance for the rectangle that represents the bounding box around the sprite I can use:
boundingRectangle = new Rectangle(
(int)position.X + paddingX,
(int)position.Y + paddingY,
frameWidth - (paddingX * 2),
frameHeight - (paddingY * 2));
I read this in XNA 4.0 Game Development by Example by Kurt Jaegers (Which has been a ton of help for me)
I'm using C# and XNA and I would like to make a scrolling background in my game.
I'm trying to figure out what the best way to implement a scrolling texture that moves in some direction indefinitely. Let's say a space background with stars. So, when ship moves do does the texture, but in opposite direction. Kinda like in "tiling" mode.
My only guess so far is to render two textures which are, let's say moving left, and then just make the most left one jump to right when it's beyond visibility or something similar to this.
So, I was wondering is there some simple way to do it in XNA, maybe some render mode, or is the way I described it is good enough? I just don't want to overcomplicate things. I obviously tried to google first, but found pretty much nothing, but it is strange considering that many games use similar techniques too.
Theory
A scrolling background image is easy to implement with the XNA SpriteBatch class. There are several overloads of the Draw method which let the caller specify a source rectangle. This source rectangle defines the section of the texture that is drawn to the specified destination rectangle on screen:
Changing the position of the source rectangle will change the section of the texture displayed in the destination rectangle.
In order to have the sprite cover the whole screen use the following destination rectangle:
var destination = new Rectangle(0, 0, screenWidth, screenHeight);
If the whole texture should be displayed use the following destination rectangle:
var source = new Rectangle(0, 0, textureWidth, textureHeight);
Than all you have to do is animate the source rectangle's X and Y coordinates and you are done.
Well, almost done. The texture should start again even if the source rectangle moves out of the texture area. To do that you have to set a SamplerState that uses texture wrap. Fortunately the Begin method of the SpriteBatch allows the usage of a custom SamplerState. You can use one of the following:
// Either one of the three is fine, the only difference is the filter quality
SamplerState sampler;
sampler = SamplerState.PointWrap;
sampler = SamplerState.LinearWrap;
sampler = SamplerState.AnisotropicWrap;
Example
// Begin drawing with the default states
// Except the SamplerState should be set to PointWrap, LinearWrap or AnisotropicWrap
spriteBatch.Begin(
SpriteSortMode.Deferred,
BlendState.Opaque,
SamplerState.AnisotropicWrap, // Make the texture wrap
DepthStencilState.Default,
RasterizerState.CullCounterClockwise
);
// Rectangle over the whole game screen
var screenArea = new Rectangle(0, 0, 800, 600);
// Calculate the current offset of the texture
// For this example I use the game time
var offset = (int)gameTime.TotalGameTime.TotalMilliseconds;
// Offset increases over time, so the texture moves from the bottom to the top of the screen
var destination = new Rectangle(0, offset, texture.Width, texture.Height);
// Draw the texture
spriteBatch.Draw(
texture,
screenArea,
destination,
Color.White
);
Microsoft has a XNA tutorial that does exactly this, you can grab the source code and read up on the actual programming logic behind a scrolling background. Bonus points they do parallax scrolling for a nice effect.
Link: http://xbox.create.msdn.com/en-US/education/tutorial/2dgame/getting_started
this site has been really amazing for helping me with game development however I'm unable to find an answer for the following question (nor am I able to solve it on my own).
I am trying to do rectangle collision in my game. My idea is to 1) get the original collision bounding rectangle 2) Transform the texture (pos/rot/scale) 3) Factor changes of item into a matrix and then use this matrix to change the original collision bounds of the item.
However, my textures contain a lot of transparency, transparency that affect the overall height/width of the texture (I do this to maintain power of two dimensions).
My problem: How to create a rectangle that forms dimensions which ignore transparency around the object. A picture is provided below:
I guess you could step through each row of pixels in the bounding rectangle, starting from the top, checking when you first hit a pixel with colour by checking its alpha value (Color.A != 0).
That way you'll get Y coordinate of the rectangle.
Then step through each column starting from the left of the bounding rectangle, looking for the first coloured pixel.
You'll get the X this way.
Then step through each row again but starting from the bottom and you'll get the height.
Then step through each column again but starting from the right and you'll get the width.
Hope that helps
I think dois answer is the way to do it. I use the following code to find the pixel value at a specific point inside my texture. You can change this code to get line by line the pixels, check for transparency and stop when you find a line with a pixel which is not transparent.
Color[] colorData = new Color[1];
Texture2D texture = //Get your Texture2D here
texture.GetData<Color>(0, new Rectangle(targetPoint.X, targetPoint.Y, 1, 1), colorData, 0, 1);
To check if pixel is not transparent I do this :
if(colorData[0].A > 0)
I don't know how expensive can this operation be for collision detection though.
I know for my games, I use circles. If your objects are reasonably round, it can often provide a closer estimate AND collision detection is dead easy. If the distance between the centres of the objects is less than the sum of the radii, then they are colliding.
If circles are out of the question, then muku or Dois have provided decent answers.
I need to draw a large set of cubes, all with (possibly) unique textures on each side. Some of the textures also have parts of transparency. The cubes that are behind ones with transparent textures should show through the transparent texture. However, it seems that the order in which I draw the cubes decides if the transparency works or not, which is something I want to avoid. Look here:
cubeEffect.CurrentTechnique = cubeEffect.Techniques["Textured"];
Block[] cubes = new Block[4];
cubes[0] = new Block(BlockType.leaves, new Vector3(0, 0, 3));
cubes[1] = new Block(BlockType.dirt, new Vector3(0, 1, 3));
cubes[2] = new Block(BlockType.log, new Vector3(0, 0, 4));
cubes[3] = new Block(BlockType.gold, new Vector3(0, 1, 4));
foreach(Block b in cubes) {
b.shape.RenderShape(GraphicsDevice, cubeEffect);
}
This is the code in the Draw method. It produces this result:
As you can see, the textures behind the leaf cube are not visible on the other side. When i reverse index 3 and 0 on in the array, I get this:
It is clear that the order of drawing is affecting the cubes. I suspect it may have to do with the blend mode, but I have no idea where to start with that.
You are relying on depth buffering to achieve occlusion. This technique only works for opaque objects.
To achieve correct occlusion for a scene containing transparent objects:
Set DepthBufferEnable and
DepthBufferWriteEnable to true
Draw all opaque geometry
Leave DepthBufferEnable set to true,
but change DepthBufferWriteEnable to
false
Sort alpha blended objects by
distance from the camera, then draw
them in order from back to front
Extract from Depth sorting alpha blended objects by Shawn Hargreaves
Drawing transparent objects properly is harder than regular ones. The reason is when face is rendered by default it marks all pixels as drawn at certain depth and as result pixels that are behind will not be drawn at all. I'd recommend getting a book on 3d rendering and look through for more details.
The easiest approach you already found - draw transparent objects AFTER non-transparent ones. Works for transpreant and semi-transparent objects. Note that transparent objects need to be sorted to be drawn correctly (unlike non-transparent ones).
In your particular case (non-semitransparent) you can change texture renreding to NOT render anything for transparent parts.
You may be able to use this if you don't have semi-transparent pixels on the objects. It'll either render completely solid or won't write to the Z-Buffer.
As in Riemers Alpha Testing.
XNA (and DirectX and all major 3D libraries) take in consideration something called culling. Although from your code I cannot tell for sure, from the images I think this is your problem. The polygons that you don't see have the vertices in the wrong order. If this is the problem, you have two solutions:
either turn culling off (device.RenderState.CullMode = CullMode.None; if I remember correctly)
apply your texture twice, with the points of the polygon both in clockwise order and counter clockwise
I'm quite new to the world of 2D-Engines. I figured out how to load images and display those as sprites and stuff, but theres one question that bugs me.
For instance, when a "rocket" hits an object it will deal damage to it and leave a crater behind. I'd like to have the crater shown on that object. That would require "skipping" some of the pixels of that image when rendering, doesn't it?
My question is, how would you do such a thing? What data strcture would you use to save this? How to display a "broken" sprite?
Create a sprite sheet.
This will contain all the spirites your object, in this case the rocket. Some of these images would be of the rocket smashing into many pieces, fire etc...
Then when your object hits, you play the collision animation. Your method would technically work, but it's overkill. Using a sprite sheet is simple, rather than drawing a massive image, you just draw a portion of the sheet, and to play the animation increment in the X an Y axis of the sheet. This naturally requires the sheet to be layed out even, but it's not too much work.
For some situations, you can simply draw another sprite on top of the original sprite. Alternatively, you can switch between different sprites depending on the state of the object.
I see you have tagged this with XNA, so assume that is your API (though this answer could well be applied to any OpenGL/D3d approach with appropriate calls). If you want to do this in an elegant fashion, I suggest using a temporary RenderState. You would switch to the new RenderState and draw your original background texture, then draw crater sprites over the top (you can modify the AlphaSourceBlend and AlphaDestinationBlend properties of the RenderState to create the subtractive effect you are looking for).
Once you have finished drawing, you can retrieve the RenderState as a texture easily using the GetTexture() function.
Keep in mind that if you are changing the blend modes, your SpriteBatch should be performing in the "immediate" mode (I forget the XNA term, but the one where it doesn't do ordering of sprites for efficiency) else it will be reset unexpectedly.
View this: http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Adding_craters.php
Slow, but probably fast enough.
public static void Fill(this Texture2D t, Func<int, int, Color> perPixel)
{
var data = new Color[t.Height * t.Width];
for (int y = 0; y < t.Height; y++)
for (int x = 0; x < t.Width; x++)
{
data[x + (y * t.Width)] = perPixel(x, y);
}
t.SetData(data);
}
I was working on something like this on a mobile Java game, a worms/scorched earth clone (actually based on GunBound).
You don't "skip" the pixels in order to leave a crater. You change the pixels in your planet's bitmap, so the crater is now a permanent part of your planet. I assume you know all about bitmaps, blitting transparent, and hit testing.
To create a crater I used a circle-fill algorithm and filled the "explosion area" with the background or transparent color.
So when doing hit-testing you have to do it twice. A bounding-box hit test for speed, then a per-pixel hit test when then bounding boxes overlap.