PMG https://forum.pmg.org.ru/ |
|
Вывод текста замедляет работу программы https://forum.pmg.org.ru/viewtopic.php?f=2&t=9448 |
Страница 1 из 1 |
Автор: | MrPalich [ 08 мар 2013 18:37 ] |
Заголовок сообщения: | Вывод текста замедляет работу программы |
Добрый день! Написал тут простенькую программу на ДиректИкс и при запуске ее работа постепенно замедляется. Начало это происходить после добавления текста. Листинг (функция вывода текста в конце) Код: #include <Windows.h> #include <d3d9.h> #include <d3dx9.h> #include <MMSystem.h> #include <d3dx9core.h> LPDIRECT3D9 pDirect3D = NULL; LPDIRECT3DDEVICE9 pDirect3DDevice = NULL; LPDIRECT3DVERTEXBUFFER9 pBufferVershin = NULL; LPDIRECT3DINDEXBUFFER9 pBufferIndex = NULL; LPD3DXFONT pFont = NULL; RECT Rec; HFONT hFont; HRESULT InitialDirect3D(HWND); LRESULT CALLBACK MainWinProc(HWND, UINT, WPARAM, LPARAM); VOID RenderingDirect3D(); VOID DeleteDirect3D(); HRESULT InitialObject(); VOID Matrix(); VOID LightMaterial(); VOID DrawMyText(LPCTSTR, int, int, int ,int , D3DCOLOR); struct CUSTOMVERTEX { FLOAT X, Y, Z; FLOAT nx, ny, nz; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL) int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstanse, LPSTR LpCmdLine, int nCmdShow) { MSG msg; HWND hwnd; WNDCLASSEXW windowsclass; windowsclass.cbSize = sizeof(WNDCLASSEXW); windowsclass.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC|CS_DBLCLKS; windowsclass.lpfnWndProc = MainWinProc; windowsclass.cbClsExtra = 0; windowsclass.cbWndExtra = 0; windowsclass.hInstance = hinstance; windowsclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); windowsclass.hCursor = LoadCursor(NULL,IDC_ARROW); windowsclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); windowsclass.lpszMenuName = NULL; windowsclass.lpszClassName = L"WINDOWSCLASS"; windowsclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION); if(!RegisterClassEx(& windowsclass)) return 0; if(!(hwnd = CreateWindowEx(NULL, L"WINDOWSCLASS", L"DirectX", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 300, 150, 500, 400, NULL, NULL, hinstance, NULL))) return(0); if(SUCCEEDED(InitialDirect3D(hwnd))) { if(SUCCEEDED(InitialObject())) { ShowWindow(hwnd, SW_SHOWDEFAULT); UpdateWindow(hwnd); ZeroMemory(&msg, sizeof(msg)); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else RenderingDirect3D(); } } } return(msg.wParam); } LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_DESTROY: { DeleteDirect3D(); PostQuitMessage(0); return 0; } case WM_KEYDOWN: { if (wparam == VK_ESCAPE) PostQuitMessage(0); return 0; } } return (DefWindowProc(hwnd, msg, wparam, lparam)); } HRESULT InitialDirect3D(HWND hwnd) { if(NULL == (pDirect3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; D3DDISPLAYMODE Display; if(FAILED(pDirect3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Display))) return E_FAIL; D3DPRESENT_PARAMETERS Direct3DParametr; ZeroMemory(&Direct3DParametr, sizeof(Direct3DParametr)); Direct3DParametr.Windowed = FALSE; Direct3DParametr.SwapEffect = D3DSWAPEFFECT_DISCARD; Direct3DParametr.BackBufferFormat = Display.Format; Direct3DParametr.EnableAutoDepthStencil = TRUE; Direct3DParametr.AutoDepthStencilFormat = D3DFMT_D16; Direct3DParametr.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN); Direct3DParametr.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN); Direct3DParametr.BackBufferCount = 3; Direct3DParametr.FullScreen_RefreshRateInHz = Display.RefreshRate; if(FAILED(pDirect3D ->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&Direct3DParametr,&pDirect3DDevice))) return E_FAIL; pDirect3DDevice -> SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); pDirect3DDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE); return S_OK; } VOID RenderingDirect3D() { if(pDirect3DDevice == NULL) return; pDirect3DDevice -> Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(60, 100, 150), 1.0f, 0); pDirect3DDevice -> BeginScene(); Matrix(); LightMaterial(); pDirect3DDevice -> SetStreamSource(0, pBufferVershin, 0, sizeof(CUSTOMVERTEX)); pDirect3DDevice -> SetFVF(D3DFVF_CUSTOMVERTEX); pDirect3DDevice -> SetIndices(pBufferIndex); pDirect3DDevice -> DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0 , 12); DrawMyText(L"MyText", 10, 10, 800, 800, D3DCOLOR_ARGB(250,250,250,0)); pDirect3DDevice -> EndScene(); pDirect3DDevice -> Present(NULL,NULL,NULL,NULL); } VOID DeleteDirect3D() { if(pDirect3DDevice != NULL) pDirect3DDevice -> Release(); if(pDirect3D != NULL) pDirect3D -> Release(); if(pBufferVershin != NULL) pBufferVershin -> Release(); if(pBufferIndex != NULL) pBufferIndex->Release(); if (pFont != NULL) pFont -> Release(); } HRESULT InitialObject() { CUSTOMVERTEX Vershin[] = { { 1.0f,-1.0f,-1.0f, 0.0f, 0.0f,-1.0f, }, //А { 1.0f, 1.0f,-1.0f, 0.0f, 0.0f,-1.0f, }, //В { -1.0f, 1.0f,-1.0f, 0.0f, 0.0f,-1.0f, }, //С { -1.0f,-1.0f,-1.0f, 0.0f, 0.0f,-1.0f, }, //D { -1.0f,-1.0f,-1.0f,-1.0f, 0.0f, 0.0f, }, //A2 { -1.0f, 1.0f,-1.0f,-1.0f, 0.0f, 0.0f, }, //B2 { -1.0f, 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, }, //C2 { -1.0f,-1.0f, 1.0f,-1.0f, 0.0f, 0.0f, }, //D2 { -1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, }, //A3 { -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, }, //B3 { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, }, //C3 { 1.0f,-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, }, //D3 { 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, }, //A4 { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, }, //B4 { 1.0f, 1.0f,-1.0f, 1.0f, 0.0f, 0.0f, }, //C4 { 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 0.0f, }, //D4 { 1.0f,-1.0f,-1.0f, 0.0f,-1.0f, 0.0f, }, //A5 { -1.0f,-1.0f,-1.0f, 0.0f,-1.0f, 0.0f, }, //B5 { -1.0f,-1.0f, 1.0f, 0.0f,-1.0f, 0.0f, }, //C5 { 1.0f,-1.0f, 1.0f, 0.0f,-1.0f, 0.0f, }, //D5 { 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, }, //A6 { -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, }, //B6 { -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, }, //C6 { 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, }, //D6 }; const unsigned short Index[]={ 0,1,2, 2,3,0, 4,5,6, 6,7,4, 8,9,10, 10,11,8, 12,13,14, 14,15,12, 16,17,18, 18,19,16, 20,21,22, 22,23,20, }; // Vertex if(FAILED(pDirect3DDevice -> CreateVertexBuffer(36*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &pBufferVershin, NULL))) return E_FAIL; VOID* pBV; if(FAILED(pBufferVershin -> Lock(0, sizeof(Vershin), (void**)&pBV, 0))) return E_FAIL; memcpy(pBV, Vershin, sizeof(Vershin)); pBufferVershin -> Unlock(); // Index pDirect3DDevice -> CreateIndexBuffer(36*sizeof(Index), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &pBufferIndex, NULL); VOID* pBI; pBufferIndex -> Lock(0, sizeof(Index), (void**)&pBI, 0); memcpy(pBI, Index, sizeof(Index)); pBufferIndex -> Unlock(); return S_OK; } VOID Matrix() { D3DXMATRIX MatrixWorld, MatrixWorldX, MatrixWorldY; D3DXMATRIX MatrixView; D3DXMATRIX MatrixProjection; // MatrixWorld UINT Time = timeGetTime() % 5000; FLOAT Angle = Time * (2.0f * D3DX_PI) / 5000.0f; D3DXMatrixRotationX(&MatrixWorldX, Angle); D3DXMatrixRotationY(&MatrixWorldY, Angle); D3DXMatrixMultiply( &MatrixWorld, &MatrixWorldX, &MatrixWorldY ); pDirect3DDevice -> SetTransform(D3DTS_WORLD, &MatrixWorld); // MatrixView D3DXMatrixLookAtLH(&MatrixView, &D3DXVECTOR3(0.0f, 0.0f, -8.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); pDirect3DDevice -> SetTransform(D3DTS_VIEW, &MatrixView); // MatrixProjection D3DXMatrixPerspectiveFovLH(&MatrixProjection, D3DX_PI/4, 1.0f, 1.0f, 100.0f); pDirect3DDevice -> SetTransform(D3DTS_PROJECTION, &MatrixProjection); } VOID LightMaterial() { D3DMATERIAL9 Material; D3DLIGHT9 Light; ZeroMemory(&Material, sizeof(D3DMATERIAL9)); Material.Diffuse.r = Material.Ambient.r = 1.0f; Material.Diffuse.g = Material.Ambient.g = 1.0f; Material.Diffuse.b = Material.Ambient.b = 0.0f; Material.Diffuse.a = Material.Ambient.a = 1.0f; pDirect3DDevice -> SetMaterial(&Material); D3DXVECTOR3 VectorDir; ZeroMemory(&Light, sizeof(D3DLIGHT9)); Light.Type = D3DLIGHT_DIRECTIONAL; Light.Diffuse.r = 1.0f; Light.Diffuse.g = 1.0f; Light.Diffuse.b = 1.0f; Light.Range = 100.0f; VectorDir = D3DXVECTOR3(0.0f, 0.0f, 1.0f); D3DXVec3Normalize( (D3DXVECTOR3*)&Light.Direction, &VectorDir ); pDirect3DDevice -> SetLight(0, &Light); pDirect3DDevice -> LightEnable(0, TRUE); pDirect3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); pDirect3DDevice->SetRenderState( D3DRS_AMBIENT, 0 ); } VOID DrawMyText(LPCTSTR StrokaTexta, int x, int y, int x1, int y1, D3DCOLOR MyColor) { hFont = CreateFont(30, 10, 0, 0, FW_NORMAL, FALSE, FALSE, 0, 1, 0, 0, 0, DEFAULT_PITCH|FF_MODERN, L"Arial"); Rec.left = x; Rec.top = y; Rec.right = x1; Rec.bottom = y1; D3DXCreateFont(pDirect3DDevice,18,0,400,0,0,RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS,ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_MODERN,L"Arial",&pFont); pFont->DrawText(NULL, StrokaTexta, -1, &Rec, DT_WORDBREAK, MyColor); } Что тут не так? |
Автор: | kurlyak [ 09 мар 2013 14:40 ] |
Заголовок сообщения: | Re: Вывод текста замедляет работу программы |
Во первых почему ты используешь D3DCREATE_SOFTWARE_VERTEXPROCESSING в функции CreateDevice()? У тебя чего, старое оборудование стоит в компе? Попробуй следующий код, может влючиться D3DCREATE_HARDWARE_VERTEXPROCESSING, это может значительно ускорить работу программы: Код: D3DCAPS9 caps; p_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); int vp = 0; if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; if( FAILED( p_d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, vp, &d3dpp, &p_d3d_Device ) ) ) { MessageBox(NULL,"Error Create Device!", "Information",MB_OK); return false; } Во вторых, в главном цикле обработки сообщений убери else и функция рендеринга будет вызываться чаще: Код: while(msg.message != WM_QUIT) { if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } //else RenderingDirect3D(); } И самое главное ты допустил ошибку в функции DrawMyText() - эта функция у тебя вызываеться в каждом кадре, теперь зайдем в тело функции: у тебя в каждом кадре создаеться новый объект pFont не разрушив его в предыдущем кадре. Надо так: Код: VOID DrawMyText(LPCTSTR StrokaTexta, int x, int y, int x1, int y1, D3DCOLOR MyColor) { ///////////////////////////// if(hFont) { DeleteObject(hFont); } ///////////////////////////// hFont = CreateFont(30, 10, 0, 0, FW_NORMAL, FALSE, FALSE, 0, 1, 0, 0, 0, DEFAULT_PITCH|FF_MODERN, L"Arial"); Rec.left = x; Rec.top = y; Rec.right = x1; Rec.bottom = y1; ///////////////////////////// if ( pFont ) { pFont->Release(); pFont = NULL; } ///////////////////////////// D3DXCreateFont(pDirect3DDevice,18,0,400,0,0,RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS,ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_MODERN,L"Arial",&pFont); pFont->DrawText(NULL, StrokaTexta, -1, &Rec, DT_WORDBREAK, MyColor); } Дальше у тебя сама функция неправильная DrawMyText() - создавать фонт в каждом кадре- это не целесообразно. Напиши функцию InitialFont() которая будет создавать фонт раз при инициализации программы и дальше пользоваться этим фонтом: Код: //глобальная переменная pFont LPD3DXFONT pFont = NULL; HRESULT InitialFont() { HRESULT hr = D3DXCreateFont(pDirect3DDevice,18,0,400,0,0,RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS,ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_MODERN,L"Arial",&pFont); return hr; } Дальше поставь вызов этой функции где- то там же в WinMain() где ты вызываешь: Код: if(SUCCEEDED(InitialDirect3D(hwnd))) { if(SUCCEEDED(InitialObject())) { if(SUCCEEDED(InitialFont())) { И вот твоя новая функция DrawMyText(): Код: VOID DrawMyText(LPCTSTR StrokaTexta, int x, int y, int x1, int y1, D3DCOLOR MyColor) { RECT Rec; Rec.left = x; Rec.top = y; Rec.right = x1; Rec.bottom = y1; pFont->DrawText(NULL, StrokaTexta, -1, &Rec, DT_WORDBREAK, MyColor); } И вобще убери вызов CreateFont() этот фонт тебе ничего не дает он нигде не используетсья. Лично я пользуюсь так: сначала в функции инициализации просто создаю фонт DirectX: Код: void Init() { ........ //инициализируем шрифт TCHAR m_strFont[LF_FACESIZE]; lstrcpy( m_strFont, _T("Arial") ); //создаем шрифт D3DXCreateFont (p_d3d_Device, 15, // Высота 0, // Ширина FW_BOLD, // Вес 0, // MipLevels FALSE, // Italic RUSSIAN_CHARSET, // CharSet OUT_DEFAULT_PRECIS, // OutputPrecision DEFAULT_QUALITY, // Quality DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily m_strFont, // pFaceName &pFont); .......... } Затем где-то в WinMain() вызываю Init(). Дальше в моей функции RenderScene() вызываю: Код: RECT rect; SetRect(&rect,0,0,300,20); pFont->DrawText(NULL, "My String", -1, &rect, DT_SINGLELINE|DT_NOCLIP, D3DCOLOR_XRGB(255, 255, 0)); Вобщим самое главное - создавать шрифт pFont один раз- при запуске и инициализации приложения. Попробуй должно все работать. |
Автор: | MrPalich [ 09 мар 2013 16:02 ] |
Заголовок сообщения: | Re: Вывод текста замедляет работу программы |
Спасибо, действительно помогло. Но у меня тут еще 2 проблемы появились. В некоторых строках у меня выводи ошибку: IntelliSense: аргумент типа "const char *" несовместим с параметром типа "LPCWSTR" В таких строках как например эта: MessageBox(NULL,"Error Create Device!", "Information",MB_OK); Я знаю что можно добавить L перед константной строкой, вот так вот: MessageBox(NULL,L"Error Create Device!", L"Information",MB_OK); Но я все листинги которые я смотрел в интернете пишутся без L. Я где-то краем глаза видел что нужно помоему отключить Юникод. Как? У меня Visual Studio 2010. Проблема выше скорее всего является и причиной второй проблемы. При попытке загрузить .Х файл (он вам наверное знаком "tiger.x", пример в DirectX SDK) сама модель загружается, а текстур на нее не налаживается. Я смотрел листинги в интернете и мой почти идентичный с ними(1 строка отличается из-за проблемы выше). Вот функции из моего листинга для загрузки Х файлов: Код: HRESULT InitialMesh() { if(FAILED(D3DXLoadMeshFromX(L"tiger.x", D3DXMESH_SYSTEMMEM, pDirect3DDevice, NULL, &pMeshBuffer, NULL, &dwNumber, &pMesh))) return E_FAIL; D3DXMATERIAL* D3DXMeshMaterials; D3DXMeshMaterials = (D3DXMATERIAL*)pMeshBuffer -> GetBufferPointer(); pMeshMaterial = new D3DMATERIAL9[dwNumber]; pMeshTextura = new LPDIRECT3DTEXTURE9[dwNumber]; for(DWORD i = 0; i < dwNumber; i++) { pMeshMaterial[i] = D3DXMeshMaterials[i].MatD3D; pMeshMaterial[i].Ambient = pMeshMaterial[i].Diffuse; if(FAILED(D3DXCreateTextureFromFile(pDirect3DDevice, (LPCTSTR)(D3DXMeshMaterials[i].pTextureFilename), &pMeshTextura[i]))) pMeshTextura[i] = NULL; } pMeshBuffer -> Release(); return S_OK; } VOID DrawMyMesh() { for(DWORD i = 0; i < dwNumber; i++) { pDirect3DDevice -> SetMaterial(&pMeshMaterial[i]); pDirect3DDevice -> SetTexture(0, pMeshTextura[i]); pMesh -> DrawSubset(i); } } Функция InitialMesh() вызывается в Main: Код: if(SUCCEEDED(InitialMesh())) { //показ окна и тд //основной цикл } Функция DrawMyMesh() вызывается в RenderingDirect3D(): Код: pDirect3DDevice -> BeginScene(); //Begin Matrix(); DrawMyMesh(); DrawMyText(L"Загрузка Х файла", 10, 10, 800, 800, D3DCOLOR_ARGB(250,250,250,0)); pDirect3DDevice -> EndScene(); //End Ну и сама строка которая мне кажется является причиной всего: Код: if(FAILED(D3DXCreateTextureFromFile(pDirect3DDevice, (LPCTSTR)(D3DXMeshMaterials[i].pTextureFilename), &pMeshTextura[i]))) В всех листингах в интернете она имеет такой вид: Код: if(FAILED(D3DXCreateTextureFromFile(pDirect3DDevice, D3DXMeshMaterials[i].pTextureFilename, &pMeshTextura[i]))) Но если я использую второй вариант то у меня ошибка: IntelliSense: аргумент типа "LPSTR" несовместим с параметром типа "LPCWSTR" |
Автор: | kurlyak [ 18 ноя 2013 21:04 ] |
Заголовок сообщения: | Re: Вывод текста замедляет работу программы |
Такие оишбки LPCTSTR выдаються когда проект в Unicode. По умолчанию Студия создает проект в Unicode. Я не помню как там в 2010 Студии, но тебе надо переключить проект Multy-Byte Character Set. У меня в 2005 Студии в закладке Class в рабочей области нажимаю прав. кропкой на имени проекта и нажимаю в меню -> Properties (Свойства проекта). Дальше когда попал в свойства ищещь в свойствах пункт General и в этом пунке должно быть у тебя "Use unicode character set" который ты должен переключить в "Use multy-byte character set" иначе тебе надо везде будет ставить макрос L перед строками или _T() для строковых переменных. Если хочешь оставить проект в Юникоде, то ты прав надо переделать немного создание текстур меша. Код: if( d3dxMaterials[i].pTextureFilename )
{ WCHAR strTexturePath[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, d3dxMaterials[i].pTextureFilename, -1, strTexturePath, MAX_PATH ); strTexturePath[MAX_PATH - 1] = L'\0'; D3DXCreateTextureFromFile( p_d3d_Device, strTexturePath, &g_pMeshTextures[i] ); } |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |