Sign in to follow this  

Tile Map Texture Alignment Problem

This topic is 4556 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm writting a simple program to display a tile map using Direct 3D in C#. I am using an orthographic projection set to make each D3D unit the size of a single pixel.
dev.Transform.Projection = Matrix.OrthoOffCenterLH(0,this.ClientRectangle.Width,this.ClientRectangle.Height,0,-1,40);
I am then using this function to draw a single tile:
private void DrawTile(int texID, float x, float y)
		{
	
			dev.SetStreamSource(0, tile_vb, 0);
			dev.VertexFormat = CustomVertex.PositionNormalTextured.Format;
			

			dev.SetTexture(0, TileTex[texID]);
	
			Matrix trans = Matrix.Translation(x*Tile.TileSize,y*Tile.TileSize,0);
			Matrix scale = Matrix.Scaling(Tile.TileSize,Tile.TileSize,1);
			scale.Multiply(trans);

			dev.SetTransform(TransformType.World,scale);//TransformType.World,Matrix.Translation(x,y,0));
			dev.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 4);
}
my tile vertex buffer is a Triangle Strip initialized thusly:
			verts[0].X = 0; verts[0].Y = 0; 
			verts[1].X = 1; verts[1].Y = 0;
			verts[2].X = 0; verts[2].Y = 1;
			verts[3].X = 1; verts[3].Y = 1;

			for(int i = 0; i < 4; i++) 
			{
				verts[i].Z = 0;
				verts[i].Tu = verts[i].X;
				verts[i].Tv = verts[i].Y;
			}
So I think all my windings and texture coords are set properly. I want perfect pixel alignment (since I am writing a 2d tile based game), but I get this instead (magnified x2): The original texture is a red and blue checker board. I thought it might be getting distorted along the triangle edges, so I also tried using a TriangleList, but I got similar artifacts. I thought it might be a driver issue, but it draws this way on two different machines. I have the newest SDK. What is going on? One thought is that DirectX does not have a pixel perfect rasterizer (so that polys sharing an edge can overlap in unpredictable ways). However this seems like a glaring deficiency so I assume it must be my fault somehow. I've looked at some tilemap demos which uses direct 3D, but none mention this problem. PS - The test texture I used above is 32x32. The square rendered is also 32x32. So I don't think it's a problem with the projection.

Share this post


Link to post
Share on other sites
ARRRRGggggggg!

This is the most frustrating bug I have ever had. When I create the display device with DeviceType.Reference instead of DeviceType.Hardware, it works correctly. Does this necessarily mean that this is a driver problem?

Share this post


Link to post
Share on other sites
Perhaps just a shot in the dark here - but isn't your vertex winding incorrect?

verts[0].X = 0; verts[0].Y = 0;
verts[1].X = 1; verts[1].Y = 0;
verts[2].X = 0; verts[2].Y = 1;
verts[3].X = 1; verts[3].Y = 1;

That forms:

1 2
3 4


That's neither clockwise or counter-clockwise.

Give this a whirl:
verts[0].X = 0; verts[0].Y = 1;
verts[1].X = 0; verts[1].Y = 0;
verts[2].X = 1; verts[2].Y = 0;
verts[3].X = 1; verts[3].Y = 1;

That forms (CW):

2 3
1 4


Worth a shot.

EDIT:
Also this:
dev.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 4);

The 4 is the number of primitives to draw, not the number of verticies. Try changing this to 2 (2 triangles to form a square).

Share this post


Link to post
Share on other sites
Hey thanks for the suggestion (I did experiment with different windings and toggles for the cull mode).

Actually I figured it out and I'm posting the answer here as a public service announcement.

In Direct3D, it turns out that if you set up an orthogonal view matrix like I did, the center of my raster fragments falls exactly between physical pixel centers on the screen. Thus the final color of the pixel is decided randomly (well, rounding errors - but it looks a bit random). The fix is to translate the view frame left and down by half a pixel.


float d = .5f;
dev.Transform.Projection = Matrix.OrthoOffCenterLH(d,this.ClientRectangle.Width+d,this.ClientRectangle.Height+d,d,-1,40);


Surprised no one else has ever run into this monster of a bug.

Share this post


Link to post
Share on other sites

This topic is 4556 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this