|
|
  |
Програмирование графики, вопрос |
|
|
|
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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|