MDX - Precise quad sizes?

Started by
14 comments, last by Seiko 18 years, 5 months ago
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]
Advertisement
Have you already check this out: http://msdn.microsoft.com/library/en-us/directx9_c/Directly_Mapping_Texels_to_Pixels.asp?frame=true
Quote:Original post by Demirug
Have 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?

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.
Quote:Original post by Demirug
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.


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!

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.
Quote:Original post by Demirug
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.


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!
:(
Do you lost the texel inside the tile or on they edge?

Can post a screenshot that shows the problem?
Quote:Original post by Demirug
Do 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?
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.

This topic is closed to new replies.

Advertisement