//----------------------------------------------------------------------------- // Name: DrawText() // Desc: Draws 2D text //----------------------------------------------------------------------------- HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, TCHAR* strText, DWORD dwFlags ) { if( m_pd3dDevice == NULL || strText == NULL ) return E_FAIL; // Setup renderstate RestoreDeviceObjects(); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); } FLOAT fStartX = sx; // Fill vertex buffer FONT2DVERTEX* pVertices = NULL; DWORD dwNumTriangles = 0; pVertices = &m_VB[0]; while( *strText ) { TCHAR c = *strText++; if( c == _T('\n') ) { sx = fStartX; sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; } if( c < _T(' ') ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale; *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.5f,2.0f), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.5f,2.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.5f,2.0f), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.5f,2.0f), dwColor, tx2, ty1 ); dwNumTriangles += 2; m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1, &m_VB[0], dwNumTriangles*2, D3DDP_WAIT); pVertices = &m_VB[0]; dwNumTriangles = 0L; sx += w; } return S_OK; }
//----------------------------------------------------------------------------- // Name: DrawText() // Desc: Draws 2D text. Note that sx and sy are in pixels //----------------------------------------------------------------------------- HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, const TCHAR* strText, DWORD dwFlags ) { if( m_pd3dDevice == NULL ) return E_FAIL; // Setup renderstate m_pStateBlockSaved->Capture(); m_pStateBlockDrawText->Apply(); m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX ); m_pd3dDevice->SetPixelShader( NULL ); m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); } // Center the text block in the viewport if( dwFlags & D3DFONT_CENTERED_X ) { D3DVIEWPORT9 vp; m_pd3dDevice->GetViewport( &vp ); const TCHAR* strTextTmp = strText; float xFinal = 0.0f; while( *strTextTmp ) { TCHAR c = *strTextTmp++; if( c == _T('\n') ) break; // Isn't supported. if( (c-32) < 0 || (c-32) >= 128-32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; xFinal += w - (2 * m_dwSpacing); } sx = (vp.Width-xFinal)/2.0f; } if( dwFlags & D3DFONT_CENTERED_Y ) { D3DVIEWPORT9 vp; m_pd3dDevice->GetViewport( &vp ); float fLineHeight = ((m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight); sy = (vp.Height-fLineHeight)/2; } // Adjust for character spacing sx -= m_dwSpacing; FLOAT fStartX = sx; // Fill vertex buffer FONT2DVERTEX* pVertices = NULL; DWORD dwNumTriangles = 0; m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); while( *strText ) { TCHAR c = *strText++; if( c == _T('\n') ) { sx = fStartX; sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; } if( (c-32) < 0 || (c-32) >= 128-32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale; if( c != _T(' ') ) { *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); dwNumTriangles += 2; if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); pVertices = NULL; m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; } } sx += w - (2 * m_dwSpacing); } // Unlock and render the vertex buffer m_pVB->Unlock(); if( dwNumTriangles > 0 ) m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); // Restore the modified renderstates m_pStateBlockSaved->Apply(); return S_OK; }
int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dwColor, const char* strText) { if (!m_pVB) return 0; UINT stride = sizeof(FONT2DVERTEX); UINT bufoffset = 0; float scalex = 1 / (float)D3D::GetBackBufferWidth() * 2.f; float scaley = 1 / (float)D3D::GetBackBufferHeight() * 2.f; float sizeratio = size / (float)m_LineHeight; // translate starting positions float sx = x * scalex - 1.f; float sy = 1.f - y * scaley; char c; // Fill vertex buffer FONT2DVERTEX* pVertices; int dwNumTriangles = 0L; D3D11_MAPPED_SUBRESOURCE vbmap; HRESULT hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap); if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__); pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; // set general pipeline state D3D::stateman->PushBlendState(m_blendstate); D3D::stateman->PushRasterizerState(m_raststate); D3D::stateman->Apply(); D3D::context->PSSetShader(m_pshader, NULL, 0); D3D::context->VSSetShader(m_vshader, NULL, 0); D3D::context->IASetInputLayout(m_InputLayout); D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::context->PSSetShaderResources(0, 1, &m_pTexture); float fStartX = sx; while (c = *strText++) { if (c == ('\n')) { sx = fStartX; sy -= scaley * size; } if (c < (' ')) continue; c -= 32; float tx1 = m_fTexCoords[c][0]; float ty1 = m_fTexCoords[c][1]; float tx2 = m_fTexCoords[c][2]; float ty2 = m_fTexCoords[c][3]; float w = (float)(tx2-tx1) * m_dwTexWidth * scalex * sizeratio; float h = (float)(ty1-ty2) * m_dwTexHeight * scaley * sizeratio; FONT2DVERTEX v[6]; v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2); v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1); v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2); v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1); v[4] = v[2]; v[5] = v[1]; memcpy(pVertices, v, 6*sizeof(FONT2DVERTEX)); pVertices+=6; dwNumTriangles += 2; if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6)) { context->Unmap(m_pVB, 0); D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); D3D::context->Draw(3 * dwNumTriangles, 0); dwNumTriangles = 0; D3D11_MAPPED_SUBRESOURCE vbmap; hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap); if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__); pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; } sx += w + spacing * scalex * size; } // Unlock and render the vertex buffer context->Unmap(m_pVB, 0); if (dwNumTriangles > 0) { D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); D3D::context->Draw(3 * dwNumTriangles, 0); } D3D::stateman->PopBlendState(); D3D::stateman->PopRasterizerState(); return S_OK; }
//----------------------------------------------------------------------------- // Name: DrawText() // Desc: Draws 2D text. Note that sx and sy are in pixels //----------------------------------------------------------------------------- HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, const TCHAR* strText ) { if( m_pd3dDevice == NULL ) return E_FAIL; effect->SetTechnique("screenspace") &&VERIFY_RESULT; Array<FONT2DVERTEX> vertices; // Adjust for character spacing sx -= m_dwSpacing; FLOAT fStartX = sx; while( *strText ) { TCHAR c = *strText++; if( c == _T('\n') ) { sx = fStartX; sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; } if( (c-32) < 0 || (c-32) >= 128-32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth ; FLOAT h = (ty2-ty1) * m_dwTexHeight; if( c != _T(' ') ) { vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.01f,1.0f), dwColor, tx1, ty2 )); vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.01f,1.0f), dwColor, tx1, ty1 )); vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.01f,1.0f), dwColor, tx2, ty2 )); vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.01f,1.0f), dwColor, tx2, ty1 )); vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.01f,1.0f), dwColor, tx2, ty2 )); vertices.Add(InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.01f,1.0f), dwColor, tx1, ty1 )); } sx += w - (2 * m_dwSpacing); } if( vertices.count == 0 ) return S_OK; unsigned n; int i; effect->Begin(&n,1) &&VERIFY_RESULT; for(i=0;i<(int)n;i++) { effect->BeginPass(i) &&VERIFY_RESULT; m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, vertices.count/3, &vertices[0],sizeof(FONT2DVERTEX)); effect->EndPass(); } effect->End() &&VERIFY_RESULT; return S_OK; }
//----------------------------------------------------------------------------- // Name: DrawText() // Desc: Draws 2D text //----------------------------------------------------------------------------- HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, TCHAR* strText, DWORD dwFlags ) { if( m_pd3dDevice == NULL ) return E_FAIL; // Setup renderstate m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock ); m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock ); m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX ); m_pd3dDevice->SetPixelShader( NULL ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) ); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); } FLOAT fStartX = sx; // Fill vertex buffer FONT2DVERTEX* pVertices = NULL; DWORD dwNumTriangles = 0; m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); while( *strText ) { TCHAR c = *strText++; if( c == _T('\n') ) { sx = fStartX; sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; } if( (c-32) < 0 || (c-32) >= 128-32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale; if( c != _T(' ') ) { *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); dwNumTriangles += 2; if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); pVertices = NULL; m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; } } sx += w - (2 * m_dwSpacing); } // Unlock and render the vertex buffer m_pVB->Unlock(); if( dwNumTriangles > 0 ) m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); // Restore the modified renderstates m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock ); return S_OK; }
int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dwColor, const std::string& text) { if (!m_pVB12) return 0; UINT stride = sizeof(FONT2DVERTEX); UINT bufoffset = 0; float scalex = 1 / (float)D3D::GetBackBufferWidth() * 2.f; float scaley = 1 / (float)D3D::GetBackBufferHeight() * 2.f; float sizeratio = size / (float)m_LineHeight; // translate starting positions float sx = x * scalex - 1.f; float sy = 1.f - y * scaley; // Fill vertex buffer FONT2DVERTEX* pVertices12; int dwNumTriangles = 0L; pVertices12 = (FONT2DVERTEX*)m_pVB12data + m_pVB12offset / sizeof(FONT2DVERTEX); // set general pipeline state D3D::currentCommandList->SetPipelineState(m_pPso); D3D::commandListMgr->dirtyPso = true; D3D::currentCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::commandListMgr->currentTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; D3D::currentCommandList->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_SRV, m_pTexture12gpu); // If we are close to running off edge of vertex buffer, jump back to beginning. if (m_pVB12offset + text.length() * 6 * sizeof(FONT2DVERTEX) >= MAX_NUM_VERTICES * sizeof(FONT2DVERTEX)) { m_pVB12offset = 0; pVertices12 = (FONT2DVERTEX*)m_pVB12data; } float fStartX = sx; for (char c : text) { if (c == '\n') { sx = fStartX; sy -= scaley * size; } if (!std::isprint(c)) continue; c -= 32; float tx1 = m_fTexCoords[c][0]; float ty1 = m_fTexCoords[c][1]; float tx2 = m_fTexCoords[c][2]; float ty2 = m_fTexCoords[c][3]; float w = (float)(tx2-tx1) * m_dwTexWidth * scalex * sizeratio; float h = (float)(ty1-ty2) * m_dwTexHeight * scaley * sizeratio; FONT2DVERTEX v[6]; v[0] = InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2); v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1); v[2] = InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2); v[3] = InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1); v[4] = v[2]; v[5] = v[1]; memcpy(pVertices12, v, 6 * sizeof(FONT2DVERTEX)); pVertices12 += 6; dwNumTriangles += 2; sx += w + spacing * scalex * size; } // Render the vertex buffer if (dwNumTriangles > 0) { D3D::currentCommandList->IASetVertexBuffers(0, 1, &m_pVB12view); D3D::currentCommandList->DrawInstanced(3 * dwNumTriangles, 1, m_pVB12offset / sizeof(FONT2DVERTEX), 0); } m_pVB12offset += 3 * dwNumTriangles * sizeof(FONT2DVERTEX); return S_OK; }
bool CD3DMGEng::DrawText2D ( float x, float y, DWORD dwColor, const TCHAR *wszText, float fTextSize, FONTFLAGS ffFlags, FONTSET fsSet ) { D3DSPRITEVERTEX2D *pVertices; //////////////////////////////////////////////////// // Make sure we have a valid vertex buffer. if ( m_pVB == NULL ) { return false; } //////////////////////////////////////////////////// // Make sure our texture and coords are loaded. if ( m_pFontTexture == NULL || m_bFontInfoLoaded == false ) { return false; } /////////////////////////////////////////////////// // Setup the rendering. m_pDevice->SetFVF( D3DFVF_SPRITEVERTEX2DTEX ); m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(D3DSPRITEVERTEX2D) ); m_pDevice->SetTexture( 0, m_pFontTexture ); /////////////////////////////////////////////////// // Do flag processing before we go any further. if ( ffFlags ) { SIZE sz; // First, get extent of drawn text. UTIL_GetTextExtent(wszText, &sz, fTextSize); // Do math on x coordinate accordingly. switch ( ffFlags ) { case D3DFF_CENTERED: x -= sz.cx/2; break; case D3DFF_RIGHT: x += sz.cx; break; case D3DFF_LEFT: default: break; } } DWORD dwTriangleCount = 0; const float fStartX = x; m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); while ( *wszText ) { TCHAR c = *wszText++; float fScl = fTextSize; if ( c == _T('\n') ) { x = fStartX; y += m_aFontCoords[fsSet].fHeight * fScl; continue; } if ( c < _T(' ') || c > _T(128) ) { continue; } float tx1 = m_aFontCoords[fsSet+c-32].tx1; float tx2 = m_aFontCoords[fsSet+c-32].tx2; float ty1 = m_aFontCoords[fsSet+c-32].ty1; float ty2 = m_aFontCoords[fsSet+c-32].ty2; float w = m_aFontCoords[fsSet+c-32].fWidth; float h = m_aFontCoords[fsSet+c-32].fHeight; w *= fScl; h *= fScl; if ( c == _T(' ') ) { x += w; continue; } *pVertices++ = InitFont2DVertex( x, y, 0.0f, 1.0f, dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( x+w, y, 0.0f, 1.0f, dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( x, y+h, 0.0f, 1.0f, dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( x, y+h, 0.0f, 1.0f, dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( x+w, y, 0.0f, 1.0f, dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( x+w, y+h, 0.0f, 1.0f, dwColor, tx2, ty2 ); x += w; dwTriangleCount += 2; //////////////////////////////////////////////////// // If we've gone over our limit, draw what we have. if ( dwTriangleCount*3 >= D3DSPRITE_NUMVERTS-6 ) { m_pVB->Unlock(); m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwTriangleCount ); m_pVB->Lock( 0, 0, (void**)&(pVertices=NULL), D3DLOCK_DISCARD ); dwTriangleCount = 0L; } } m_pVB->Unlock(); //////////////////////////////////////////////////// // Draw if we have anything. if ( dwTriangleCount > 0 ) { m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwTriangleCount ); } return true; }
//----------------------------------------------------------------------------- // Name: DrawText() // Desc: Draws 2D text //----------------------------------------------------------------------------- int32 CFont::m_DrawText(float4 sx, float4 sy, uint32 color, char8 *text, int32 start_char, int32 end_char, float4 xScale, float4 yScale) { int32 l; char8 c; float4 tx1, ty1, tx2, ty2, h, w, sz, rhw, fStartX; D3DVIEWPORT8 vp; FONT2DVERTEX *pVertices = NULL; int32 dwNumTriangles = 0; if ((start_char<0) || (end_char<0)) return(0); if (end_char<start_char) return(0); l=strlen(text); if (start_char>=l) return(0); if (end_char >= l) return(0); m_SetStates(); p_RenderLib->p_Device->GetViewport(&vp); sx = (sx+1.0f)*vp.Width/2; sy = (sy+1.0f)*vp.Height/2; sz = 0.9f; rhw = 1.0f; fStartX = sx; float4 fLineHeight = (p_TexCoords[0][3] - p_TexCoords[0][1] )*p_TexHeight; // Fill vertex buffer p_VertexBuffer->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD); l=0; while ((*text) && (l<=end_char)) { c = *text++; tx1 = p_TexCoords[c-32][0]; ty1 = p_TexCoords[c-32][1]; tx2 = p_TexCoords[c-32][2]; ty2 = p_TexCoords[c-32][3]; w = (tx2-tx1)*p_TexWidth; h = (ty2-ty1)*p_TexHeight; w *= (xScale*vp.Width)/fLineHeight; h *= (yScale*vp.Height)/fLineHeight; if (l<start_char) goto next_letter; if (c < ' ') goto next_letter; else if (c =='\n') { sx = fStartX; sy += (p_TexCoords[0][3]-p_TexCoords[0][1])*p_TexHeight; } else if (c != ' ') { *pVertices++ = InitFont2DVertex(sx+0-0.5f, sy+h-0.5f, sz, rhw, color, tx1, ty2); *pVertices++ = InitFont2DVertex(sx+0-0.5f, sy+0-0.5f, sz, rhw, color, tx1, ty1); *pVertices++ = InitFont2DVertex(sx+w-0.5f, sy+h-0.5f, sz, rhw, color, tx2, ty2); *pVertices++ = InitFont2DVertex(sx+w-0.5f, sy+0-0.5f, sz, rhw, color, tx2, ty1); *pVertices++ = InitFont2DVertex(sx+w-0.5f, sy+h-0.5f, sz, rhw, color, tx2, ty2); *pVertices++ = InitFont2DVertex(sx+0-0.5f, sy+0-0.5f, sz, rhw, color, tx1, ty1); dwNumTriangles += 2; if (dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) { // Unlock, render, and relock the vertex buffer p_VertexBuffer->Unlock(); p_RenderLib->p_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); pVertices = NULL; p_VertexBuffer->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD); dwNumTriangles = 0; } } next_letter: ; sx += w; l++; } // Unlock and render the vertex buffer p_VertexBuffer->Unlock(); if (dwNumTriangles > 0) p_RenderLib->p_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); p_RenderLib->p_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); return(1); }
HRESULT cFont::DrawText(FLOAT sx, FLOAT sy, DWORD dwColor, const char* strText, DWORD dwFlags) { if (this->m_pDevice == NULL)return E_FAIL; m_pStateBlockSaved->Capture(); m_pStateBlockDrawText->Apply(); this->m_pDevice->SetFVF(D3DFVF_FONT2DVERTEX); this->m_pDevice->SetPixelShader(NULL); this->m_pDevice->SetStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX)); if (dwFlags & D3DFONT_FILTERED) { this->m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); this->m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); } if (dwFlags & DT_RIGHT) { SIZE sz; GetTextExtent(strText, &sz); sx -= (FLOAT)sz.cx; } if (dwFlags & DT_CENTER) { SIZE sz; GetTextExtent(strText, &sz); sx -= (FLOAT)(sz.cx / 2.0); } FLOAT fStartX = sx; FONT2DVERTEX* pVertices = NULL; DWORD dwNumTriangles = 0; m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); while (*strText) { unsigned char c = *strText++; if (c == '\n') { sx = fStartX; sy += (m_fTexCoords[0][3] - m_fTexCoords[0][1])*dwHeight; } if (CheckChar(c)) continue; FLOAT tx1 = m_fTexCoords[c - 32][0]; FLOAT ty1 = m_fTexCoords[c - 32][1]; FLOAT tx2 = m_fTexCoords[c - 32][2]; FLOAT ty2 = m_fTexCoords[c - 32][3]; FLOAT w = (tx2 - tx1) * dwWidth / m_fTextScale; FLOAT h = (ty2 - ty1) * dwHeight / m_fTextScale; if (c != ' ') { if (dwFlags & DT_SHADOW) { float sxa, sya; sxa = sx; sya = sy; sxa = sx + 1.0f; *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); sxa = sx - 1.0f; *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sxa + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); sya = sy - 1.0f; *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); sya = sy + 1.0f; *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sya + h - 0.5f, 0.9f, 1.0f), 0xff000000, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sya + 0 - 0.5f, 0.9f, 1.0f), 0xff000000, tx1, ty1); dwNumTriangles += 8; } *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), dwColor, tx1, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), dwColor, tx1, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), dwColor, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), dwColor, tx2, ty1); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + w - 0.5f, sy + h - 0.5f, 0.9f, 1.0f), dwColor, tx2, ty2); *pVertices++ = InitFont2DVertex(D3DXVECTOR4(sx + 0 - 0.5f, sy + 0 - 0.5f, 0.9f, 1.0f), dwColor, tx1, ty1); dwNumTriangles += 2; if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6)) { this->m_pVB->Unlock(); this->m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); pVertices = NULL; this->m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); dwNumTriangles = 0L; } } sx += w; } this->m_pVB->Unlock(); if (dwNumTriangles > 0) this->m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); m_pStateBlockSaved->Apply(); return S_OK; }
int32 CFont::m_DrawAnimatedText(float4 x, float4 y, float4 xScale, float4 yScale, float4 end_xScale, float4 end_yScale, uint32 color, char8 *text, int32 start_char, int32 end_char, AD_Matrix *rot) { int32 l; char8 c; float4 tx1, ty1, tx2, ty2, h, w, sx, sy, sz, rhw, fStartX; float4 wrot, hrot; D3DVIEWPORT8 vp; FONT2DVERTEX *pVertices; int32 dwNumTriangles = 0L; #define ROT_2DPOINT(x, y) \ wrot=rot->a[0][0]*x+rot->a[0][1]*y; \ hrot=rot->a[1][0]*x+rot->a[1][1]*y; \ if ((start_char<0) || (end_char<0)) return(0); if (end_char<start_char) return(0); l=strlen(text); if ((start_char>=l) || (end_char >= l)) return(0); p_RenderLib->p_Device->GetViewport(&vp); sx = (x+1.0f)*vp.Width/2; sy = (y+1.0f)*vp.Height/2; sz = 0.9f; rhw = 1.0f; fStartX = sx; float4 fLineHeight = (p_TexCoords[0][3] - p_TexCoords[0][1] )*p_TexHeight; fLineHeight=1.0f/fLineHeight; // Fill vertex buffer p_VertexBuffer->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD); l=0; while ((*text) && (l<=end_char)) { c = *text++; tx1 = p_TexCoords[c-32][0]; ty1 = p_TexCoords[c-32][1]; tx2 = p_TexCoords[c-32][2]; ty2 = p_TexCoords[c-32][3]; w = (tx2-tx1)*p_TexWidth; h = (ty2-ty1)*p_TexHeight; if (l<start_char) { w *= (end_xScale*vp.Width)*fLineHeight; h *= (end_yScale*vp.Height)*fLineHeight; w=w*0.5f; goto next_letter; } else { w *= (xScale*vp.Width)*fLineHeight; h *= (yScale*vp.Height)*fLineHeight; w=w*0.5f; } if (c == '\n') { sx = fStartX; sy += yScale*vp.Height; } if (c < ' ') goto next_letter; if (c != ' ') { h=h*0.5f; ROT_2DPOINT(-w, h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx1, ty2); ROT_2DPOINT(-w, -h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx1, ty1); ROT_2DPOINT(w, h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx2, ty2); ROT_2DPOINT(w, -h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx2, ty1); ROT_2DPOINT(w, h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx2, ty2); ROT_2DPOINT(-w, -h) *pVertices++ = InitFont2DVertex(sx+w+wrot-0.5f, sy+h+hrot-0.5f, sz, rhw, color, tx1, ty1); dwNumTriangles += 2; if (dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) { // Unlock, render, and relock the vertex buffer p_VertexBuffer->Unlock(); p_RenderLib->p_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); p_VertexBuffer->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD); dwNumTriangles = 0; } } next_letter: ; sx=sx+2*w; l++; } // Unlock and render the vertex buffer p_VertexBuffer->Unlock(); if (dwNumTriangles > 0) p_RenderLib->p_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); return(1); }
void draw_filename_background(int iy1, int iy2, Filename_notice *notice) { if (notice == NULL) { return; } LPDIRECT3DDEVICE8 pd3dDevice = notice->pd3dDevice; // convenience D3DVIEWPORT8 vp; pd3dDevice->GetViewport(&vp); float x1 = 0; float y1 = (float)iy1; float x2 = (float)vp.Width; float y2 = (float)iy2; pd3dDevice->CaptureStateBlock(notice->dwSavedStateBlock); pd3dDevice->ApplyStateBlock(notice->dwDrawTextStateBlock); pd3dDevice->SetTexture(0, NULL); pd3dDevice->SetVertexShader(D3DFVF_FONT2DVERTEX); pd3dDevice->SetPixelShader(NULL); pd3dDevice->SetStreamSource(0, notice->pVB, sizeof(FONT2DVERTEX)); FONT2DVERTEX* pVertices; // dark almost opaque rectangle DWORD color = 0xB0000000; notice->pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD); pVertices[0] = InitFont2DVertex( D3DXVECTOR4(x1, y1, 0.5, 1), color, 0, 0); pVertices[1] = InitFont2DVertex( D3DXVECTOR4(x1, y2, 0.5, 1), color, 0, 1); pVertices[2] = InitFont2DVertex( D3DXVECTOR4(x2, y2, 0.5, 1), color, 1, 1); pVertices[3] = InitFont2DVertex( D3DXVECTOR4(x2, y1, 0.5, 1), color, 1, 0); notice->pVB->Unlock(); pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); // semi-transparent thin white lines color = 0x80ffffff; notice->pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD); pVertices[0] = InitFont2DVertex( D3DXVECTOR4(x1, y1, 0.5, 1), color, 0, 0); pVertices[1] = InitFont2DVertex( D3DXVECTOR4(x2, y1, 0.5, 1), color, 0, 1); pVertices[2] = InitFont2DVertex( D3DXVECTOR4(x1, y2 - 1, 0.5, 1), color, 1, 1); pVertices[3] = InitFont2DVertex( D3DXVECTOR4(x2, y2 - 1, 0.5, 1), color, 1, 0); notice->pVB->Unlock(); pd3dDevice->DrawPrimitive(D3DPT_LINELIST, 0, 2); pd3dDevice->ApplyStateBlock(notice->dwSavedStateBlock); }
void draw_filename_notice(int iy1, int iy2, Filename_notice *notice) { if (notice == NULL) { return; } LPDIRECT3DDEVICE8 pd3dDevice = notice->pd3dDevice; // convenience D3DVIEWPORT8 vp; pd3dDevice->GetViewport(&vp); float x1 = (float)(((int)vp.Width - notice->width)/2) - 0.5f; float y1 = (float)(iy1 + (iy2 - iy1 - notice->height)/2) - 0.5f; float x2 = x1 + notice->width; float y2 = y1 + notice->height; pd3dDevice->CaptureStateBlock(notice->dwSavedStateBlock); pd3dDevice->ApplyStateBlock(notice->dwDrawTextStateBlock); pd3dDevice->SetVertexShader(D3DFVF_FONT2DVERTEX); pd3dDevice->SetPixelShader(NULL); pd3dDevice->SetStreamSource(0, notice->pVB, sizeof(FONT2DVERTEX)); FONT2DVERTEX* pVertices; #if 1 notice->pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD); pVertices[0] = InitFont2DVertex( D3DXVECTOR4(x1, y1, 0.5, 1), 0xffffffff, 0, 0); pVertices[1] = InitFont2DVertex( D3DXVECTOR4(x1, y2, 0.5, 1), 0xffffffff, 0, 1); pVertices[2] = InitFont2DVertex( D3DXVECTOR4(x2, y2, 0.5, 1), 0xffffffff, 1, 1); pVertices[3] = InitFont2DVertex( D3DXVECTOR4(x2, y1, 0.5, 1), 0xffffffff, 1, 0); notice->pVB->Unlock(); // change this to 100 or 1000 to see drawing problem for (int i = 0; i < 1; i++) { pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); } #else static double spread = 1.0; for (int i = -250; i <= 250; i++) { double opacity = exp(-float(i) * i / (spread*spread))/spread; int alpha = (int)(opacity*0xff); if (alpha > 0) { DWORD color = (alpha << 24) | 0x00ffffff; notice->pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD); pVertices[0] = InitFont2DVertex( D3DXVECTOR4(x1 + i, y1, 0.5, 1), color, 0, 0); pVertices[1] = InitFont2DVertex( D3DXVECTOR4(x1 + i, y2, 0.5, 1), color, 0, 1); pVertices[2] = InitFont2DVertex( D3DXVECTOR4(x2 + i, y2, 0.5, 1), color, 1, 1); pVertices[3] = InitFont2DVertex( D3DXVECTOR4(x2 + i, y1, 0.5, 1), color, 1, 0); notice->pVB->Unlock(); pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); } } spread += 2; #endif pd3dDevice->ApplyStateBlock(notice->dwSavedStateBlock); }
int CD3DFont::DrawTextScaled(float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const std::string& Text) { if (!m_pVB) return 0; SetRenderStates(); D3D::ChangeStreamSource(0, m_pVB, 0, sizeof(FONT2DVERTEX)); float vpWidth = 1; float vpHeight = 1; float sx = x*vpWidth - 0.5f; float sy = y*vpHeight - 0.5f; float fStartX = sx; float invLineHeight = 1.0f / ((m_fTexCoords[0][3] - m_fTexCoords[0][1]) * m_dwTexHeight); // Fill vertex buffer FONT2DVERTEX* pVertices; int dwNumTriangles = 0L; m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); //First, let's measure the text float tw = 0; float mx = 0; float maxx = 0; for (char c : Text) { if (c == ('\n')) mx = 0; if (c < (' ')) continue; float tx1 = m_fTexCoords[c - 32][0]; float tx2 = m_fTexCoords[c - 32][2]; float w = (tx2 - tx1)*m_dwTexWidth; w *= (fXScale*vpHeight)*invLineHeight; mx += w + spacing*fXScale*vpWidth; if (mx > maxx) maxx = mx; } float offset = -maxx / 2; float wScale = (fXScale*vpHeight)*invLineHeight; float hScale = (fYScale*vpHeight)*invLineHeight; // Let's draw it for (char c : Text) { if (c == ('\n')) { sx = fStartX; sy += fYScale*vpHeight; } if (c < (' ')) continue; c -= 32; float tx1 = m_fTexCoords[c][0]; float ty1 = m_fTexCoords[c][1]; float tx2 = m_fTexCoords[c][2]; float ty2 = m_fTexCoords[c][3]; float w = (tx2 - tx1)*m_dwTexWidth; float h = (ty2 - ty1)*m_dwTexHeight; w *= wScale; h *= hScale; FONT2DVERTEX v[6]; v[0] = InitFont2DVertex(sx, sy + h, dwColor, tx1, ty2); v[1] = InitFont2DVertex(sx, sy, dwColor, tx1, ty1); v[2] = InitFont2DVertex(sx + w, sy + h, dwColor, tx2, ty2); v[3] = InitFont2DVertex(sx + w, sy, dwColor, tx2, ty1); v[4] = v[2]; v[5] = v[1]; memcpy(pVertices, v, 6 * sizeof(FONT2DVERTEX)); pVertices += 6; dwNumTriangles += 2; if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6)) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); m_pVB->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD); dwNumTriangles = 0; } sx += w + spacing*fXScale*vpWidth; } // Unlock and render the vertex buffer m_pVB->Unlock(); if (dwNumTriangles > 0) dev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, dwNumTriangles); RestoreRenderStates(); return S_OK; }
//----------------------------------------------------------------------------- // Name: DrawTextScaled() // Desc: Draws scaled 2D text. Note that x and y are in viewport coordinates // (ranging from -1 to +1). fXScale and fYScale are the size fraction // relative to the entire viewport. For example, a fXScale of 0.25 is // 1/8th of the screen width. This allows you to output text at a fixed // fraction of the viewport, even if the screen or window size changes. //----------------------------------------------------------------------------- HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, FLOAT fXScale, FLOAT fYScale, DWORD dwColor, TCHAR* strText, DWORD dwFlags ) { if( m_pd3dDevice == NULL ) return E_FAIL; // Set up renderstate m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock ); m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock ); m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX ); m_pd3dDevice->SetPixelShader( NULL ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) ); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); } D3DVIEWPORT8 vp; m_pd3dDevice->GetViewport( &vp ); FLOAT sx = (x+1.0f)*vp.Width/2; FLOAT sy = (y+1.0f)*vp.Height/2; FLOAT sz = z; FLOAT rhw = 1.0f; FLOAT fStartX = sx; FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight; // Fill vertex buffer FONT2DVERTEX* pVertices; DWORD dwNumTriangles = 0L; m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); while( *strText ) { TCHAR c = *strText++; if( c == _T('\n') ) { sx = fStartX; sy += fYScale*vp.Height; } if( c < _T(' ') ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1)*m_dwTexWidth; FLOAT h = (ty2-ty1)*m_dwTexHeight; w *= (fXScale*vp.Width)/fLineHeight; h *= (fYScale*vp.Height)/fLineHeight; if( c != _T(' ') ) { *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); dwNumTriangles += 2; if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; } } sx += w; } // Unlock and render the vertex buffer m_pVB->Unlock(); if( dwNumTriangles > 0 ) m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); // Restore the modified renderstates m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock ); return S_OK; }