Оптимизация рисования GDI+?

Я использую C++ и GDI+. Я собираюсь создать приложение для векторного рисования и хочу использовать GDI+ для рисования.

Я создал простой тест, чтобы ознакомиться с ним:

case WM_PAINT:
        GetCursorPos(&mouse);
        GetClientRect(hWnd,&rct);

        hdc = BeginPaint(hWnd, &ps);
        MemDC = CreateCompatibleDC(hdc);
        bmp = CreateCompatibleBitmap(hdc, 600, 600);
        SelectObject(MemDC,bmp);
        g = new Graphics(MemDC);

        for(int i = 0; i < 1; ++i)
        {
            SolidBrush sb(Color(255,255,255));
            g->FillRectangle(&sb,rct.top,rct.left,rct.right,rct.bottom);
        }

        for(int i = 0; i < 250; ++i)
        {
            pts[0].X = 0;
            pts[0].Y = 0;

            pts[1].X = 10 + mouse.x * i;
            pts[1].Y = 0 + mouse.y * i;

            pts[2].X = 10 * i + mouse.x;
            pts[2].Y = 10 + mouse.y * i;

            pts[3].X = 0 + mouse.x;
            pts[3].Y = (rand() % 600) + mouse.y;

            Point p1, p2;
            p1.X = 0;
            p1.Y = 0;
            p2.X = 300;
            p2.Y = 300;

            g->FillPolygon(&b,pts,4);
        }


        BitBlt(hdc,0,0,900,900,MemDC,0,0,SRCCOPY);

        EndPaint(hWnd, &ps);

        DeleteObject(bmp);
        g->ReleaseHDC(MemDC);
        DeleteDC(MemDC);
        delete g;
        break;

Мне интересно, правильно ли я делаю это, или у меня есть области, убивающие процессор. Потому что сейчас для рендеринга этого требуется ~ 1 секунда, и я хочу, чтобы он очень быстро перерисовывался. Спасибо

В реальной ситуации было бы лучше просто определить часть экрана для перерисовки и перерисовывать только элементы в пределах этого?


person jmasterx    schedule 01.05.2010    source источник
comment
Я задал связанный вопрос некоторое время назад. Возможно, это может дать вам несколько советов: stackoverflow .com/questions/957573/   -  person Pedery    schedule 15.05.2010


Ответы (2)


Вместо того, чтобы создавать все ресурсы и сносить их все для каждого WM_PAINT, вы можете попробовать разгрузить это для настройки и очистки приложения. Другими словами, переместите все вещи, такие как CreateCompatibleDC, CreateCompatibleBitmap, в WM_CREATE и соответствующие удаления в WM_DESTROY. Вы можете сохранить ссылки на все контексты устройства, дескрипторы кистей и т.п. как атрибуты класса или статические переменные. Таким образом, когда наступит время WM_PAINT, вся настройка уже сделана, и вам нужно только обработать фактический рисунок.

person JustJeff    schedule 15.05.2010
comment
при повторном рассмотрении кажется, что вы рисуете много полигонов полуслучайной формы. win32 gdi на самом деле не является высокопроизводительной графической системой. это нормально с базовыми прямоугольными вещами, но когда вы начнете запрашивать у него произвольные полигоны, это точно будет медленнее. Будь это я, я бы рассмотрел DirectX или OpenGL для чего-то более сложного, чем настоящие базовые вещи. - person JustJeff; 15.05.2010

Самая медленная строка в вашем коде на данный момент, вероятно, BitBlt(hdc,0,0,900,900,MemDC,0,0,SRCCOPY);. Функции Blit обычно очень медленные и нагружают ЦП. Использование графического процессора было бы быстрее, но гораздо сложнее (если вообще возможно подключиться к GDI+). Попробуйте найти способ рисовать на поверхности, которую вы будете использовать в конечном итоге, не копируя попиксельно.

person ssube    schedule 01.05.2010
comment
Нет, кажется, g-›FillPolygon(&b,pts,4); (умножить на 250) Если я уменьшу количество итераций до 30, оно быстро улучшится, но мне понадобится более 30 фигур :-p - person jmasterx; 01.05.2010
comment
Используйте переменную для цикла, не всегда рисуйте 250 фигур, рисуйте столько, сколько вам нужно. Будет некоторое замедление по мере того, как вы рисуете больше, это естественно. Также старайтесь не рисовать одинаковые фигуры дважды (если вам не нужно беспокоиться о прозрачности). - person ssube; 01.05.2010
comment
Что мне делать, когда нужно перерисовать все окно (т.е. все...)? - person jmasterx; 01.05.2010