|
Програмирование графики, вопрос |
|
|
|
 |
Ответов
(1 - 61)
|
Sep 1 2016, 16:02
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
быстрые методы это аппаратно через opengl. хотя даже и тупое копирование вроде как работает. на fltk несколько мс чтобы картинку скопировать и еще ~50мс чтобы отрисовать. Код unsigned char pic[1000*800*3];
class MyWindow : public Fl_Double_Window{ public: MyWindow() : Fl_Double_Window(1000,800) { } void draw(){ fl_draw_image(pic,0,0,1000,800,3,0); } };
MyWindow * w;
void callback(void*) { static int t = GetTickCount(); printf("%d\n",GetTickCount() - t); t = GetTickCount();
for (int y = 0; y < 800; y++){ pic[3*(0+y*1000)+0] = rand(); pic[3*(0+y*1000)+1] = rand(); pic[3*(0+y*1000)+2] = rand(); for (int x = 999; x >= 1; x--){ pic[3*(x+y*1000)+0] = pic[3*((x-1)+y*1000)+0]; pic[3*(x+y*1000)+1] = pic[3*((x-1)+y*1000)+1]; pic[3*(x+y*1000)+2] = pic[3*((x-1)+y*1000)+2]; } } w->redraw(); Fl::repeat_timeout(0.1, callback); }
int main(int argc, char ** argv){ w = new MyWindow(); for (int y = 0; y < 800; y++){ for (int x = 0; x < 1000; x++){ pic[3*(x+y*1000)+0] = rand(); pic[3*(x+y*1000)+1] = rand(); pic[3*(x+y*1000)+2] = rand(); } } Fl::add_timeout(0.1, callback); w->show(); return Fl::run(); }
|
|
|
|
|
Sep 1 2016, 18:00
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Типа такого надо ) Вся картинка должна ехать влево с обновлением справа
Сообщение отредактировал whale_nik - Sep 1 2016, 18:00
Эскизы прикрепленных изображений
|
|
|
|
|
Sep 2 2016, 06:38
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(whale_nik @ Sep 1 2016, 19:49)  Если делать тупо в лоб то страшные тормоза, посоветуйте куда копать, явно есть методы быстрого вывода, задача для меня вновье. Пример на дельфи, на билдер сами адаптируете. 1. Создаёте вспомогательный TBitmap (где-нибудь в конструкторе): Код bt := TBitMap.Create; 2. Рисуете в него свои точки: Код for y := 1 to bt.Height-1 do begin pt := bt.ScanLine[y]; for x := 1 to bt.Width-1 do pt^[x] := Round(Random*x); end; end; 3. Можете добавить что угодно, например, текст: Код bt.Canvas.TextOut(10,10, 'И не надо никакого MSDN'); 4. Выводите битмап на форму: Код Canvas.Draw(0,0, bt); Всё!
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 2 2016, 21:26
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Сделал как советуете, все равно жесть как медленно и жрет кучу процессорного времени ( Может не так что сделал ? Builder 6.0
|
|
|
|
|
Sep 2 2016, 22:16
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Открываете MSDN на разделе Windows GDI\Bitmap Functions. Изучаете всё, что касается семейства BitBlt-функций. Создаёте memory device context, рисуете в нём (только с умом - не перерисовывая каждый раз туеву хучу точек, а дорисовывая только новый участок точек), затем из memory device context перекидываете картинку (с необходимым сдвигом) за пару операций BitBlt (или родственных) на screen device context. Плюсую. Кстати у TCanvas есть Handle, который явялется device context, который, как я понимаю, можно пихать в WinAPI функции. Кроме того у TCanvas имеются методы с аналогичным WinAPI функционалом, но надо бы протестировать их на тормознутость. http://docs.embarcadero.com/products/rad_s...vas_Handle.htmlВозможно у TImage тоже будет возможность взять device context....надо погуглить
--------------------
The truth is out there...
|
|
|
|
|
Sep 2 2016, 23:34
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
у openGL есть glDrawPixels. инициализация через GLFW а вот winAPI функции лучше запихать в... <Гусары, МОЛЧАТЬ!> можно заодно с builder 6.0 Код #include "GLFW/glfw3.h" #include <stdio.h> #include <windows.h>
unsigned char pic[1000*800*3];
int main(void){ int t0 = GetTickCount(); GLFWwindow* window;
/* Initialize the library */ if (!glfwInit()) return -1;
/* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(1000, 800, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; }
/* Make the window's context current */ glfwMakeContextCurrent(window); /* Loop until the user closes the window */ while (!glfwWindowShouldClose(window)){ /* Render here */ glClear(GL_COLOR_BUFFER_BIT); for (int i = 0; i < 1000*800*3; i++) pic[i] = rand(); glDrawPixels(1000,800, GL_RGB, GL_UNSIGNED_BYTE, pic); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); printf("%d\n", GetTickCount()-t0); t0 = GetTickCount(); } glfwTerminate(); return 0; }
|
|
|
|
|
Sep 3 2016, 03:01
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(_pv @ Sep 3 2016, 05:34)  у openGL есть glDrawPixels. а вот winAPI функции лучше запихать в... <Гусары, МОЛЧАТЬ!> И Ваш код будет таким-же тормознутым как и предыдущих дельфи-"специалистов". Главная ошибка: перерисовывать попиксельно каждый раз весь экран. Рисовать по пикселам нужно минимум - только обновлённую часть. Старую часть изображения просто копировать ...Blt-функциями. Сомневаюсь, что у OpenGL будет выигрыш по сравнению с WinAPI-шными BitBlt/PatBlt/.... В своё время много времени потратил на оптимизацию подобной задачи: переделывал изначальный свой WinAPI-вариант (через BitBlt/PatBlt/...) на DirectDraw. Получил абсолютно то же самое время работы. Сделал вывод, что при возможности, WinAPI-шные BitBlt/PatBlt/... вызывают изнутри DirectX, поэтому и не видно разницы во времени работы. Думаю что с OpenGL будет то же самое. Конечно в том, что ставить точки лучше не по одной, а пачкой - Вы правы. В WinAPI по-моему тоже есть подобная функция. Цитата(whale_nik @ Sep 3 2016, 06:36)  Если бы как то не заносить значения по новой а двигать область памяти этой матрицы, прибавляя справа по одному столбцу, там же все на указателях, нельзя так сделать ? Память как то закольцевать ) Я Вам это советовал ещё несколько сообщений назад. Но видно "чукча - не читатель..."
|
|
|
|
|
Sep 3 2016, 08:42
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Курить в сторону направления, заданного jcxz  Перемещая окна винды, очевидно, что скроллинг реализовать можно. Так как сама ОС это делает. ТС можно также попробовать посмотреть в сторону оптимизации алгоритма вывода на отображение нарисованного тем или иным способом. Я имею ввиду конвейерную подготовку данных и их отображение. ( Пока виртуально отрисовывается массив, уже готовый образ отображается другим потоком). Кроме того, если ОНО сдвигается, то нет смысла перерисовывать 99.999 информации. Достаточно вывести правый "столбик", который "новый". Эти 99.999 изображения уже на экране, их выводить не нужно, достаточно только указать драйверу сместить указатель отображения левого верхнего угла массива в видео-памяти. Как до него добраться - это уже спортивный вопрос
|
|
|
|
|
Sep 3 2016, 08:48
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(jcxz @ Sep 3 2016, 09:01)  И Ваш код будет таким-же тормознутым как и предыдущих дельфи-"специалистов". не будет, нынче скопировать пару МБайт из памяти в память это долго??? на моём довольно древнем компе, которому лет 10 уже, это занимает 1.5мс. Код LARGE_INTEGER t0,t1,f; QueryPerformanceFrequency(&f); QueryPerformanceCounter(&t0); for (int j = 0; j < 800; j++) memcpy(&pic[j*3000],&pic[j*3000+3],3000-3); QueryPerformanceCounter(&t1); printf("%G\n", (double)(t1.QuadPart - t0.QuadPart)/ f.QuadPart); да это криво и правильно было бы сделать два буфера размером с экран и заполнять их по очереди и отрисовывать со сдвигом. для этого есть glRasterPos3f. а совсем правильно сложить это сразу в память видеокарты, тогда и сдвиги и отрисовка процессор никак не нагрузят
|
|
|
|
|
Sep 3 2016, 09:38
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Я правильно понял, что если создать две одинаковые матрицы, и потом по очереди копировать одну в другую со сдвигом , прибавляя новые данные ? Так можно скопировать ? Можно примерчик плиз ? Я так понимаю это glCopyPixels ? Цитата(AHTOXA @ Sep 3 2016, 10:09)  Так у вас таймер молотит раз в миллисекунду! Это 1000FPS, конечно жрёт. Сделайте, 100ms, и будет всё нормально. Эта штука вообще должна летать со скоростью пули по хорошему, как на локаторе С-400 ) со 100 мс пока зкран весь сдвинется родить можно будет )
Сообщение отредактировал whale_nik - Sep 3 2016, 09:42
|
|
|
|
|
Sep 3 2016, 11:51
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(AHTOXA @ Sep 3 2016, 14:10)  Вы же сами в стартовом посте написали про 0.1с. Вот это и есть 100мс. А 1000FPS вы никакими BitBlt и OpenGl-ями не получите. Урежьте осетра  Чета я не то сказал ))) Реально хотелось бы достичь макс скорость 5 сек на весь экран, это 5/1100 = 4,5 мс/столбец ну а тут как получиться Цитата(_pv @ Sep 3 2016, 14:17)  с glCopyPixels сдвинуть текущую картинку на один пиксель и через glDrawPixels дорисовать только один недостающий столбец. никаких дополнительных буферов в этом случае вообще не надо. Осталось все это нарисовать в коде ) Цитата(Onkel @ Sep 3 2016, 13:47)  я еще когда в 90е делал систему сдирания буржуйских чипов для наших конфетных харь, готовил следующий экран в памяти, vga имело буфер размером со всю экранную память, и потом просто переключал память, выводимую на экран. Ну тут кроме это окна еще куча других работает, копировать весь экран не получиться. Такое предлагаю, создаем матрицу размер +1 по х, вводим новые значения в правый столбец, выводим в канву со сдвигом -1 (чтобы новые данные появились справа) копируем полученную канву в матрицу с нуля, и тд. Типа того, работает но жрет ресурсов столько же как предыдущие варианты ( похоже это типа тоже тупое копирование массива а не сдвиг указателя памяти TRect tRectFrom(1,0,1101,800); TRect tRectTo (0,0,1100,800); Image1->Canvas->CopyMode=cmSrcCopy; Image1->Canvas->CopyRect(tRectTo,gBitmap->Canvas,tRectFrom); TRect tRectFrom2(0,0,1100,800); TRect tRectTo2 (0,0,1100,800); gBitmap->Canvas->CopyRect(tRectTo2,Image1->Canvas,tRectFrom2); for ( y = 0; y < h1; y++) { ptr = (Byte *)gBitmap->ScanLine[y]; ptr[3300+0] = (Byte)Col; ptr[3300-1] = (Byte)0; ptr[3300-2] = (Byte)0; ptr[3300-3] = (Byte)Col; ptr[3300-4] = (Byte)0; ptr[3300-5] = (Byte)0; ptr[3300-6] = (Byte)Col; ptr[3300-7] = (Byte)0; ptr[3300-8] = (Byte)0; } ps а не , был не прав, вроде меньше нагрузка ...
Сообщение отредактировал Herz - Sep 3 2016, 12:35
|
|
|
|
|
Sep 3 2016, 12:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(whale_nik @ Sep 3 2016, 14:51)  . . . . Ну тут кроме это окна еще куча других работает, копировать весь экран не получиться. . . . . Если Вам эта работа нужна в качестве инструмента. В винде, по крайней мере в XP, можно "монополизировать" экран, те. фактически работать без окон, графика в полноэкранном режиме. (я давненько игрался с этим режимомом для реализации простого, но длинного графика-лога с удобным скроллингом мышкой и масштабированием) Окон естесетвенно, нет. Ваш график отображается реалтайм. При восстановлении стандартного режима, окно "свертывается", с упрощенным отрбражением, скроллинг загрубляется, например, до 20 позиций раз по полсекунды.
|
|
|
|
|
Sep 3 2016, 12:38
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Без окон никак, увы. Вот вроде бы нагрузка небольшая получилась...
Сообщение отредактировал Herz - Sep 3 2016, 17:24
Причина редактирования: Избыточное цитирование
|
|
|
|
|
Sep 3 2016, 12:44
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(DASM @ Sep 3 2016, 16:43)  а почему побайтно работаете и не пословно? Не понял вопроса, в смысле цвета ?
Сообщение отредактировал whale_nik - Sep 3 2016, 16:52
|
|
|
|
|
Sep 3 2016, 13:16
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(whale_nik @ Sep 3 2016, 16:51)  Чета я не то сказал ))) Реально хотелось бы достичь макс скорость 5 сек на весь экран, это 5/1100 = 4,5 мс/столбец ну а тут как получиться 4,5 мс - это 222 герца. Тоже многовато. Вы примите во внимание, что для человеческого глаза не нужна такая частота. Достаточно, скажем, 60 Гц (вернее, достаточно 25, а 60 - это будет ультра-гладкая картинка). Вот и перерисовывайте соответственно 60 раз в секунду. Пусть за одну перерисовку у вас добавляется не один, а несколько столбцов.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Sep 3 2016, 17:42
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(AHTOXA @ Sep 3 2016, 17:16)  4,5 мс - это 222 герца. Тоже многовато. Вы примите во внимание, что для человеческого глаза не нужна такая частота. Достаточно, скажем, 60 Гц (вернее, достаточно 25, а 60 - это будет ультра-гладкая картинка). Вот и перерисовывайте соответственно 60 раз в секунду. Пусть за одну перерисовку у вас добавляется не один, а несколько столбцов. 4,5 это не обновление картинки а добавление одного столбца, а частота окна получиться 5 сек если считать кадром обновление всего окна. Цитата(amaora @ Sep 3 2016, 17:26)  В лоб будет больше 60 к/с, если оптимизировать как должно, немного медленнее memcpy. А можно и взять готовый memmove, останется добавлять один столбец. Выводить можно через libsdl. Вы говорите для меня загадками ) Господа, вот такая штука виснет намертво и ничего не выводит, если без goto в таймере вызывать все отлично, в чем дело ? int h1 = gBitmap->Height; int w1 = 3300; fg: Col--; for ( y = 0; y < h1; y++) // âàðèàíò 2 = ìåíÿåì â ìàñèâå òîëüêî îäèí ñòîëáåö { data_in[0][y]=random(250); data_in[1][y]=random(250); data_in[2][y]=random(250); } //----------------------------------- TRect tRectFrom(1,0,1101,h1); TRect tRectTo (0,0,1100,h1); Image1->Canvas->CopyMode=cmSrcCopy; Image1->Canvas->CopyRect(tRectTo,gBitmap->Canvas,tRectFrom); TRect tRectFrom2(0,0,1100,h1); TRect tRectTo2 (0,0,1100,h1); gBitmap->Canvas->CopyRect(tRectTo2,Image1->Canvas,tRectFrom2); for ( y = 0; y < h1; y++) { ptr = (Byte *)gBitmap->ScanLine[y]; ptr[w1+0] = (Byte)data_in[0][y]; ptr[w1-1] = (Byte)data_in[1][y]; ptr[w1-2] = (Byte)data_in[2][y]; } //----------------------------------- Sleep(100); goto fg;
|
|
|
|
|
Sep 3 2016, 17:46
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ребят, я не понимаю зачем нам тут gl и уж тем более полноэкранная графика с монополизацией экрана.... Компонент лежит на форме и может предоставить свой DC(Device Context). Этот контекст как раз позволит рисовать в заданную область на форме(в окне). Зачем лезть в gl если есть более стандартные функции из GDI. Сделать это всё на Canvas вместо Image и будет счастье. Я бы взял за основу вот этот пример, где есть скроллинг битмэпа https://msdn.microsoft.com/ru-ru/library/wi...0(v=vs.85).aspxИспользуется как раз BitBlt() Device context у нас есть, буфер сделать нет проблем... в целом тоже нет проблем ) Ежели кто-то сможет пояснить за использование GL в данном случае то я бы с интересом почитал.
--------------------
The truth is out there...
|
|
|
|
|
Sep 3 2016, 17:58
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(AHTOXA @ Sep 3 2016, 17:16)  Вот 5 сек на весь экран примерно 5мс/столбец, не вижу тут мега быстрого чего то .
|
|
|
|
|
Sep 3 2016, 19:09
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(sigmaN @ Sep 3 2016, 22:31)  Логичнее было бы в архив прилепить исходник, вместо этого безобразия Пардон, попробуйте этот
|
|
|
|
|
Sep 3 2016, 19:23
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Проц не грузит(не более 1 - 2% показывает диспетчер задач) Плохо только, что дёргается немного скроллинг. Видимо используется таймер(ну, который Timer, который на форму кидается). Он как-то кривовато работает с маленькими задержками.... Предлагаю попробовать отдельный Thread + Sleep() с подкрученным перед этим таймером для увеличения точности https://msdn.microsoft.com/ru-ru/library/wi...8(v=vs.85).aspxЦитата To increase the accuracy of the sleep interval, call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function to set the timer resolution to its minimum. Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application. Кстати помнится у меня были проблемы когда я рисовал из другого потока. Так что рисуйте только из основного потока! Вполне может быть, что существует не многопоточный способ убрать эту дерготню.... Это я просто предположил, что дело в таймере. Просто я когда-то наблюдал такие-же подергивания когда таймером анимировал выезд строки в титрах. Кстати еще как-то использовал для точного измерения времени QueryPerformanceCounter(), может удастся сюда приспособиьт как-нибудь https://msdn.microsoft.com/en-us/library/wi...8(v=vs.85).aspx
--------------------
The truth is out there...
|
|
|
|
|
Sep 3 2016, 23:24
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну Sleep() это я предложил просто. Хотя вы правы, в MSDN этот момент описывается. Я тут подумал, что в принципе таймер это просто надстройка над API Цитата TTimer is used to simplify calling the Windows API timer functions SetTimer and KillTimer, and to simplify processing the WM_TIMER messages. http://docwiki.embarcadero.com/Libraries/B...ExtCtrls.TTimerЕсть информация, что стандартное разрешение таймера в венде 15.6ms https://randomascii.wordpress.com/2013/07/0...gawatts-wasted/Думаю это довольно мало для наших целей... Так что самое первое что надо попробовать - таки задрать частоту таймера(не забыть потом вернуть как было!) https://msdn.microsoft.com/en-us/library/wi...6(v=vs.85).aspxЯ тут начал задумываться а как вообще тогда сделать плавную анимацию средствами GDI? Add: Провел эксперимент: увеличил частоту таймера. Ничего не изменилось. Заметил кстати, что изменяя ширину окна изменяется и скорость движения пикселей... Очень странно....
--------------------
The truth is out there...
|
|
|
|
|
Sep 4 2016, 04:08
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(DASM @ Sep 4 2016, 05:43)  Таймера в винде для такого иные, см. BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount) По этим таймерам не получишь пробуждение потока. Только время померить можно. Чтобы не дёргалось изображеие, копать надо в сторону синхронизации с кадровой развёрткой видеокарты. И если хочется чтобы под виндой потоку и процессу меньше мешали другие процессы/потоки, повышайте приоритет и потока и процесса: SetThreadPriority()/SetPriorityClass(). Но опять-же - если поток уже ушёл в Sleep то получить управление он может только с дискретностью таймера виндового шедулера, который 18.2Гц всего. Ну хотя если получит событие от периферии какой-либо, то может тоже пробудится? Например - от изохронной точки USB с частотой 1кГц может быть сможет пробуждаться. Но винда - это не реалтайм система, она не для того делалась, так что гарантии нет никакой.
|
|
|
|
|
Sep 4 2016, 10:23
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Провел тут пару экспериментов со слипом... за основу было взято это https://www.daniweb.com/programming/softwar...the-windows-gdiВ общем создать в Visual Studio Win32 проект и скопипастить туда http://pastebin.com/USiiAXxZfps специально зажат, чтобы цикл упирался именно в Sleep() таким образом равномерность движения будет зависеть только от равномерности слипа. Также интересно раскоментить //timeBeginPeriod(1); в WinMain() и убедиться, что Sleep() тоже начинает работать точнее. Т.е. виндовый шедулер зависит от частоты таймера(о чем в MSDN тоже где-то читал). Сам скроллинг сделано втупую на циклах... тут не в этом прикол как говорится. Кстати у ТСа пиксели какие-то большие в примере! Вот тут у меня реально 1000*800 как в первом посте указано. Во вложении exe для проверки плавности ) У ТСа проблема с плавностью явно не из-за проблемы точности Sleep()! Ибо там рывки такие, что со стула упасть можно P.S. кстати если в цикле оставить только BitBlt то получается более 500FPS. так что сама операция отрисовки на экран реально быстрая!
--------------------
The truth is out there...
|
|
|
|
|
Sep 4 2016, 19:12
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(sigmaN @ Sep 4 2016, 01:59)  а, ну если чисто для пробы то в цикле while(!Application.terminated() ) { делаете то что вы делаете сейчас в обработчике онтаймер; потом Application.processMessages(); } Ну там в документации гляньте, может Terminated это не функция... В общем это наверно будет самое быстрое что можно сделать легко и просто
Цикл этот запихните в обработчик кнопки старт например. Так пробовал, ничего не работало, все виснет намертво почему то. Насчет пикселей в том примере что у вас там сразу по три выводиться для скорости, это был пример для Антохи с 5 сек на экран.
Сообщение отредактировал whale_nik - Sep 4 2016, 19:17
|
|
|
|
|
Sep 4 2016, 19:32
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Удалил файл проекта так как вы уже свой написали, я просмотрел ) Цитата(sigmaN @ Sep 4 2016, 23:15)  Странно.. при условии, что в цикле есть вызов Application.processMessages(); висеть не должно... Счас спробую . Заработало, но в цикле самое быстрое 10 сек на экран, проц уже грузиться сильно, если в примере что я давал по три точки это 3,3 сек, Так чтобы как пуля надо уже что то другое делать. вот по три точки сразу в бесконечном цикле без таймеров и задержек
Сообщение отредактировал whale_nik - Sep 4 2016, 19:18
|
|
|
|
|
Sep 5 2016, 10:46
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Глянул пару исходничков тут.. В том числе Quake 3 даже. Похоже нормальные пацаны для измерения времени c миллисекундной точностью используют timeGetTime() вместо GetTickCount(); И таки в самом начале они разгоняют таймер использую timeBeginPeriod(1), что в том числе благотворно сказывается и на Sleep(); В общем вот усовершенствованная версия максимально плавной анимации, которую я смог достичь. http://pastebin.com/gAQqdrJ0Кстати по скорости тоже я впечатлен. Скроллинг удалось разогнать до 680FPS! В принципе учитывая, что TCanvas даёт нам свой DC - можно то-же самое реализовать и в C++ Builder и в Delphi. И даже в случае чего завернуть это в отдельный компонент, чтоб можно было эти графики ложить на форму. Я так когда-то самодельный DBGrid делал с нестандартной раскраской )
--------------------
The truth is out there...
|
|
|
|
|
Sep 5 2016, 10:56
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну не знаю, тут вопрос как-бы про принципиальную возможность простой, но плавной анимации. Например графики плывущие в окно выовдить через DirectX не хотелось бы т.к. в нем надо отдельно разбираться наверно.... В принципе полученным результатом лично я сейчас доволен. И по скорости и по плавности. Для типичных задач типичного эмбэддера очень достойно. Нам то не игры тут писать ) Обратите внимание сколько 30FPS версия моего тестового образца жрет процессора. Красота же! ADD:очень интересные эффекты наблюдаются если плавно менять FPS. Используйте стрелки влево-вправо. те кратность развертке очень важна! 60фпс лучше чем 70 на 40 вообще как-то странно все это выглядт....
--------------------
The truth is out there...
|
|
|
|
|
Sep 6 2016, 05:18
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(sigmaN @ Sep 5 2016, 23:42)  Главный вывод моих экспериментов такой: BitBlt на экран нужно делать 60раз в сек(если конечно успевает проц). А саму отрисовку графики можно делать и с меньшей частотой, это не важно. Главное именно Blt в окно чтоб выполнялось 60fps. И тогда красота получается) И какой смысл? Перерисовывать 60раз/сек неизменяющуюся картинку? Делать BitBlt из памяти на экран чаще чем частота обновления картинки - нет смысла. Видеопамять она не теряет предыдущую картинку, на то она и память. Нарисовали картинку в памяти - копируете её BitBlt в видеоОЗУ. Можно даже параллельно (в другом thread) с отрисовкой новой картинки в памяти. Ещё лучше если сделать синхронизацию с кадровой развёрткой, для уменьшения всяких артефактов, типа дёрганья и искажения картинки из-за наложения частоты кадровой развёртки и частоты обновления картинки.
|
|
|
|
|
Sep 6 2016, 08:54
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(sigmaN @ Sep 6 2016, 14:40)  но выводящий на экран цикл всё равно должен крутиться с частотой 60Гц. Зачем? Цитата(sigmaN @ Sep 6 2016, 14:40)  Кто бы сказал как нам в венде синхронизировать свой Thread с VSync - цены бы не было этому человеку! Только я так понял, что даже в GL и DirectX VSync включается отправкой запроса драйверу типа: "давай я буду рисовать как хочу, а ты там синхронизируй всё это с VSync". И драйвер видяхи еще и имеет право не выполнять просьбу. Например в панели управления NVidia можно выключить VSync и всё ) Или наоборот включить принудительно. Там возможно другой механизм кадровой синхронизации есть. Например: Двойная буферизация, с рисованием в теневой странице (в это время отображается другая страница). По завершении формирования картинки, рисующий алгоритм вызывает функцию - запрос переключения страниц. Но этот запрос выполнится только во время обратного хода луча и страницы поменяются местами. И с этого момента рисующему алгоритму должно прийти уведомление, что с этого момента его запрос выполнен и он может рисовать новый кадр в новой теневой странице. Не знаю есть ли такой механизм, но такой вариант возможен. С таким механизмом не будет случаев, когда часть картинки отобразилась в одном кадре (успела нарисоваться), а другая часть - в следующем.
|
|
|
|
|
Sep 6 2016, 09:12
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата Зачем? Уж не знаю, эксперимент показал, что на 60Гц таки всё двигается плавнее. У меня Win10 Кстати я в своих экспериментах не видел тиринга. Терзают меня догадки, что GDI уже синхронизирован с VSync где-то внутри.... А вот именно синхронизировать поток с VSync это было бы полезно. Ну чтоб вместо Sleep() было что-нибудь типа WaitForVSync().
--------------------
The truth is out there...
|
|
|
|
|
Sep 8 2016, 22:39
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Подскажите еще допустим есть переменная 0-256, как вывести цвет точки так , чтобы при изменение переменной от 0 до 256 цвет менялся по спектру глаза те 0- фиолетовый, 128- желто-зеленый, 256- красный, долго думал пока не понял. Цвет задается тремя цифрами (красный, зеленый синий ), но как их скомбинировать под эту задачу... Те надо плавный спектр а не скажем (TColor)RGB(256-Col,128,Col);  Те нужно знать весовые функции для каждого цвета в зависимости от переменной 0-256
Сообщение отредактировал whale_nik - Sep 8 2016, 23:10
|
|
|
|
|
Sep 9 2016, 09:06
|
Местный
  
Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483

|
Цитата(alexr22b @ Sep 9 2016, 07:17)  Спасибо, то что надо )
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|