# Why does my ID3DXSprite appear to be incorrectly scaled?

I am using D3D9 for rendering some simple things (a movie) as the backmost layer, then on top of that some text messages, and now wanted to add some buttons to that.

Before adding the buttons everything seemed to have worked fine, and I was using a ID3DXSprite for the text as well (ID3DXFont), now I am loading some graphics for the buttons, but they seem to be scaled to something like 1.2 times their original size.

In my test window I centered the graphic, but it being too big it just doesnt fit well, for example the client area is 640x360, the graphic is 440, so I expect 100 pixel on left and right, left side is fine [I took screenshot and "counted" the pixels in photoshop], but on the right there is only about 20 pixels)

My rendering code is very simple (I am omitting error checks, et cetera, for brevity)

// initially viewport was set to width/height of client area

// clear device
m_d3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0,0,0,0), 1.0f, 0 );

// begin scene
m_d3dDevice->BeginScene();

// render movie surface (just two triangles to which the movie is rendered)

m_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,false);
m_d3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); // bilinear filtering
m_d3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); // bilinear filtering
m_d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); //Ignored
m_d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_d3dDevice->SetTexture( 0, m_movieTexture );
m_d3dDevice->SetStreamSource(0, m_displayPlaneVertexBuffer, 0, sizeof(Vertex));
m_d3dDevice->SetFVF(Vertex::FVF_Flags);
m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

// render sprites

m_font->DrawText( m_playerSprite, m_currentMessage.c_str(), m_currentMessage.size(),
// text
m_font->DrawText( m_playerSprite, m_currentMessage.c_str(), m_currentMessage.size(),
&m_playerFontRect, DT_RIGHT|DT_TOP|DT_NOCLIP, m_playerFontColorMessage ) );

// control object
m_sprite->Draw( m_texture, 0, 0, &m_vecPos, 0xFFFFFFFF ); // draws a few objects like this

m_sprite->End()

// end scene
m_d3dDevice->EndScene();


What did I forget to do here? Except for the control objects (play button, pause button etc which are placed on a "panel" which is about 440 pixels wide) everything seems fine, the objects are positioned where I expect them, but just too big.

By the way I loaded the images using D3DXCreateTextureFromFileEx (resizing wnidow, and reacting to lost device, etc, works fine too).

For experimenting, I added some code to take an identity matrix and scale is down on the x/y axis to 0.75f, which then gave me the expected result for the controls (but also made the text smaller and out of position), but I don't know why I would need to scale anything. My rendering code is so simple, I just wanted to draw my 2D objects 1;1 the size they came from the file...

I am really very inexperienced in D3D, so the answer might be very simple...

Normally when you load texture data with D3DXCreateTextureFromFileEx and pass 0 or D3DX_DEFAULT for the width and height parameters and the source data is not a power of two along both dimensions, the resulting texture will be resized so its dimensions are a power of two. This can result in your size computations not matching up correctly and resulting in stretching or scaling artifacts when you render, if you aren't careful.

The next power of two after 440 is 512, which is approximately 1.2 times greater, so this is what you might be seeing. I certainly don't see anything in your code sample that would cause the artifacts you describe, so if it's not the texture rescaling problem I'm describing, the issue is likely elsewhere in your code.

When you call D3DXCreateTextureFromFileEx, try passing D3DX_DEFAULT_NONPOW2 instead of 0 or D3DX_DEFAULT for the width and height parameters, assuming your device does in fact support non-power-of-two textures (almost anything modern should, but if it doesn't this will have no effect).

• Oh, yes, the D3DX_DEFAULT_NONPOW2 actually fixed my problem. Thanks! But it doesn't quite make sense to me, because I stored the texture size, and when I call Draw() I pass in the source rectangle, and would have expected it to just copy the texture of 424 width to the screen. But what actually happened was that it cut off my texture and parts of it were missing. Does that mean that when DX loads the texture and the texture size gets rounded up, it also stretches the original texture to fit the new size? I thought it would have just left it empty (or uninitialized values in that area)... – Bjoern Mar 20 '12 at 1:52
• It does resize, because you can account for it resizing by querying the size post-load (or via the load information parameter, I believe). You couldn't always account for filling it with padding -- what color value would you use? There's no such thing as a "empty color" so any choice, even one with alpha, may clash with the pixel data already present, forcing you to crop instead of use the whole texture (which may be more expensive). – Josh Mar 20 '12 at 2:50
• Ok I see, makes sense. I know I can't expect it to put any colour, that's why I said it might be filled with garbage.. but considering the cropping might be extra cost it makes sense then. Thanks. – Bjoern Mar 20 '12 at 6:28