Question

I am trying to build a simple 2D game using 2D sprites with DirectX 9, and I'm having problems getting the images to come out cleanly. I'd like to load bmp images and display them on the screen as is (no interpolation, no magnification, no filtering or anti-aliasing, etc).

I'm sure I'm missing something, but when I try and render a 100x100 bmp to the screen, it looks choppy and distorted, like a pixel art image would normally look when shrunken slightly. I want the bmp to look exactly as it does when loaded in MS Paint.

Does anyone have any idea why this might be the case? My code is shown below:

Initialization code:

g_DxCom = Direct3DCreate9( D3D_SDK_VERSION );
if ( g_DxCom == NULL )
{
    return false;
}

D3DDISPLAYMODE d3dDisplayMode;

if ( FAILED( g_DxCom->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3dDisplayMode ) ) )
{
    return false;
}

D3DPRESENT_PARAMETERS d3dPresentParameters;
::ZeroMemory( &d3dPresentParameters, sizeof(D3DPRESENT_PARAMETERS) );
d3dPresentParameters.Windowed = FALSE;
d3dPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPresentParameters.BackBufferFormat = d3dDisplayMode.Format;  // D3DFMT_X8R8G8B8
d3dPresentParameters.BackBufferWidth = d3dDisplayMode.Width;
d3dPresentParameters.BackBufferHeight = d3dDisplayMode.Height;
d3dPresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
                                    D3DDEVTYPE_HAL,
                                    this->hWnd,
                                    D3DCREATE_HARDWARE_VERTEXPROCESSING,
                                    &d3dPresentParameters,
                                    &pd3dDevice ) ) )
{
    if ( FAILED( g_DxCom->CreateDevice( D3DADAPTER_DEFAULT,
                                        D3DDEVTYPE_HAL,
                                        this->hWnd,
                                        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                        &d3dPresentParameters,
                                        &pd3dDevice ) ) )
    {
        return false;
    }
}

texture = NULL;
bg_texture = NULL;

Render code:

LPDIRECT3DDEVICE9   g_dxDevice;

float float1 = 99.5f;    // I'd like to render my 100x100 sprite from screen coordinates 100, 100 to 200, 200
float float2 = 198.5f;

CUSTOMVERTEX OurVertices[] =
{
    { float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
    { float1, float1, 1.0f, 1.0f, 0.0f, 0.0f },
    { float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
    { float1, float2, 1.0f, 1.0f, 0.0f, 1.0f },
    { float2, float1, 1.0f, 1.0f, 1.0f, 0.0f },
    { float2, float2, 1.0f, 1.0f, 1.0f, 1.0f }
};

LPDIRECT3DVERTEXBUFFER9 v_buffer;

g_dxDevice->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX),
                                0,
                                CUSTOMFVF,
                                D3DPOOL_MANAGED,
                                &v_buffer,
                                NULL );

VOID* pVoid;

// Lock the vertex buffer into memory
v_buffer->Lock( 0, 0, &pVoid, 0 );

// Copy our vertex buffer to memory
::memcpy( pVoid, OurVertices, sizeof(OurVertices) );

// Unlock buffer
v_buffer->Unlock();

LPDIRECT3DTEXTURE9 g_texture;
HRESULT hError;

DWORD dwTextureFilter = D3DTEXF_NONE;

g_dxDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, dwTextureFilter );
g_dxDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, dwTextureFilter );

g_dxDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
g_dxDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);

hError = D3DXCreateTextureFromFile( g_dxDevice, L"Test.bmp", &g_texture );   // 100x100 sprite

g_dxDevice->SetTexture( 0, g_texture );

g_dxDevice->Clear( 0,
                   NULL,
                   D3DCLEAR_TARGET,
                   D3DCOLOR_XRGB( 0, 40, 100 ),
                   1.0f,
                   0 );

g_dxDevice->BeginScene();

// Do rendering on the back buffer here
g_dxDevice->SetFVF( CUSTOMFVF );
g_dxDevice->SetStreamSource( 0, v_buffer, 0, sizeof(CUSTOMVERTEX) );
g_dxDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 6 );

g_dxDevice->EndScene();

g_dxDevice->Present( NULL, NULL, NULL, NULL );

g_texture->Release();
v_buffer->Release();
Was it helpful?

Solution

Okay, so I've finally figured it out, and I should have known this was the case. It looks like DirectX9 only works with textures with sizes that are multiples of 2. If I change the texture so that the sprite square is 128 x 128 (just adding some transparency) and run the application with float2 changed appropriately, there is no distortion in the rendered image.

Hurrah...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top