Odd outline in quad aligned render

Started by
7 comments, last by Rhapsodus 19 years, 12 months ago
Greetings, recently I began to implement a menu system in a game and thus I started with the basic operation: rendering menu UI. The problem is that some of the items have very odd 1-2 pixel jagged lines around them about, ESPECIALLY PNG files. This is especially true when the alpha goes from 100% -> 0% in the graphic. I think it is the aliasing or mip map filtering, but I made sure that it was disabled. The surface is not using any multi-sampling. When I compare a screen shot to the actual graphics in photoshop the images look like some pixels are averaged with their neighbors... Any ideas?? I know that texture coordinates have a -0.5f bias, but that shouldn''t make a difference for me since I am always using the entire texture... so I am kind of stumped... Is this occuring on the video card''s power of 2 conversion? Is there something wrong with my texture coordinates perhaps?

void myMenuItem::RenderOntoScreen( LPDIRECT3DDEVICE8* m_pd3dDevice, DWORD dwXOrigin, DWORD dwYOrigin, DWORD dwWidth, DWORD dwHeight )
{  
	//*******************************************************

	// Do not render if we are not visible

	//*******************************************************

	if (!Visible) 
		return;  

	//*******************************************************

	// Do not render

	//*******************************************************

	if( !stricmp( CurrentTexture, "NOTHING" ) )
	{
		return;
	}

	//*******************************************************

	// Create 4 texel vertices for this quad

	//*******************************************************

	static TLVertex2 pScreenVerts[4];
	DWORD dwColor = D3DCOLOR_ARGB(byte(255),byte(255),byte(255),byte(255)); 
	
	//*******************************************************

	// UV Coordinates for the top left point

	//*******************************************************

	pScreenVerts[0].vPosition = D3DXVECTOR4( dwXOrigin, dwHeight, 0, 1.0f );  
	pScreenVerts[0].dwDiffuse = dwColor;  
	pScreenVerts[0].tu = 1.0;  
	pScreenVerts[0].tv = 0.0;  
	
	//*******************************************************

	// UV Coordinates for the bottom left

	//*******************************************************

	pScreenVerts[1].vPosition = D3DXVECTOR4( dwXOrigin, dwYOrigin, 0, 1.0f );  
	pScreenVerts[1].dwDiffuse = dwColor;  
	pScreenVerts[1].tu = 1.0;  
	pScreenVerts[1].tv = 1.0;  
	
	//*******************************************************

	// UV Coordinates for the top right

	//*******************************************************

	pScreenVerts[2].vPosition = D3DXVECTOR4( dwWidth, dwHeight, 0, 1.0f );  
	pScreenVerts[2].dwDiffuse = dwColor;  
	pScreenVerts[2].tu = 0.0;  
	pScreenVerts[2].tv = 0.0;  
	
	//*******************************************************

	// UV Coordinates for the bottom right

	//*******************************************************

	pScreenVerts[3].vPosition = D3DXVECTOR4( dwWidth, dwYOrigin, 0, 1.0f );  
	pScreenVerts[3].dwDiffuse = dwColor;  
	pScreenVerts[3].tu = 0.0;  
	pScreenVerts[3].tv = 1.0;  

	//*******************************************************

	// Set up the render states

	//*******************************************************


	(*m_pd3dDevice)->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
	(*m_pd3dDevice)->SetRenderState( D3DRS_ZENABLE, FALSE );
	(*m_pd3dDevice)->SetRenderState( D3DRS_ALPHABLENDENABLE,   FALSE );
	 
	if (AlphaMode==d3_ALPHATGA)
	{
		(*m_pd3dDevice)->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE );
		(*m_pd3dDevice)->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
		(*m_pd3dDevice)->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	}

	if (AlphaMode==d3_ALPHABMP)
	{
		(*m_pd3dDevice)->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE );
		(*m_pd3dDevice)->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
		(*m_pd3dDevice)->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
	}

	(*m_pd3dDevice)->SetRenderState( D3DRS_FOGENABLE,	 FALSE );
	(*m_pd3dDevice)->SetRenderState( D3DRS_LIGHTING,     FALSE);

	    
	//*******************************************************

	// Set up the texture states

	//*******************************************************

	(*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
    (*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
    (*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
    
	(*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
    (*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
    (*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );

	(*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
	(*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	(*m_pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

	//*******************************************************

	// Draw the primitives and vertex shading

	//*******************************************************

	(*m_pd3dDevice)->SetVertexShader( D3DFVF_TL2VERTEX );  
	(*m_pd3dDevice)->SetTexture( 0, menuTextures[menuTManager.FindTexture(CurrentTexture)] );  
	d3dApp.d3_SetTextureName(CurrentTexture);
	(*m_pd3dDevice)->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2,pScreenVerts,sizeof(TLVertex2));  

	//*******************************************************

	// Set the renderer back to what it was

	//*******************************************************

	(*m_pd3dDevice)->SetRenderState( D3DRS_ALPHABLENDENABLE,   FALSE );
	(*m_pd3dDevice)->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
	(*m_pd3dDevice)->SetRenderState( D3DRS_ZENABLE, TRUE );
}

struct TLVertex2
{  
	D3DXVECTOR4 vPosition;  
	DWORD dwDiffuse; 
	FLOAT tu, tv;
};

const DWORD D3DFVF_TL2VERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;
Advertisement
Oh and to specify, the parameters passed in are in screen space. Meaning a typical call would be a basic Exit button:


located at : 234 pixes, 123 pixels
width would be: 212 pixels
height would be: 168
The D3DX Texture loader functions are loading the images and stretching them to fit powers of 2 sizes.

The easy fix is to resize your images so they are all powers of 2, with the extra space unused. Then use the texture coordinates to choose the section you need. This does waste memory though.


Stay Casual,

Ken
Drunken Hyena
Stay Casual,KenDrunken Hyena
Hmmm,

I am pretty sure there is a way to render a graphic exactly as it is from a file without sampling, stretching, or blurring. And I know dx handles png formats, it is drawing properly except for the ''edges'' of the graphic... The blurring is quite wrong, let me try and put up a screen shot
Ok here are some screen shots of what I am talking about:

This is what the more button should look like, this is what it looks like when I take the png and copy/paste it onto the background.

http://new3.gamehouse.com/images/MoreButton_PhotoShop.jpg

This is the actual texture used for a button, the red area represents the transparency. I wasn't sure if IE Explorer displays png so I had to convert the real file.


http://new3.gamehouse.com/images/MoreButton.jpg


And this is what it looks like when it is rendered in the game...

http://new3.gamehouse.com/images/MoreButton_InGame.jpg


This is the wierd jagged line I was referring to which is the edge of the transparencies...


Also, here is the start button and some mock up panels:

http://new3.gamehouse.com/images/StartButton_InGame.jpg


http://new3.gamehouse.com/images/StartButton_Photoshop.jpg

notice the wierd out line on the 2d graphic again? You will also see more clearly the filtering at work blurring out certain parts of the background ???






[edited by - Rhapsodus on April 21, 2004 7:07:49 PM]

[edited by - Rhapsodus on April 21, 2004 7:09:53 PM]

[edited by - Rhapsodus on April 21, 2004 7:11:30 PM]
yeah, we had some similar problems with our game engine.

Basically, we get perfect results iff:

1. All textures are stored as a 2^n tex (as DrunkenHyena said) and padded with transparent colour

2. Filtering is set to point for BOTH loading and rendering

3. UV clamping is enabled

4. Sub-texel (?) alignment is used - as described in the SDK docs.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

jolly,

Hmmm, I don''t accept dx not being able to render a simple .jpg without distortion

I tried your suggestions but the textures come out like utter crap, at least with POINT filtering.

Ironically enough I can get the textures to line up properly with the -0.5f bias as described in the documentation. This works well if I didn''t have png based hit areas, but for some odd reason I still get those artifacts with the MORE button even with clamping...

I will have to keep playing around with it...
Good suggestions though, I didn''t think about clamping
I fixed the alignment issues with the textures, but I still an''t account for the odd edge artifacts in the transparent .png and the fuzzy looking sampling of all textures
quote:I tried your suggestions but the textures come out like utter crap, at least with POINT filtering.


Our game never scales/rotates the sprites, so the nastiness of POINT filtering isn''t evident. But I suppose it''s not a good general solution

quote:I still an''t account for the odd edge artifacts


Have you tried it on any different hardware? and/or with different texture formats? Maybe email ATI/Nvidia (accordingly) see if they have any ideas... I''ve asked devrel@ati.com for info before and they''re usually quite helpful (e.g. if there is a known issue with what your doing)

good luck!
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

This topic is closed to new replies.

Advertisement