Помогите оптимизировать графику
От: MadCoder_61  
Дата: 02.10.04 21:46
Оценка:
Здравствуйте!

Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом
(только GDI).
При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
пределы секунды.
Подскажите, пожалуйста:
Как можно для изображений 640х480 довести количество кадров хотя бы до 30?
Заранее благодарю.
Re: Помогите оптимизировать графику
От: Evgeniy13 Россия  
Дата: 03.10.04 08:32
Оценка: 2 (1) +1
Здравствуйте, MadCoder_61, Вы писали:

Ну, можно создать текстуру (битмап), этакий Back Buffer (который Вы, я так понимаю, создали), на которую рисовать, а затем BitBlt. Еще хорошо бы использовать не SetPixel, а непосредственный доступ к битам изображения. А вообще надо использовать DirectDraw.

MC_>Здравствуйте!


MC_>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_> (только GDI).
MC_>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>пределы секунды.
MC_>Подскажите, пожалуйста:
MC_> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?
MC_>Заранее благодарю.
Не все в этом мире можно выразить с помощью нулей и единиц...
Re: Помогите оптимизировать графику
От: korzhik Россия  
Дата: 03.10.04 08:49
Оценка: 3 (1)
Здравствуйте, MadCoder_61, Вы писали:

MC_>Здравствуйте!


MC_>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_> (только GDI).
MC_>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>пределы секунды.
MC_>Подскажите, пожалуйста:
MC_> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?

Ну если задачу надо выполнить только средствами GDI, то я бы попробовал использовать DIB секцию как back buffer.
Используя DIB секцию мы можем получить непосредственный доступ к битам изображения.
Ну а после заполнения секции делать BitBlt.
Re: Помогите оптимизировать графику
От: GUID Россия  
Дата: 03.10.04 09:07
Оценка:
Здравствуйте, MadCoder_61, Вы писали:

MC_>Здравствуйте!


MC_>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_> (только GDI).
MC_>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>пределы секунды.
MC_>Подскажите, пожалуйста:
MC_> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?

Я полагаю, что проблема низврой производительности вовсе не в функции SetPixel (все таки сейчас видеокарты очень быстрые), я думаю проблема в алгоритме вывода на экран. Вы не могли бы привести высокоуровневое написание, иллюстрирующее как выглядит программа. Например, впишите сюда недостаяющие операторы: где Вы контекст получаете, где выводите точку на экран:


for (int i = 0; i< 100; i++)
{
    for (int j = 0; j< 100; j++)
    {
    }
}
Re[2]: Помогите оптимизировать графику
От: MadCoder_61  
Дата: 03.10.04 12:05
Оценка:
GUI>Я полагаю, что проблема низврой производительности вовсе не в функции SetPixel (все таки сейчас видеокарты очень быстрые), я думаю проблема в алгоритме вывода на экран. Вы не могли бы привести высокоуровневое написание, иллюстрирующее как выглядит программа. Например, впишите сюда недостаяющие операторы: где Вы контекст получаете, где выводите точку на экран:


Class Буфер Отображения
{
Инициализация ( Указатель на окно )
{
создается буфер размером с окно;
//В дальнейшем все рисование будет идти в нем
}

Рисование точки ( x, y, color )
{
// Самое часто!!! Если отключить данную функцию, то fps почти не
// падают — 10 – 15 fps на сложную сцену.
m_pDC->SetPixel(x, y, color);
}

Изменение размера окна ( новый размер )
{
пересоздаем буфер;
// происходит очень редко
}

Отчистка буфера()
{
закрашиваем буфер;
m_pDC->FillSolidRect(..) // на скорость не сильно влияет
}


Начать рисование ()
{
отчистка буфера
}

Закончить рисование
{
копирование буфера в окно;
}
};


Class Визуализатор
{

Создание проекции (Буфер Отображения )
{
Буфер Отображения->Начало рисования();
цикл по всем объектам сцены
цикл по всем полигонам объекта
Проецирование полигона ( текущий полигон, буфер ображения )
Буфер Отображения->Конец рисования();
}

Проецирование полигона
{
// используется метод заполнения треугольника
// горизонтальными линиями
// y1 – самая верхняя, y3 – самая нижняя
Определяем разницу по высоте (y3 – y1);
Пока не достигли у3
{
Определяем разницу по ширине;
Пока не достигли x2
{
Считаем освещенность ( dx , dy );
Буфер Отображения-> Рисование точки ( dx, dy, color )
// То есть m_pDC->SetPixel(x, y, color);
}

}
}
};
Re[3]: Помогите оптимизировать графику
От: GUID Россия  
Дата: 03.10.04 13:08
Оценка: 3 (1)
Здравствуйте, MadCoder_61, Вы писали:

