Search code examples
c++directxtexturesspritedirectx-9

Deformed texture when using sprites (Directx 9)


I'm on my way of making a simple 2D tile game using ID3DXSprite. When I managed to draw an image I noticed it didn't have the same quality as when I was editing it. I've read that in Directx 8 and newer all textures must be multiples of 2, but this is not my case since the image is 32x32.

Original image: link

Rendered image: link

Initialization code:

bool D3DEngine::InitD3D(HWND hwnd)
{
    D3D = Direct3DCreate9(D3D_SDK_VERSION);    
    D3DPRESENT_PARAMETERS D3DPP;

    ZeroMemory(&D3DPP, sizeof(D3DPP));    
    D3DPP.Windowed = true;    
    D3DPP.SwapEffect = D3DSWAPEFFECT_DISCARD;    
    D3DPP.hDeviceWindow = hwnd;
    D3DPP.BackBufferFormat = D3DFMT_A8R8G8B8;
    D3DPP.BackBufferWidth = 300;
    D3DPP.BackBufferHeight = 300;
    D3DPP.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    if (D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &D3DPP, &D3DDevice) != D3D_OK)
    {
        return false;
    }
    else
    {
        D3DXCreateTextureFromFile(D3DDevice, ".bmp", &Texture);

        D3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        D3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

        Sprite = new D3DSprite(D3DDevice);
        Camera = new Camera2D(0, 0, ScreenPosX, ScreenPosY, 1.0f, 0.0f);

        Debug->Output("Started DirectX");
        return true;
    }
}

Render Code:

void D3DSprite::DrawTexture(LPDIRECT3DTEXTURE9 Texture, CONST RECT* Rect, ScreenPos Pos, D3DCOLOR Color)
{
    D3DXVECTOR3 Center(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 Position(Pos.x - Camera->GetX(), Pos.y - Camera->GetY(), 0.0f);

    Handle->Draw(Texture, Rect, &Center, &Position, Color);
}

struct ScreenPos
{
    float x;
    float y;
};

class D3DSprite 
{
    public:

        LPD3DXSPRITE Handle;

        D3DSprite(LPDIRECT3DDEVICE9 Device);
        ~D3DSprite();

        void DrawTexture(LPDIRECT3DTEXTURE9 Texture, CONST RECT* Rect, ScreenPos Pos, D3DCOLOR Color);
        void DrawTexture(LPDIRECT3DTEXTURE9 Texture, CONST RECT* Rect, WorldPos Pos, D3DCOLOR Color);
        void Begin(DWORD Flags) { Handle->Begin(Flags); };
        void End() { Handle->End(); };
};

void D3DEngine::Render()
{
    D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0, 1.0f), 1.0f, 0);

    D3DDevice->BeginScene();

    ScreenPos Position = {0, 0};

    Sprite->Begin(D3DXSPRITE_OBJECTSPACE | D3DXSPRITE_ALPHABLEND);

    Sprite->DrawTexture(Texture, NULL, Position, D3DCOLOR_COLORVALUE(1.0f, 1.0f, 1.0f, 1.0f));

    Sprite->End();
    D3DDevice->EndScene();
    D3DDevice->Present(NULL, NULL, NULL, NULL);

}

Solution

  • It is not quite clear what do you mean by "deformed texture" . What I see is that second picture is a blurred first one. And also there are black border on left and top.

    Blurring.

    Blurring can be caused by

        D3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        D3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    

    When drawing simple sprites, like tiled maps, you, probably, will want to disable mipmapping. So try to comment out this lines, or use D3DTEXF_NONE as third argument.

    Mixed software/hardware device.

    Another strange thing is D3DCREATE_MIXED_VERTEXPROCESSING flag on device creation. Not quite sure if it can cause blurring, but most common is to set D3DCREATE_HARDWARE_VERTEXPROCESSING. It's unlikely that in 2013 you can find any Windows-based device which cannot render DirectX 9 in hardware.

    Black border.

    As of black border I have no idea. Hope that you've just missed 1 pixel when cropped your screenshot =)

    Power of 2 textures.

    I've read that in Directx 8 and newer all textures must be multiples of 2, but this is not my case since the image is 32x32.

    That is wrong (mostly). In present days you can (and will want) to make use of textures of any size. It only depends on hardware capabilities. But again here, it is unlikely that you can find non-pow2-texture device in 2013.

    Imagine that you have big textures, such as 800x800. Resizing its to 1024x1024 would be a huge hard drive space, system memory and GPU memory waste.

    If you still in doubt if you have pow-2 capable device or not, use GetDeviceCaps and check flag D3DPTEXTURECAPS_POW2.

    A little more grumbling.

    As of those strange oldish things in your code, from times when DirectX 8 was common and DirectX 9 was high-end. There is mo place for it in year 2013. Probably, you will want to drop out (and burn) your current guide or book and pick up something more fresh, like DirectX 11 (not 10) and feel the power. Or, at least, latest DirectX 9, not ancient one.

    Good luck and happy coding! =)