# MDX - Precise quad sizes?

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

## Recommended Posts

A few days ago I had a texture mapping problem. In short I could not and can still not map a section of a 512x512 (32x32) texture to a quad using point sampling without texture alignment problems. After several days of painful debugging it seems that either my quad sizes are not accurate enough to allow explicit point sampling texture mapping or my transforms are inaccurate thus not showing the full 32x32 pixels of each quad. As I've tested by rendering the same texture (albeit with various textures taken from the 512x512 map) for each tile and as on many of the tiles the texture is perfect I'm thinking the actual texture mapping is fine and the problem must be with my geometry or view trasnforms. BTW, when I say corruption I mean I'm rendering a simple square texture that has a 1 pixel internal square border. I've left a 5 pixel boundary so it's not an edge problem and yet the 1 pixel border looses one of it's lines on certain tile positions. As it's the entire line, i.e. on one tile the top line might be missing it just seems that the pixels and texels are not aligned for certain quads? As such I'd like to know if it is possible to guarantee a perfect 32x32 pixel quad (2 tris) irrespective of position on screen. This is obviously in relation to a top down tiled map but with every 4th/5th row/column currently showing signs of texture corruption i.e. one pixel/texel isn't aligned I suspect that the precision of a (single vb.net) means that I'm not guaranteed a 32x32 quad for each of my tile positions. You can see the maths below and with both the x and y using decimals I wonder if this means that quad boundaries vary ever so slightly? update : pic here http://img8.picsplace.to/img8/1/problem_000.jpg Can someone please assist this newbie as I've lost countless hours on this and don't seem to be getting any closer to a solution. BTW, here are my constants, transforms and vertex construction code snippets.
  Private Const cInternalScreenWidth As Integer = 1024
Private Const cInternalScreenHeight As Integer = 768
Private Const cMapTileWidth As Integer = 32
Private Const cMapTileHeight As Integer = 32
Private Const cTilePerScreenWidth As Integer = CInt(cInternalScreenWidth / cMapTileWidth)
Private Const cTilePerScreenHeight As Integer = CInt(cInternalScreenHeight / cMapTileHeight)
Private Const cTextureWidthScale As Single = 10 / cTilePerScreenWidth
Private Const cTextureHeightScale As Single = 10 / cTilePerScreenHeight

--------------------------------------------------------------------------------
'Matrices
.Transform.World = Matrix.Identity

.Transform.View = Matrix.LookAtLH(New Vector3(Xposition, Yposition, 9), New Vector3(Xposition, Yposition, 0), New Vector3(0.0F, 1.0F, 0.0F))

.Transform.Projection = Matrix.PerspectiveFovLH(1, 1.0F, 0.0F, 5.0F)

--------------------------------------------------------------------------------
'Tile Vertex calcualtions for the entire map
'cTextureWidthScale = 0.3125       -- Noted here for convenience
'cTextureHeightScale = 0.416666657 -- Noted here for convenience

For RowLoop As Integer = 0 To TotalVerticalMapTiles - 1
For ColumnLoop As Integer = 0 To TotalHorizontalMapTiles - 1
With MapTiles(ColumnLoop, RowLoop)

'Assign verts and textures Triangle 1
.X(1) = 6 - ((ColumnLoop + 1) * cTextureWidthScale)
.Y(1) = 6 - (RowLoop * cTextureHeightScale)

.X(2) = .X(1)
.Y(2) = 6 - ((RowLoop + 1) * cTextureHeightScale)

.X(3) = 6 - (ColumnLoop * cTextureWidthScale)
.Y(3) = .Y(1)

'Triangle 2
.X(4) = .X(3)
.Y(4) = .Y(2)

.X(5) = .X(3)
.Y(5) = .Y(1)

.X(6) = .X(1)
.Y(6) = .Y(2)

End With

TileCount = TileCount + 1

Next ColumnLoop
Next RowLoop

-------------------------------------------------------------------------------
'Texture Coordiantes mappings
Dim TexturesPerRow As Single = CSng(TemplateTextureWidth / cMapTileWidth)
Dim TexturesPerColumn As Single = CSng(TemplateTextureHeight / cMapTileHeight)
Dim Alignment As Single = CSng(1 / (TemplateTextureWidth * 2))

ReDim MapTextures(CInt(TexturesPerRow * TexturesPerColumn))
Dim OffsetX,OffsetY As Single

For TextureNumber As Integer = 1 To (CInt(TexturesPerRow * TexturesPerColumn))

