我正在尝试使用字符构造四边形,这个字符在字形纹理内(使用D3DXFont :: GetGlyphData获得)。
大部分字符都是正确绘制的。
然而,诸如“F”和“A”之类的字符被颠倒了。
保存到文件时,没有任何字形似乎是颠倒的。
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
ID3DXSprite* pSprite;
ID3DXFont* pFont;
void drawCharacter(const char c, int screenX, int screenY, D3DCOLOR color)
{
struct CUSTOMVERTEX
{
float x, y, z, rhw, tu, tv;
};
WORD glyphIndex;
IDirect3DTexture9* texture;
RECT rect;
POINT point;
D3DSURFACE_DESC desc;
if(GetGlyphIndices(pFont->GetDC(), &c, 1, &glyphIndex, GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR)
return;
if(pFont->GetGlyphData(glyphIndex, &texture, &rect, &point) != S_OK)
return;
if(texture->GetLevelDesc(0, &desc) != D3D_OK)
return;
const float glyphWidth = static_cast<float>(desc.Width);
const float glyphHeight = static_cast<float>(desc.Height);
const float charWidth = static_cast<float>(rect.right - rect.left);
const float charHeight = static_cast<float>(rect.bottom - rect.top);
const float startX = static_cast<float>(screenY);
const float startY = static_cast<float>(screenY);
float u = (static_cast<float>(rect.left) + 0.5f) / glyphWidth;
float v = (static_cast<float>(rect.top) + 0.5f) / glyphHeight;
float u2 = u + (charWidth / glyphWidth);
float v2 = v + (charHeight / glyphHeight);
const CUSTOMVERTEX char_quad[4] =
{
// Bottom left vertex
{
startX, startY, 0.0f, 1.0f,
u, v2
},
// Bottom right vertex
{
startX + charWidth, startY, 0.0f, 1.0f,
u2, v2
},
// Top right vertex
{
startX + charWidth, startY + charHeight, 0.0f, 1.0f,
u2, v
},
// Top left vertex
{
startX, startY + charHeight, 0.0f, 1.0f,
u, v
}
};
// D3DXSaveTextureToFileA("glyph.dds", D3DXIFF_DDS, texture, 0);
d3ddev->SetTexture(0, texture);
d3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, char_quad, sizeof(CUSTOMVERTEX));
}
// this is the function used to render a single frame
void render_frame()
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
pSprite->Begin(D3DXSPRITE_ALPHABLEND);
// select which vertex format we are using
d3ddev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
drawCharacter('F', 100, 100, D3DCOLOR_XRGB(0, 255, 0));
pSprite->End();
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "WindowClass";
if(!RegisterClassEx(&wc))
{
return 0;
}
hWnd = CreateWindowEx(NULL,
"WindowClass",
"Our Direct3D Program",
WS_OVERLAPPEDWINDOW,
0, 0,
800, 600,
NULL,
NULL,
hInstance,
NULL);
if(!hWnd)
{
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
ShowWindow(hWnd, nCmdShow);
// set up and initialize Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(!d3d)
{
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;
// create a device class using this information and the info from the d3dpp stuct
if(d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev) != D3D_OK)
{
d3d->Release();
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
if(D3DXCreateSprite(d3ddev, &pSprite) != D3D_OK)
{
d3d->Release();
d3ddev->Release();
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
if(D3D_OK != D3DXCreateFont(d3ddev,
14,
0,
FW_BOLD,
1,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
"Georgia",
&pFont))
{
d3d->Release();
d3ddev->Release();
pSprite->Release();
UnregisterClass(wc.lpszClassName, hInstance);
return 0;
}
MSG msg;
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
render_frame();
}
d3d->Release();
d3ddev->Release();
pSprite->Release();
pFont->Release();
UnregisterClass(wc.lpszClassName, hInstance);
return msg.wParam;
}
修改:已更新,以包含我的问题的完整示例。
答案 0 :(得分:0)
我做了任何DirextX的事情已经有一段时间了,但我认为这可能与四维纹理坐标排序有关。我运行了你的代码并尝试了这个:
const CUSTOMVERTEX char_quad[4] =
{
// Top left vertex
{
startX, startY + charHeight, 0.0f, 1.0f,
u, v2
},
// Top right vertex
{
startX + charWidth, startY + charHeight, 0.0f, 1.0f,
u2, v2
},
// Bottom right vertex
{
startX + charWidth, startY, 0.0f, 1.0f,
u2, v
},
// Bottom left vertex
{
startX, startY, 0.0f, 1.0f,
u, v
}
};
输出字符ABCDEF的都好。 我不能完全记住如何指定自定义顶点,所以我猜我可能幸运的是上面的黑客:)
再看看这个,我认为应该命令坐标以顺时针绕组顺序渲染三角形(因此它不会被剔除)。重新排序坐标更有意义我想:
// TRIANGLEFAN coords:
// v1-----v2 clockwise winding order
// | / |
// | / |
// v0-----v3
//
const CUSTOMVERTEX char_quad[4] =
{
// Bottom left vertex
{
startX, startY, 0.0f, 1.0f,
u, v
},
// Top left vertex
{
startX, startY + charHeight, 0.0f, 1.0f,
u, v2
},
// Top right vertex
{
startX + charWidth, startY + charHeight, 0.0f, 1.0f,
u2, v2
},
// Bottom right vertex
{
startX + charWidth, startY, 0.0f, 1.0f,
u2, v
},
};