Expandable
2007-09-19, 18:32:09
Hallo allerseits,
ich habe ein kleines Problem mit dem Font-Rendering unter D3D9. Meine App zeichnet nichts außer der aktuellen Framerate. Dazu wird folgende Klasse verwendet, die im D3D-SDK Sample "Text3D" auch vollkommen korrekt ihren Dienst tut:
FontRendererD3D9::FontRendererD3D9(LPDIRECT3DDEVICE9 device) : m_device(device), m_font(0)
{
if (FAILED(D3DXCreateFont(m_device, FONTSIZE, 0, FW_NORMAL, 1, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, FONTNAME, &m_font)))
throw new RenderSystemD3D9Exception("D3DXCreateFont failed");
}
FontRendererD3D9::~FontRendererD3D9()
{
if (m_font != 0)
m_font->Release();
}
void FontRendererD3D9::DrawString(const char* str, int x, int y)
{
RECT fontRectangle;
SetRect(&fontRectangle, x, y, 0, 0);
m_device->BeginScene();
m_font->DrawText(0, str, -1, &fontRectangle, DT_NOCLIP, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f));
m_device->EndScene();
}
Ich hatte den Verdacht, dass es an irgendeinem State-Call liegen muss, allerdings zeigt mir PIX, dass außer BeginScene/EndScene und den DrawCalls nichts aufgerufen wird. Nun habe ich eine Stelle gefunden, die den Unterschied macht:
Rufe ich CreateDevice() mit D3DCREATE_SOFTWARE_VERTEXPROCESSING auf, ist die Schrift klar. Verwende ich dagegen D3DCREATE_HARDWARE_VERTEXPROCESSING, was ja eigentlich sinnvoller ist, ist die Schrift unscharf. Es funktioniert mit beidem, wenn ich den Viewport nicht ändere:
D3DVIEWPORT9 viewport;
viewport.X = 0;
viewport.Y = 0;
viewport.Height = m_winHeight;
viewport.Width = m_winWidth;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
m_device->SetViewport(&viewport);
Hier mal ein Bild zu Verdeutlichung:
http://img232.imageshack.us/img232/7046/fontrenderingth5.th.png (http://img232.imageshack.us/my.php?image=fontrenderingth5.png)
Mein Setup-Code sieht so aus:
void RenderSystemD3D9::Initialize(HINSTANCE hInstance)
{
RenderSystem::Initialize(hInstance);
m_d3dObject = Direct3DCreate9(D3D_SDK_VERSION);
if (m_d3dObject == 0)
throw RenderSystemD3D9Exception("Direct3DCreate9() failed");
m_d3dObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode);
m_d3dObject->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_caps);
if (m_caps.VertexShaderVersion < D3DVS_VERSION(2,0))
throw RenderSystemD3D9Exception("Vertex Shader 2.0 support required");
if (m_caps.PixelShaderVersion < D3DPS_VERSION(2,0))
throw RenderSystemD3D9Exception("Pixel Shader 2.0 support required");
SetupPresentParameters();
if (FAILED(m_d3dObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_presentParams, &m_device)))
throw RenderSystemD3D9Exception("CreateDevice() failed");
RenderSystem::Factory::Instance = new RenderSystemD3D9::FactoryD3D9(m_device);
m_isInitialized = true;
WindowSizeChange(m_winWidth, m_winHeight);
m_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
m_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
void RenderSystemD3D9::SetupPresentParameters()
{
ZeroMemory(&m_presentParams, sizeof(m_presentParams));
D3DFORMAT adapterFormat = m_isWindowed == true ? m_displayMode.Format : D3DFMT_X8R8G8B8;
if (FAILED(m_d3dObject->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat,
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8))){
throw RenderSystemD3D9Exception("24bit depth buffer, 8bit stencil buffer not supported (D3D)");
}
m_presentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
m_presentParams.Windowed = m_isWindowed;
m_presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_presentParams.BackBufferCount = 1;
m_presentParams.BackBufferFormat = adapterFormat;
m_presentParams.BackBufferWidth = m_isWindowed == true ? 0 : m_displayMode.Width;
m_presentParams.BackBufferHeight = m_isWindowed == true ? 0 : m_displayMode.Height;
m_presentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
m_presentParams.MultiSampleQuality = 0;
m_presentParams.hDeviceWindow = m_hWnd;
m_presentParams.EnableAutoDepthStencil = true;
m_presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
Also irgendwie macht die Änderung des ViewPorts im Hardware-Modus das Font-Rendering kaputt. Sieht zufällig irgendjemand, woran das liegen könnte? Ich werde hier nämlich langsam wahnsinnig.
Vielen Dank!
ich habe ein kleines Problem mit dem Font-Rendering unter D3D9. Meine App zeichnet nichts außer der aktuellen Framerate. Dazu wird folgende Klasse verwendet, die im D3D-SDK Sample "Text3D" auch vollkommen korrekt ihren Dienst tut:
FontRendererD3D9::FontRendererD3D9(LPDIRECT3DDEVICE9 device) : m_device(device), m_font(0)
{
if (FAILED(D3DXCreateFont(m_device, FONTSIZE, 0, FW_NORMAL, 1, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, FONTNAME, &m_font)))
throw new RenderSystemD3D9Exception("D3DXCreateFont failed");
}
FontRendererD3D9::~FontRendererD3D9()
{
if (m_font != 0)
m_font->Release();
}
void FontRendererD3D9::DrawString(const char* str, int x, int y)
{
RECT fontRectangle;
SetRect(&fontRectangle, x, y, 0, 0);
m_device->BeginScene();
m_font->DrawText(0, str, -1, &fontRectangle, DT_NOCLIP, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f));
m_device->EndScene();
}
Ich hatte den Verdacht, dass es an irgendeinem State-Call liegen muss, allerdings zeigt mir PIX, dass außer BeginScene/EndScene und den DrawCalls nichts aufgerufen wird. Nun habe ich eine Stelle gefunden, die den Unterschied macht:
Rufe ich CreateDevice() mit D3DCREATE_SOFTWARE_VERTEXPROCESSING auf, ist die Schrift klar. Verwende ich dagegen D3DCREATE_HARDWARE_VERTEXPROCESSING, was ja eigentlich sinnvoller ist, ist die Schrift unscharf. Es funktioniert mit beidem, wenn ich den Viewport nicht ändere:
D3DVIEWPORT9 viewport;
viewport.X = 0;
viewport.Y = 0;
viewport.Height = m_winHeight;
viewport.Width = m_winWidth;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
m_device->SetViewport(&viewport);
Hier mal ein Bild zu Verdeutlichung:
http://img232.imageshack.us/img232/7046/fontrenderingth5.th.png (http://img232.imageshack.us/my.php?image=fontrenderingth5.png)
Mein Setup-Code sieht so aus:
void RenderSystemD3D9::Initialize(HINSTANCE hInstance)
{
RenderSystem::Initialize(hInstance);
m_d3dObject = Direct3DCreate9(D3D_SDK_VERSION);
if (m_d3dObject == 0)
throw RenderSystemD3D9Exception("Direct3DCreate9() failed");
m_d3dObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode);
m_d3dObject->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_caps);
if (m_caps.VertexShaderVersion < D3DVS_VERSION(2,0))
throw RenderSystemD3D9Exception("Vertex Shader 2.0 support required");
if (m_caps.PixelShaderVersion < D3DPS_VERSION(2,0))
throw RenderSystemD3D9Exception("Pixel Shader 2.0 support required");
SetupPresentParameters();
if (FAILED(m_d3dObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_presentParams, &m_device)))
throw RenderSystemD3D9Exception("CreateDevice() failed");
RenderSystem::Factory::Instance = new RenderSystemD3D9::FactoryD3D9(m_device);
m_isInitialized = true;
WindowSizeChange(m_winWidth, m_winHeight);
m_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
m_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
void RenderSystemD3D9::SetupPresentParameters()
{
ZeroMemory(&m_presentParams, sizeof(m_presentParams));
D3DFORMAT adapterFormat = m_isWindowed == true ? m_displayMode.Format : D3DFMT_X8R8G8B8;
if (FAILED(m_d3dObject->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat,
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8))){
throw RenderSystemD3D9Exception("24bit depth buffer, 8bit stencil buffer not supported (D3D)");
}
m_presentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
m_presentParams.Windowed = m_isWindowed;
m_presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_presentParams.BackBufferCount = 1;
m_presentParams.BackBufferFormat = adapterFormat;
m_presentParams.BackBufferWidth = m_isWindowed == true ? 0 : m_displayMode.Width;
m_presentParams.BackBufferHeight = m_isWindowed == true ? 0 : m_displayMode.Height;
m_presentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
m_presentParams.MultiSampleQuality = 0;
m_presentParams.hDeviceWindow = m_hWnd;
m_presentParams.EnableAutoDepthStencil = true;
m_presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
Also irgendwie macht die Änderung des ViewPorts im Hardware-Modus das Font-Rendering kaputt. Sieht zufällig irgendjemand, woran das liegen könnte? Ich werde hier nämlich langsam wahnsinnig.
Vielen Dank!