OffsetX = CSng(((TextureNumber - ((Int(TextureNumber / TexturesPerRow) * TexturesPerRow))) * (cMapTileWidth)) - (cMapTileWidth - 2)) - 1
OffsetY = CSng((Int(TextureNumber / TexturesPerColumn)) * (cMapTileHeight)) + 1

With MapTextures(TextureNumber)
ReDim .tu(6)
ReDim .tv(6)

.tu(1) = ((OffsetX + (cMapTileWidth - 2)) / TemplateTextureWidth) - Alignment
.tv(1) = (OffsetY / TemplateTextureHeight) - Alignment

.tu(2) = .tu(1)
.tv(2) = ((OffsetY + (cMapTileHeight - 2)) / TemplateTextureHeight) - Alignment

.tu(3) = (OffsetX / TemplateTextureWidth) - Alignment
.tv(3) = .tv(1)

.tu(4) = .tu(3)
.tv(4) = .tv(2)

.tu(5) = .tu(3)
.tv(5) = .tv(1)

.tu(6) = .tu(1)
.tv(6) = .tv(2)

End With
Next TextureNumber


[Edited by - Seiko on November 24, 2005 8:38:27 AM]

##### Share on other sites
Have you already check this out: http://msdn.microsoft.com/library/en-us/directx9_c/Directly_Mapping_Texels_to_Pixels.asp?frame=true

##### Share on other sites
Quote:
 Original post by DemirugHave you already check this out: http://msdn.microsoft.com/library/en-us/directx9_c/Directly_Mapping_Texels_to_Pixels.asp?frame=true

Yep, that's why I think it's my geometry or projection. The fact that the same texture is ok on certain tiles suggests to me at least that the texture mapping is fine. Note too that the texture mapping are precalculated once only and then reused for the tiles. So my logic says if it is ok for one tile why not for another?

##### Share on other sites
I would assume a rounding problem with your vertex cords.

Have you tried working with pre transformed vertices? In the case of 2D with perfect texel to pixel mapping this is normally the better way.

##### Share on other sites
Quote:
 Original post by DemirugI would assume a rounding problem with your vertex cords. Have you tried working with pre transformed vertices? In the case of 2D with perfect texel to pixel mapping this is normally the better way.

I did contemplate switching to pre transformed vertices but I really wanted to create a baseline using none transformed vertices as I use alot of matrices for the sprites movement and rotation. Although I could still no doubt use the matrices I was hoping to then bolster the engine with simplified lighting and shadowing techniques as my understanding progresses. Alas, I'm failing on the first task as I can't even control the precise quad size. (lol). I thought I could try and clamp values or something but I'm not really sure which values to clamp, round up or down!

##### Share on other sites
First off all you should make sure that your vertex cords are the problem. Can you render the tiles as wireframe and make a screenshot? This will make it possible to check the size of each tile. If they are not all 32*32 you can limit your search to the vertex cords.

As I don’t know the rest of your code it is possible that I am wrong but your matrix setup looks a little bit unusual for a 2D game.

##### Share on other sites
Quote:
 Original post by DemirugFirst off all you should make sure that your vertex cords are the problem. Can you render the tiles as wireframe and make a screenshot? This will make it possible to check the size of each tile. If they are not all 32*32 you can limit your search to the vertex cords.As I don’t know the rest of your code it is possible that I am wrong but your matrix setup looks a little bit unusual for a 2D game.

My quads, including the wireframe lines are actually 36x35 pixels which you'd think would cause the problem but as I'm clamping the textures I thought I would see an area not covered or taken from an adajecent texel? If a single texel is applied to two pixels then I would have simply concluded that the texture mapping is incorrect due to the size but as I actually looose a texel it suggests to me that my transforms are the problem?

