Sign in to follow this  
utilae

D3DXSprite - Source Rect incorrect sometimes (textures bleed)

Recommended Posts

utilae    188
Hi, I am using C++ and DirectX9, D3DXSprite, etc. I have gotten D3DXSprite to work, but I have one last problem. My source rect is off by one pixel at times. Subsections of my texture are called tiles. I specify a tile to be drawn as a sprite. The source rect correctly displays a tile for almost all tiles. But there are about three tiles that are off by one pixel, ie they show one pixel extra then they should at the top, right and bottom of the rect. This means that parts of other tiles are shown with the drawn tile. This causes a strange shading effect, which I do not want. Anyone got any ideas? I have checked each tile in my texture file and they are correct. I have checked the code that stores information on a tiles location in the texture, and that is correct. For example, when I create a tile and specify the location rect of the tile on the texture, that data is correct. Here is my sprite sprite drawing code:
g_pSprite->Begin(D3DXSPRITE_ALPHABLEND);

//loop through list of sprites and text to render
vector<SPRITEX>::iterator itSprite=m_lstSpritexList.begin();
while(itSprite!=m_lstSpritexList.end())
{
	//get the rect for finding a tiles location on the texture
	RECT recTile=TextureManager.GetTileRect(itSprite->sTextureName,itSprite->sTileName);

	//width/height of tile
	int nTileWidth=recTile.right-recTile.left;
	int nTileHeight=recTile.bottom-recTile.top;
	//width/height of sprites destination rectangle
	int nDestWidth=itSprite->recDest.right-itSprite->recDest.left;
	int nDestHeight=itSprite->recDest.bottom-itSprite->recDest.top;

	//centre of sprite
	D3DXVECTOR2 Centre=D3DXVECTOR2(itSprite->recDest.left+((float)nDestWidth/2),itSprite->recDest.top+((float)nDestHeight/2));
	//position of sprite
	D3DXVECTOR2 Trans=D3DXVECTOR2(itSprite->recDest.left,itSprite->recDest.top);
	//factor to scale sprite by
	D3DXVECTOR2 Scale=D3DXVECTOR2((float)nDestWidth/nTileWidth,(float)nDestHeight/nTileHeight);

	//sprite rotation in radians (counter clockwise)
	float Rotation=(float)itSprite->fRotation*g_fDegreesToRadians;

	//make the sprite rotate, scale, and be in a specified position
	D3DXMATRIX Mat;
	D3DXMatrixTransformation2D(&Mat,NULL,0.0,&Scale,&Centre,Rotation,&Trans);
	g_pSprite->SetTransform(&Mat);

	//draw sprite
	HRESULT hrDrawSprite=g_pSprite->Draw(TextureManager.GetTexture(itSprite->sTextureName),
	&recTile,
	NULL,
	NULL,
	itSprite->dwColor//0xFFFFFFFF keeps texture color
	);

	//necesary to allow font->drawtext() to work properly with sprite->draw()
	D3DXMatrixIdentity(&Mat);
	g_pSprite->SetTransform(&Mat);
	++itSprite;//next spritex
}
g_pSprite->End();




GetTileRect() function: My tiles are initially stored as floats to be used with drawprimitive. So they are converted to rects from floats in the GetTileRect() function. Initially when adding a tile I specify the tile location on the texture as a rect, which is converted to a float using the following code: //eg a 32x32 tile in the top left corner of the texture: //nTileTop=1 nTileLeft=1 nTileRight=32 nTileBottom=32 or //nTileTop=1 nTileLeft=33 nTileRight=64 nTileBottom=32 is next to it newTile.m_tvTop=(float)(nTileTop-1)/(*itTextures)->m_nHeight; newTile.m_tuLeft=(float)(nTileLeft-1)/(*itTextures)->m_nWidth; newTile.m_tuRight=(float)(nTileRight)/(*itTextures)->m_nWidth; newTile.m_TvBottom=(float)(nTileBottom)/(*itTextures)->m_nHeight; GetTileRect() function:
RECT CTextureManager::GetTileRect(const string &sFilename,const string &sTileName)
{
	RECT recTileRECT;
	recTileRECT.top=0;
	recTileRECT.left=0;
	recTileRECT.right=0;
	recTileRECT.bottom=0;
	
	//iterate through texture list
	list<LOADEDTEXTURE*>::iterator itTextures=m_lstMainTextureList.begin();
	while(itTextures!=m_lstMainTextureList.end())
	{
		//found texture to get tile from
		if((*itTextures)->m_sFilename==sFilename)
		{
			//iterate through tile list
			list<TILE>::iterator itTiles=(*itTextures)->m_TileList.begin();
			while(itTiles!=(*itTextures)->m_TileList.end())
			{
				//found tile
				if(itTiles->m_sTileName==sTileName)
				{
					//return tile rect
					recTileRECT.top=(itTiles->m_tvTop*(*itTextures)->m_nHeight);
					recTileRECT.left=(itTiles->m_tuLeft*(*itTextures)->m_nWidth);
					recTileRECT.right=itTiles->m_tuRight*(*itTextures)->m_nWidth;
					recTileRECT.bottom=itTiles->m_TvBottom*(*itTextures)->m_nHeight;
					
					return recTileRECT;
				}
				else ++itTiles;
			}
		}
		else ++itTextures;
	}
	g_Log<<"TextureManager->GetTileRect("<<sFilename<<", "<<sTileName<<"): Tile Not Found In List"<<endl;
	return recTileRECT;
}




So, anyone able to help? If my source rect code shown here is not the problem, then maybe there is some other factor that could be cauing my problem? Any help appreciated :) [Edited by - utilae on November 26, 2005 2:18:02 PM]

Share this post


Link to post
Share on other sites
utilae    188
Could someone please help?


It seems that when I draw a sprite with a scale of 1.0f x & y, the correct section of the texture draws. For some sprites, when I draw them scaled, the source section of the texture seems to expand by 1 pixel in either direction. This means that part of another tile will be drawn along with the intended tile.



Anyone else had problems like this?

Share this post


Link to post
Share on other sites
Bezben    202
IIRC the Microsoft RECT structure is broken a bit, I seem to recall an article about it that rendered bunnies, but I couldn't find it. Anyway, try reducing the bottom and right members of your source rect by one.

Share this post


Link to post
Share on other sites
utilae    188
I looked at that article and this article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/ProgrammingGuide/GettingStarted/Direct3DTextures/coordinates/MappingTexelsToPixels.asp

But they don't really help.

Microsofts article seems logical, subtracting 0.5 from all sides of the rect. But I do not know where to do this. In my GetRectTile() function, subtracting 0.5 from all sides will not work, since a RECT is made up of longs and D3DXSprite only takes a RECT.



Could someone give me a suggestion as to what modification I can make to my code that will fix my texture bleeding problem?

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