Sign in to follow this  
Bearhugger

How do I properly align objects in 2D?

Recommended Posts

Whenever I draw 2D objects on the screen that need to be aligned, such as text and tiles, it is never well aligned on the X and Y coordinates. For example, when I draw a line of text, some characters are one pixel higher then others. I know about the -0.5f trick, but the problems reappear whenever I change the game's resolution. Here is the code for my DrawBitmap method:
void DxVideo::DrawBitmap( Bitmap * pSource, int nDestX, int nDestY, int nDestWidth, int nDestHeight, int nSrcX, int nSrcY, int nSrcWidth, int nSrcHeight )
{
    const D3DXVECTOR3 Axis( 0.0f, 0.0f, 1.0f );
    DxBitmap * pDxSource = reinterpret_cast< DxBitmap * >( pSource );
    TEXTURED_VERTEX * pVertices;

    // starts rendering
    _BeginScene();

    // get the vertices
    _PrepareTexturedVertexBuffer( 4 );
    m_pTexturedVertexBuffer->Lock( 0, sizeof( TEXTURED_VERTEX ) * 4, reinterpret_cast< void ** >( &pVertices ), 0 );
    
    // set the vertices
    pVertices[ 0 ].fX = nDestWidth / -2.0f;
    pVertices[ 0 ].fY = nDestHeight / -2.0f;
    pVertices[ 0 ].fZ = static_cast< float >( pDxSource->m_nZValue );
    pVertices[ 0 ].fU = static_cast< float >( nSrcX ) / static_cast< float >( pDxSource->m_nTextureWidth );
    pVertices[ 0 ].fV = static_cast< float >( nSrcY ) / static_cast< float >( pDxSource->m_nTextureHeight );
    pVertices[ 0 ].dwColor = pDxSource->m_ColorModifier;
    pVertices[ 1 ].fX = nDestWidth / 2.0f;
    pVertices[ 1 ].fY = nDestHeight / -2.0f;
    pVertices[ 1 ].fZ = static_cast< float >( pDxSource->m_nZValue );
    pVertices[ 1 ].fU = static_cast< float >( nSrcX + nSrcWidth ) / static_cast< float >( pDxSource->m_nTextureWidth );
    pVertices[ 1 ].fV = static_cast< float >( nSrcY ) / static_cast< float >( pDxSource->m_nTextureHeight );
    pVertices[ 1 ].dwColor = pDxSource->m_ColorModifier;
    pVertices[ 2 ].fX = nDestWidth / 2.0f;
    pVertices[ 2 ].fY = nDestHeight / 2.0f;
    pVertices[ 2 ].fZ = static_cast< float >( pDxSource->m_nZValue );
    pVertices[ 2 ].fU = static_cast< float >( nSrcX + nSrcWidth ) / static_cast< float >( pDxSource->m_nTextureWidth );
    pVertices[ 2 ].fV = static_cast< float >( nSrcY + nSrcHeight ) / static_cast< float >( pDxSource->m_nTextureHeight );
    pVertices[ 2 ].dwColor = pDxSource->m_ColorModifier;
    pVertices[ 3 ].fX = nDestWidth / -2.0f;
    pVertices[ 3 ].fY = nDestHeight / 2.0f;
    pVertices[ 3 ].fZ = static_cast< float >( pDxSource->m_nZValue );
    pVertices[ 3 ].fU = static_cast< float >( nSrcX ) / static_cast< float >( pDxSource->m_nTextureWidth );
    pVertices[ 3 ].fV = static_cast< float >( nSrcY + nSrcHeight ) / static_cast< float >( pDxSource->m_nTextureHeight );
    pVertices[ 3 ].dwColor = pDxSource->m_ColorModifier;

    // unlock the buffer and set it as the source
    m_pTexturedVertexBuffer->Unlock();
    m_pD3dDevice->SetStreamSource( 0, m_pTexturedVertexBuffer, 0, sizeof( TEXTURED_VERTEX ));

    // set the vertex type
    m_pD3dDevice->SetFVF( PPFVF_TEXTURED );
    
    // set the blending mode
    SetBlendMode( pDxSource->m_BlendMode );

    // set the texture
    if( m_pActiveTexture != pDxSource->m_pTexture )
    {
        m_pD3dDevice->SetTexture( 0, pDxSource->m_pTexture );
        m_pActiveTexture = pDxSource->m_pTexture;
    }

    // save the old view matrix
    m_pMatrixStack->Push();

    // rotate the view
    if( pDxSource->m_nRotation != 0 )
        m_pMatrixStack->RotateAxis( &Axis, pDxSource->m_nRotation * D3DX_PI / 180.0f );

    // mirror
    if( pDxSource->m_MirrorMode == MIRRORMODE_FLIPBOTH )
        m_pMatrixStack->Scale( -1.0f, -1.0f, 1.0f );
    else if( pDxSource->m_MirrorMode == MIRRORMODE_FLIPHORIZONTAL )
        m_pMatrixStack->Scale( -1.0f, 1.0f, 1.0f );
    else if( pDxSource->m_MirrorMode == MIRRORMODE_FLIPVERTICAL )
        m_pMatrixStack->Scale( 1.0f, -1.0f, 1.0f );

    // translate
    m_pMatrixStack->Translate( nDestX + nDestWidth / 2.0f, nDestY + nDestHeight / 2.0f, 0.0f );
    
    // apply the resulting view matrix
    m_pD3dDevice->SetTransform( D3DTS_VIEW, m_pMatrixStack->GetTop() );

    // draw the quad
    m_pD3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

    // restore the old view matrix
    m_pMatrixStack->Pop();
}
And here is the code where I initialize the D3D parameters, in case there is any option I forgot to set.
bool DxVideo::_ResetDeviceParameters()
{
    float fTemp;

    // reset the transform matrices
    m_pD3dDevice->SetTransform( D3DTS_PROJECTION, &m_CurrentProjectionMatrix );

    // no texture
    m_pActiveTexture = NULL;

    // turn off lighting
    m_pD3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

    // show back-facing polygons
    m_pD3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
    
    // disable the depth buffer
    m_pD3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
    m_pD3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
    
    // make fully transparent pixels not affect the depth mask
    m_pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
    m_pD3dDevice->SetRenderState( D3DRS_ALPHAREF, 0 );
    m_pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL );
    
    // enable alpha blending
    m_pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
    m_CurrentBlendingMode = Video::BLENDMODE_INVALID;
    
    // linear fog, white by default
    m_pD3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_LINEAR );
    fTemp = 0.0f;
    m_pD3dDevice->SetRenderState( D3DRS_FOGSTART, *( reinterpret_cast< DWORD * >( &fTemp )));
    fTemp = 1.0f;
    m_pD3dDevice->SetRenderState( D3DRS_FOGEND, *( reinterpret_cast< DWORD * >( &fTemp )));
    
    return true;
}
Does anyone have an idea of what I am doing wrong? I have lost a lot of time with this issue.

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