This really is a pain to get to the bottom of. BTW, thanks for the support!
:(

##### Share on other sites
Do you lost the texel inside the tile or on they edge?

Can post a screenshot that shows the problem?

##### Share on other sites
Quote:
 Original post by DemirugDo you lost the texel inside the tile or on they edge? Can post a screenshot that shows the problem?

Alas, I have no where to post a screen shot although I have now found out that my quad sizes are definately wrong in the areas with the texture problem. For the correctly textured tiles the quads are 36x35 however on the incorrect columns the quads are 37x35 thus the mapping gets a little skewed. This must be either my vertex construction or my projections? As for the textel loss or gain dependant on how I tweak my code it is well within the 32x32 texture area.

So how can I create a map of tiles that do not suffer from this imprecision?

##### Share on other sites
Usually I'm working in an ortho view when dealing with this problem but it may still work here. Generally, all of my 2D grapgics-objects have a few extra floating point memebers used for baising either the texture coordiantes, the vertex space coordiantes or even both. Generally these numbers are tiny say, 0.0005f Sometimes this does the trick, but the real problem is when I go to test on different hardrware. Nearly every card samples and rounds a different way and I'm still figuring a way around this. One way, belive it or not, is to use the baising along with bi-linear texture filtering. If the textures are designed well and the bais is just right, it seems to look pretty good on nearly every card.

Since you are working in perspective though, I really don't think there is any way that you can expect to properly map texles to pixels. Most hardware is concerned with speed, not accuracy.

##### Share on other sites
You can upload images there: http://picsplace.to/

Maybe it is both. I am still not understand the reason for your view and projection matrix you are use. Do you have copy this from some 3D sample?

For 2D you can use Identity or set the view matrix to a scale matrix that allows you to use real pixel coordinates for your vertices. Maybe I have an example an my system but I am normally don’t use vb for my DX stuff.

##### Share on other sites
Quote:
 Original post by DemirugYou can upload images there: http://picsplace.to/ Maybe it is both. I am still not understand the reason for your view and projection matrix you are use. Do you have copy this from some 3D sample?For 2D you can use Identity or set the view matrix to a scale matrix that allows you to use real pixel coordinates for your vertices. Maybe I have an example an my system but I am normally don’t use vb for my DX stuff.

Ah thanks, I've uploaded the pic. This is a simple map of tiles. There are two 32x32 textures being used from within one 512x512 texture. As you can see some tiles are not shown correctly. They are effected in columns and rows.

http://img8.picsplace.to/img8/1/problem_000.jpg

As for the matrix. It's just one I set up having browsed a number of examples. This allows me to scroll and keep an overhead view. i.e top down scroller.

##### Share on other sites
Quote:
 Original post by lack o commentsUsually I'm working in an ortho view when dealing with this problem but it may still work here. Generally, all of my 2D grapgics-objects have a few extra floating point memebers used for baising either the texture coordiantes, the vertex space coordiantes or even both. Generally these numbers are tiny say, 0.0005f Sometimes this does the trick, but the real problem is when I go to test on different hardrware. Nearly every card samples and rounds a different way and I'm still figuring a way around this. One way, belive it or not, is to use the baising along with bi-linear texture filtering. If the textures are designed well and the bais is just right, it seems to look pretty good on nearly every card.Since you are working in perspective though, I really don't think there is any way that you can expect to properly map texles to pixels. Most hardware is concerned with speed, not accuracy.

Thanks, yes I had thought of that but as my maps are going to quite large I didn't want to have to try and apply offsets per column/row to my geometry. As for the cards, I've tested this on three albeit ATI cards, 9600, x700 and x800.
All show the same problem.

##### Share on other sites
Quote:
 Original post by DemirugI would assume a rounding problem with your vertex cords. Have you tried working with pre transformed vertices? In the case of 2D with perfect texel to pixel mapping this is normally the better way.

Excerpt from Tom Miller's blogs:

"When a Direct3D device is created, the runtime will change the Floating point unit to suit its needs (by default switch to single precision, the default for the CLR is double precision). This is done because it has better performance than double precision (naturally). When creating the device you should use the CreateFlags.FpuPreserve flag to keep the CLR's double precision."

Are you working with a single or double precission?

##### Share on other sites
Quote:
Original post by mohamed adel
Quote:
 Original post by DemirugI would assume a rounding problem with your vertex cords. Have you tried working with pre transformed vertices? In the case of 2D with perfect texel to pixel mapping this is normally the better way.

Excerpt from Tom Miller's blogs:

"When a Direct3D device is created, the runtime will change the Floating point unit to suit its needs (by default switch to single precision, the default for the CLR is double precision). This is done because it has better performance than double precision (naturally). When creating the device you should use the CreateFlags.FpuPreserve flag to keep the CLR's double precision."

Are you working with a single or double precission?

Hmmm, thats interesting I'll see what happens. Many thanks.

##### Share on other sites
Quote:
Original post by Anonymous Poster
Quote:
Original post by mohamed adel
Quote:
 Original post by DemirugI would assume a rounding problem with your vertex cords. Have you tried working with pre transformed vertices? In the case of 2D with perfect texel to pixel mapping this is normally the better way.

Excerpt from Tom Miller's blogs:

"When a Direct3D device is created, the runtime will change the Floating point unit to suit its needs (by default switch to single precision, the default for the CLR is double precision). This is done because it has better performance than double precision (naturally). When creating the device you should use the CreateFlags.FpuPreserve flag to keep the CLR's double precision."

Are you working with a single or double precission?

Hmmm, thats interesting I'll see what happens. Many thanks.

Alas, it has no effect
:(