如何在场景中绘制文字?

时间:2013-02-20 15:35:47

标签: c++ directx directx-9

我有一些代码,我很久以前就从互联网上下载了这些代码,我想玩它。

所以我提取了有趣的部分,创建了一个代理d3d9.dll并连接到游戏。

现在我有一个问题,因为我在这两个代码片段之间的图形中找不到差异,这两个代码片段决定是否必须在屏幕上或游戏场景中绘制顶点

(我的意思是,就像 - 一个HUD在屏幕上,你总是看到它,并且车辆在游戏场景中,当你转身时你看不到它。)

第一部分是我要编辑的代码,我想让它在游戏场景中显示文本,而不是在屏幕上显示为静态文本。

DLL中使用的代码是:

float                   m_fTexCoords[224][4];

float CD3DFont::DrawLength ( const char *szText ) const
{
    float   len = 0.0f;
    float   sub = ( m_dwCreateFlags & FCR_BORDER ) ? 2.0f : 0.0f;

    for ( const char *p = szText; *p; p++ )
    {
        int c = *(unsigned char *)p - 32;
        if ( c >= 0 && c < 224 )
            len += ( (m_fTexCoords[c][2] - m_fTexCoords[c][0]) * m_texWidth - sub ) - m_chrSpacing * 2;
    }

    return len;
}

HRESULT CD3DFont::Print ( float x, float y, DWORD color, const char *szText)
{
    if ( !m_isReady )
        return E_FAIL;

    float   strWidth = DrawLength( szText );

    x -= (float)m_chrSpacing;

    if ( FAILED(this->BeginRender()) )
        return E_FAIL;

    DWORD   fvf;
    m_pD3Ddev->GetFVF( &fvf );
    m_pD3Ddev->SetFVF( D3DFVF_BITMAPFONT );
    m_pD3Ddev->SetTexture( 0, m_pD3Dtex );
    m_pD3Ddev->SetStreamSource( 0, m_pD3Dbuf, 0, sizeof(d3dvertex_s) );

    while ( *szText )
    {
        UINT        usedTriangles = 0;
        d3dvertex_s *pVertex;

        if ( FAILED(m_pD3Dbuf->Lock(0, 0, (void **) &pVertex, D3DLOCK_DISCARD)) )
        {
            m_pD3Ddev->SetFVF( fvf );
            this->EndRender();
            return E_FAIL;
        }


        for ( ; *szText; szText++ )
        {
            int c = *(unsigned char *)szText - 32;
            if ( !(c >= 0 && c < 224) )
                continue;

            float   tx1 = m_fTexCoords[c][0];
            float   tx2 = m_fTexCoords[c][2];
            float   ty1 = m_fTexCoords[c][1];
            float   ty2 = m_fTexCoords[c][3];
            float   w = ( tx2 - tx1 ) * m_texWidth;
            float   h = ( ty2 - ty1 ) * m_texHeight;

            *pVertex++ = Init2DVertex( x - 0.5f, y - 0.5f, color, tx1, ty1 );           //topleft
            *pVertex++ = Init2DVertex( x + w - 0.5f, y - 0.5f, color, tx2, ty1 );       //topright
            *pVertex++ = Init2DVertex( x - 0.5f, y + h - 0.5f, color, tx1, ty2 );       //bottomleft
            *pVertex++ = Init2DVertex( x + w - 0.5f, y - 0.5f, color, tx2, ty1 );       //topright
            *pVertex++ = Init2DVertex( x + w - 0.5f, y + h - 0.5f, color, tx2, ty2 );   //bottomright
            *pVertex++ = Init2DVertex( x - 0.5f, y + h - 0.5f, color, tx1, ty2 );       //bottomleft
            if ( m_dwCreateFlags & FCR_BORDER )
                w -= 2.0f;

            x += w - ( m_chrSpacing * 2 );

            usedTriangles += 2;
            if ( usedTriangles >= m_maxTriangles )
                break;
        }

        if ( usedTriangles > 0 )
        {
            m_pD3Dbuf->Unlock();
            m_pD3Ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, usedTriangles );
        }
    }

    m_pD3Ddev->SetFVF( fvf );
    this->EndRender();

    return S_OK;
}

