Sign in to follow this  
Telamon

Tile Map Texture Alignment Problem

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
off the top of my head, all I can think of is texture filtering. Try turning it off or to the lowest form of filtering.

Share this post


Link to post
Share on other sites
For some reason, it won't let me edit... but anyways...

If that fixes it, you have to clamp the texture. Google for "texture clamping".

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

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