1) А где ты получаешь контекст окна? Что такое в Инициализации создается буфер, в котором все будет рисоваться, хотя ты выхываешь функцию SetPixel. Где вызывается BeginPaint / EndPaint?
2) Для оптимизации SetPixel имеет смысл применить дедовский метод: использовать CreateBitmapIndirect и работать с буфером как с обычным массивом (т.е. вместо SetPixel использовать bmBits[y<<8+x]=color; — для картинки шириной в 256 точек — ширину картинки лучше кратной степени двойки — тогда можно использовать операцию сдвига вместо умножения на ширину). Потом вызвать один раз BitBlt — и вывести весь буфер на экран сразу. Единственно, что нужно самому проверять выход за границы массива.
3) Насчет DirectX тут высказались совершенно верно — DX работает быстрее
Re[4]: Помогите оптимизировать графику
От: MadCoder_61  
Дата: 03.10.04 13:23
Оценка:
Здравствуйте, GUID, Вы писали:

GUI>1) А где ты получаешь контекст окна? Что такое в Инициализации создается буфер, в котором все будет рисоваться, хотя ты выхываешь функцию SetPixel. Где вызывается BeginPaint / EndPaint?


В начале рендера и в конце рендера всей сцены соответственно

GUI>2) Для оптимизации SetPixel имеет смысл применить дедовский метод: использовать CreateBitmapIndirect и работать с буфером как с обычным массивом (т.е. вместо SetPixel использовать bmBits[y<<8+x]=color; — для картинки шириной в 256 точек — ширину картинки лучше кратной степени двойки — тогда можно использовать операцию сдвига вместо умножения на ширину). Потом вызвать один раз BitBlt — и вывести весь буфер на экран сразу. Единственно, что нужно самому проверять выход за границы массива.


Огромное спасибо, наврено это и есть самый оптимальный метод.

GUI>3) Насчет DirectX тут высказались совершенно верно — DX работает быстрее


Проблема в том, что вообще там где это будет использоваться еще нет DirectX или OpenGL
Re[4]: Помогите оптимизировать графику
От: Evgeniy13 Россия  
Дата: 03.10.04 20:00
Оценка:
Здравствуйте, GUID, Вы писали:

> bmBits[y<<8+x]=color; — для картинки шириной в 256 точек — ширину картинки лучше кратной степени двойки — тогда можно

> использовать операцию сдвига вместо умножения на ширину).

Ну уж, если так оgтимизировать, то можно не париться с 256 точками, а писать так:
for (int y; y<height; ++y)
  for (int xy=y*width, x=0, max = (y+1)*width; xy<max; ++xy, ++x)
    bmBits[xy]=color(x,y);
Не все в этом мире можно выразить с помощью нулей и единиц...
Re[4]: Помогите оптимизировать графику
От: retalik www.airbandits.com/
Дата: 04.10.04 10:09
Оценка: +1
Здравствуйте, GUID, Вы писали:

GUI>2) Для оптимизации SetPixel имеет смысл применить дедовский метод: использовать CreateBitmapIndirect и работать с буфером как с обычным массивом (т.е. вместо SetPixel использовать bmBits[y<<8+x]=color;


Ошибка, кстати, тоже дедовская: y<<8+x означает y<<(8+x), что, очевидно, совсем не то, что нужно...
Успехов,
Виталий.
Re[5]: Помогите оптимизировать графику
От: GUID Россия  
Дата: 04.10.04 21:27
Оценка:
Здравствуйте, Evgeniy13, Вы писали:

E>Здравствуйте, GUID, Вы писали:


>> bmBits[y<<8+x]=color; — для картинки шириной в 256 точек — ширину картинки лучше кратной степени двойки — тогда можно

>> использовать операцию сдвига вместо умножения на ширину).

E>Ну уж, если так оgтимизировать, то можно не париться с 256 точками, а писать так:

E>
E>for (int y; y<height; ++y)
E>  for (int xy=y*width, x=0, max = (y+1)*width; xy<max; ++xy, ++x)
E>    bmBits[xy]=color(x,y);
E>


"Не париться" и "оптимизировать" — взаимоисключающие друг друга понятия. Если хотитите что-то соптимизировать — придется париться и идти на ограничения.

Кстати ваш алгоритм я бы изложил с следующей редакции:

Addr = 0;
for (int y = 0; y < height; y++)
{
  for (int x = 0; x < width; x++)
  {
    bmBits[Addr] = color(x,y);
    Addr++;
  }
}
Re: Помогите оптимизировать графику
От: gandalf_g Россия  
Дата: 05.10.04 04:10
Оценка:
Здравствуйте, MadCoder_61, Вы писали:

MC_>Здравствуйте!


MC_>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_> (только GDI).
MC_>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>пределы секунды.
MC_>Подскажите, пожалуйста:
MC_> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?
MC_>Заранее благодарю.

можно попробовать рисовать в HBITMAP юзая SetDIBits(), т.е. заполняешь попиксельно картинку(массив) в памяти, записываешь ее в HBITMAP и выводишь на экран. лучше сходу ничего не придумал, по идее должно быть быстрее.
Have fun...
Re: Помогите оптимизировать графику
От: Mr.ToNik Россия http://sinstr.ru
Дата: 05.10.04 11:59
Оценка:
Здравствуйте, MadCoder_61, Вы писали:

MC_>Здравствуйте!