然后我看到了一个名为“DrawLine”的函数,所以我决定检查它并查看它的作用,它在游戏世界中划了一条线,而不是屏幕上的静态线,所以当我转身时看不到具体的位置 - 我不会看到这一行:

bool CD3DRender::DrawLine ( const D3DXVECTOR3 &a, const D3DXVECTOR3 &b, DWORD dwColor )
{
    if ( FAILED(CD3DBaseRender::BeginRender()) )
        return false;

    ////////////////////////////////////////////////////
    // Make sure we have a valid vertex buffer.
    if ( m_pD3Dbuf == NULL )
    {
        return false;
    }

    m_pD3Ddev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
    m_pD3Ddev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
    //m_pD3Ddev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    //m_pD3Ddev->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );

    m_pD3Ddev->SetRenderState( D3DRS_CLIPPING, false );
    m_pD3Ddev->SetRenderState ( D3DRS_ZENABLE, false );
    //m_pD3Ddev->SetRenderState ( D3DRS_LIGHTING, false );
    D3DLVERTEX  lineList[2];

    //////////////////////////////////////////////////
    // Lock the vertex buffer and copy in the verts.
    m_pD3Dbuf->Lock( 0, 0, (void **) &lineList, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK ); // flogs: D3DLOCK_NOSYSLOCK, D3DLOCK_DISCARD
    {
        lineList[0].x = a.x;
        lineList[0].y = a.y;
        lineList[0].z = a.z;
        lineList[0].color = dwColor;
        lineList[0].specular = dwColor;

        lineList[1].x = b.x;
        lineList[1].y = b.y;
        lineList[1].z = b.z;
        lineList[1].color = dwColor;
        lineList[1].specular = dwColor;
    }

    m_pD3Dbuf->Unlock();

    // store FVF to restore original at the end of this function
    DWORD       fvf;
    m_pD3Ddev->GetFVF( &fvf );
    m_pD3Ddev->SetFVF( D3DFVF_LVERTEX );
    //m_pD3Ddev->SetFVF( D3DFVF_PRIMITIVES );

    ////////////////////////////////////////////////////
    // Draw!
    m_pD3Ddev->DrawPrimitiveUP( D3DPT_LINESTRIP, 1, lineList, sizeof(lineList) / 2 );

    // reset states
    m_pD3Ddev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
    m_pD3Ddev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
    m_pD3Ddev->SetRenderState ( D3DRS_ZENABLE, true );
    m_pD3Ddev->SetRenderState( D3DRS_CLIPPING, true );

    // restore FVF
    m_pD3Ddev->SetFVF( fvf );

    CD3DBaseRender::EndRender();

    return true;
}

现在的问题是:区别在哪里? 这段代码告诉了哪里:

“嘿,在播放器屏幕上绘制文字并让它留在那里”?

“嘿,在游戏世界中画这个,只画出玩家能看到的那个”?

有人能指出我正确的方向吗?或者也许如何编辑打印功能以显示游戏世界中的文字?

提前感谢。


简明我想要实现的例子:

现在打印什么(绿色框)以及我想要它做什么(红色框)

(从另一个游戏中获取的屏幕,其中存在这样的“3d文本”,但该程序是封闭源代码): enter image description here enter image description here

您可以看到红色框中文本的位置已在屏幕上更改,但未在游戏中更改。我也想这样做。 (你也可以看到红色和蓝色的#)

DrawLine代码已经在游戏中创建了一条线,但它只是一条线,而不是文本,所以最终如何发生另一条线而另一条线没有?

1 个答案:

答案 0 :(得分:1)

我只能猜测你的其余代码是做什么的。似乎Print方法是在一个环境中调用的,其中变换矩阵已设置为形成正交视图,而DrawLine方法使用游戏的矩阵。

但是,您不想在场景中绘制文本。这将导致文本的错位和错误缩放。你真正想要做的是在屏幕上获得场景位置的位置并在那里绘制文本。您可以使用D3DXVec3Project功能。一定要提供正确的变换矩阵。不是2D渲染的更新版本。