겁나 느리다.. 초당 380fps정도밖에 출력 되지 않는 것 같다.. 물론 Text 개수와도 충분히 연관이 있다.
그래서 구글링 네이버년한테 검색을 좀 해봤는데
참고2 : http://www.gpgstudy.com/forum/viewtopic.php?t=1202
이런 내용들이..
더 빠른 혹은 더 많은 기능을 가진 것을 원한다면 자체글꼴렌더러를 만들어도 됩니다만....
ID3DXFont자체는 그렇게 느리지 않습니다.... 우선....이걸 쓸때 보통 주의할만한 사항은
첫번째인자를 NULL값으로 비우지 않는 겁니다....
별도 생성한 D3DXSprite로 Begin~End를 둘러친 다음, 이 안에 필요한만큼 글자들을 모아찍도록 권장되고 있습니다..
아직 그렇게 안하셨다면 꼭 하시길 바랍니다.......
이미 말씀대로 구현된 상태이지만 문자열이 많아질 수록 fps는 급격히 떨어집니다.. 문자열이 별로 없으면 fps는 봐줄만했습니다만, 사이즈가 큰 문자열들이나 좀 채팅 수준의 문자열을 표시하면 fps가 15 정도까지도 떨어집니다....
현재의 ID3DXFont가 그렇게 느리지 않은 이유는 ....
--
1. 글리프(폰트글자 )테이블텍스쳐를 캐시처럼 동적으로 운용하고 있고.....
(DrawText시엔, 항상 글자단위로 가져와서 글자 하나를 폴리건쿼드 하나에 입힙니다.....미리 그려진 글자가 있다면,
해당텍스쳐 UV를 참조하고, 더이상 win GDI처리를 하지 않습니다..)
2. D3DXSprite과 병행해서, 되도록 많은글자들을 모아서 더 적게 DrawCall처리 합니다... (흔히 말하는 배치처리입니다..)
--
속도개선/기능추가를 위해 따로 만드는 분들의 자체글꼴렌더러도 위의 2가지정도는 비슷하게 구현한다고 볼수 있습니다...
그래도, 느리다는 얘기가 있는 것을 보면, 제가 모르는 다른 문제일수도 있겠네요......
위의 분 말씀대로 d3dxfont를 사용하시면 매우 느려집니다. 사용이 불가능할정도죠.
우선 7.0에서 쓰던 방식처럼 매 프레임 getdc하고 뿌리고, 그러는 방법은 아마 불가능하지 않을까라고 생각합니다.
제가 쓰는방식은 메모리DC를 하나 생성하신후 거기에 텍스트를 찍으시고, 그걸 텍스쳐로 카피해와서 텍스쳐를 저장해놓으시고, 텍스트가 바뀌었을경우에만 텍스쳐를 업데이트해주시면 속도저하가 거의 없이 사용하실수있습니다.
프로그래밍상의 방법이 바뀌어야해서 이제까지 만드신 소스를 사용하실수 없겠지만요..
제발 9.0에서는 다른 방법이 나왔으면...
완성형 방식의 한글 출력은 외곽선으로 그리든 아니면 DC->텍스처로 올리든 현재의 그래픽 카드들에서는 본질적으로 한계를 가지고 있습니다.
그래픽 카드의 메모리가 지금의 몇 배가 된다면 모든 한글 글자들을 텍스처로 담아둘 수 있으므로 해결될 것입니다만 메모리가 그렇게 늘어난다면 아마 텍스트 보다는 다른 용도로 사용하게 될 가능성이 크구요....
또 그래픽 카드 구조가 3D와 2D 접근을 동시에 허용하도록 변한다면 텍스처 업로드 과정이 필요가 없으니 해결되겠지만 그런 변화가 생길 지는 알수 없구요..
어쨌든 현재로서는 임의의(특히 실행 시점에서 결정되는-채팅 등) 한글 텍스트를 속도와 메모리 모두 만족시키는 방식으로 출력하는 유일한 방법은 Glan 같은 자모 조합식 방법밖에 없다고 강력히 주장합니다. 자모조합식으로 전환해 보심이...
완성형을 고집한다면, 외곽선 정보에 대해 메시 줄이기를 적용해서 메시 데이터를 최소화하는 것, 자주 쓰이는 글자들에 대해 캐싱-풀링-해싱 등을 적용하는 것 등 몇 가지 최적화가 가능하겠지만 근본적인 해답이 되지는 않을 것입니다.....
자모조합식 외곽선 출력이 가능하다면 좋겠는데 그런 거 시도하는 회사 있는지 모르겠네요
KGDA 프로그래밍 자료실에, DX 9.0에서 DC에 직접 출력하는 예제 소스가 올라왔습니다.
DC에 직접 접근한다는 거... 환영할만한 변화 중 하나인 것 같습니다.
CPU-GPU 병렬성에 영향을 미칠 수도 있겠지만 어쨌든 텍스처를 계속 갱신하는 것보다는 훨씬 낫겠죠...
DC 얻어다 찍어보니.. 일단 빠르고, 편합니다. 에, 심심해서 d3dfont 로 한가득 찍어보고, dc 로도 해봤는데 dc의 완승이였슴다.
DX8 에서 GetDC 가 없어져서 좀 황당했는데, 선그릴때 라든가, GDI 함수중에도 쓸만한게 많았는데 이제야 제대로 됐다고나 할까요.
근데 백버퍼에 찍어봤는데, 제 경우 좀 문제가 생겼어요. 분명히 프리미티브 다 찍고 나중에 텍스트 찍었는데, 꼭 Z테스트 한것마냥 텍스트는 뒤에 있다는.. -.-
Present후에 GetDC를 해야한다는건...
DC위에 바로 문자열을 찍지 말라는거네요....
문자열위에 다른 3D/2D객체가 놓이게되면 방법이 없으니....
폭이 256pixel정도되는 문자열 한가운데 64pixel정도되는 대화상자가 떡허니 뜨면...
짤리는 문자열/문자 처리도 장난아닐테고...
게다가 그넘이 경계는 불투명이고 안쪽은 반투명이 먹는다던가 하면...
거의 불가능이.....
텍스쳐로 만들어 쓰는게 좋을듯...
Present후에 GetDC를 해야하는게 아니면 이런 문젠 없겠죠....
난 일단 아래처럼 구현 해놨는데 첫번째 인자에 sprite 머시기를 넣어 줘야 더 잘나오나보다..
BOOL Direct3D9Renderer::RenderText(const std::string &strText, RECT &rcDest, TextFlags nFlags, COLORREF nColor)
{
register LPD3DXFONT lpFont = m_lpFont;
if (!lpFont)
return FALSE;
register HRESULT hr;
hr = m_lpDevice->BeginScene();
if (SUCCEEDED(hr))
{
register UINT nFormat = 0;
if (IS_SET_BIT(nFlags, TextFlagHorzLeft)) nFormat |= DT_LEFT;
if (IS_SET_BIT(nFlags, TextFlagHorzCenter)) nFormat |= DT_CENTER;
if (IS_SET_BIT(nFlags, TextFlagHorzRight)) nFormat |= DT_RIGHT;
if (IS_SET_BIT(nFlags, TextFlagVertTop)) nFormat |= DT_TOP;
if (IS_SET_BIT(nFlags, TextFlagVertCenter)) nFormat |= DT_VCENTER;
if (IS_SET_BIT(nFlags, TextFlagVertBottom)) nFormat |= DT_BOTTOM;
if (IS_SET_BIT(nFlags, TextFlagSingleline)) nFormat |= DT_SINGLELINE;
if (IS_SET_BIT(nFlags, TextFlagWordBreak)) nFormat |= DT_WORDBREAK;
if (IS_SET_BIT(nFlags, TextFlagCalcRect)) nFormat |= DT_CALCRECT;
if (IS_SET_BIT(nFlags, TextFlagNoClip)) nFormat |= DT_NOCLIP;
register int r, g, b;
GetSeperatedColor(nColor, r, g, b);
EnableAlpha();
hr = lpFont->DrawText(NULL, strText.c_str(), (int)strText.length(), &rcDest, nFormat, D3DCOLOR_XRGB(r,g,b));
m_lpDevice->EndScene();
}
//Present(rcDest);
return TRUE;
}
'MS > DirectX' 카테고리의 다른 글
D3DFont 성능 (0) | 2012.07.10 |
---|---|
DX Sprite 사용법 (0) | 2012.06.26 |
DirectDraw - SetClipper (2) (0) | 2012.06.01 |
DirectDraw - SetClipper (1) (0) | 2012.06.01 |