MC_>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_> (только GDI).
MC_>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>пределы секунды.
MC_>Подскажите, пожалуйста:
MC_> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?
MC_>Заранее благодарю.

It's easy!
Например так:
(Конечно, можно быстрее, но так нагляднее)


void CMyFrame::OnPaint() 
{
  CPaintDC dc(this);

 //Создаем буфер
  int CX = 400, CY = 100;

  DWORD *lpbInit = new DWORD[CX * CY];


 //Здесь рисуем прямо в память - так наиболее быстро  
 //BEGIN
 //Фигню рисуем
 for (int i = 0; i < CY; i++)
  {
    for (int j = 0; j < CX; j++)
    {
      BYTE color = (BYTE)(255-abs(i*255/(CY/2)-255));

      lpbInit[i*CX+j] = RGB(color, color, color);
    }
  }
 //END

 
 //Делаем из буфера BITMAP
  BITMAPINFO bmi = {
    sizeof(BITMAPINFOHEADER), CX, CY, 1, 32, BI_RGB, 0,
    0, 0, 0, 0 
  };

  HBITMAP hBitmap = ::CreateDIBitmap(
    dc.GetSafeHdc(), &bmi.bmiHeader, CBM_INIT,
    lpbInit, &bmi, DIB_RGB_COLORS);

  CBitmap bitmap;
  bitmap.Attach(hBitmap);  //Аттачим заготовку.

  //Отрисовываем буфер в контекст
  dc.DrawState(CPoint(10, 10), CSize(CX, CY), 
    &bitmap, DST_BITMAP);

  //Чистимся
  bitmap.DeleteObject();
  delete lpbInit;
}
Сделать человеку приятное очень просто. Не сделайте ему гадость и ему будет приятно!
Баг — это клоп. Таpакан — это, видимо, фича.
Re[2]: Помогите оптимизировать графику
От: Mr.ToNik Россия http://sinstr.ru
Дата: 05.10.04 14:31
Оценка:
Здравствуйте, GUID, Вы писали:

GUI>Здравствуйте, MadCoder_61, Вы писали:


MC_>>Здравствуйте!


MC_>>Необходимо выводить каждый пиксель, координаты которого хаотичны, собственным цветом

MC_>> (только GDI).
MC_>>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>>пределы секунды.
MC_>>Подскажите, пожалуйста:
MC_>> Как можно для изображений 640х480 довести количество кадров хотя бы до 30?

GUI>Я полагаю, что проблема низврой производительности вовсе не в функции SetPixel (все таки сейчас видеокарты очень быстрые), я думаю проблема в алгоритме вывода на экран. Вы не могли бы привести высокоуровневое написание, иллюстрирующее как выглядит программа. Например, впишите сюда недостаяющие операторы: где Вы контекст получаете, где выводите точку на экран:



GUI>
GUI>for (int i = 0; i< 100; i++)
GUI>{
GUI>    for (int j = 0; j< 100; j++)
GUI>    {
GUI>    }
GUI>}
GUI>


Конечно, это может быть и алгоритм тоже , но SetPixel это ОЧЕНЬ узкое место в коде.
MC_>>При рисовании методом CDC::SetPixel() (используя буфер) количество кадров для маленьких изображений (100х100 пикселей) падает до 15-30 в секунду, а для больших выходит за
MC_>>пределы секунды.
100х100 = 10^4 вызовов SetPixel() — накладные растоды на каждый вызов + проверки каждый вызов+ собственно работа с контекстом каждый вызов
Это долгооо...
Сделать человеку приятное очень просто. Не сделайте ему гадость и ему будет приятно!
Баг — это клоп. Таpакан — это, видимо, фича.
Re[3]: Помогите оптимизировать графику
От: retalik www.airbandits.com/
Дата: 05.10.04 14:43
Оценка:
Здравствуйте, Mr.ToNik, Вы писали:

MT>Конечно, это может быть и алгоритм тоже , но SetPixel это ОЧЕНЬ узкое место в коде.

Подтвержаю: читал, что для SetPixel создается... BITMAP единичного размера и выполняется BitBlt. Не самая дешевая операция, согласитесь.

Сам в kernel не лез, источник данных: Фень Юань, "Программирование графики".
Успехов,
Виталий.
Re[4]: Помогите оптимизировать графику
От: Mr.ToNik Россия http://sinstr.ru
Дата: 05.10.04 15:08
Оценка:
Здравствуйте, retalik, Вы писали:

R>Здравствуйте, Mr.ToNik, Вы писали:


MT>>Конечно, это может быть и алгоритм тоже , но SetPixel это ОЧЕНЬ узкое место в коде.

R>Подтвержаю: читал, что для SetPixel создается... BITMAP единичного размера и выполняется BitBlt. Не самая дешевая операция, согласитесь.

R>Сам в kernel не лез, источник данных: Фень Юань, "Программирование графики".


Очень концептуальное решение. Главное, идеология соблюдена!
Сделать человеку приятное очень просто. Не сделайте ему гадость и ему будет приятно!
Баг — это клоп. Таpакан — это, видимо, фича.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.