реклама на сайте
подробности

 
 
5 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Програмирование графики, вопрос
whale_nik
сообщение Sep 1 2016, 14:49
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483



Народ, надо вывести двумерный массив данных 1000*800 в виде точек на image (прогаю в buildere)
причем надо его сдвигать на одну координату скоростью 0,1сек ( с вводом новых )
Если делать тупо в лоб то страшные тормоза, посоветуйте куда копать, явно есть методы быстрого вывода,
задача для меня вновье.
Те в итоге видим экран 1000*800, по нему ползет изображение, которое обновляется справа на одну линию все время.
Go to the top of the page
 
+Quote Post
_pv
сообщение Sep 1 2016, 16:02
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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();
}

Go to the top of the page
 
+Quote Post
whale_nik
сообщение Sep 1 2016, 16:13
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483



Не совсем понял а как это все вывести на форму ?
Я пока просто точки ставил rolleyes.gif

Сообщение отредактировал whale_nik - Sep 1 2016, 16:13
Go to the top of the page
 
+Quote Post
whale_nik
сообщение Sep 1 2016, 18:00
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483



Типа такого надо )
Вся картинка должна ехать влево с обновлением справа

Сообщение отредактировал whale_nik - Sep 1 2016, 18:00
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
jcxz
сообщение Sep 2 2016, 04:35
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(whale_nik @ Sep 2 2016, 00:00) *
Типа такого надо )
Вся картинка должна ехать влево с обновлением справа

Открываете MSDN на разделе Windows GDI\Bitmap Functions. Изучаете всё, что касается семейства BitBlt-функций.
Создаёте memory device context, рисуете в нём (только с умом - не перерисовывая каждый раз туеву хучу точек, а дорисовывая только новый участок точек), затем из memory device context перекидываете картинку (с необходимым сдвигом) за пару операций BitBlt (или родственных) на screen device context.
И если всё так сделаете, загрузка CPU будет близкая к нулю, даже на слабом CPU.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Sep 2 2016, 06:38
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 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);


Всё!


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
whale_nik
сообщение Sep 2 2016, 21:26
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483




Сделал как советуете, все равно жесть как медленно и жрет кучу процессорного времени (
Может не так что сделал ?
Builder 6.0
Прикрепленные файлы
Прикрепленный файл  Project1.zip ( 573.5 килобайт ) Кол-во скачиваний: 9
 
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Sep 2 2016, 22:16
Сообщение #8


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...
Go to the top of the page
 
+Quote Post
_pv
сообщение Sep 2 2016, 23:34
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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;
}

Go to the top of the page
 
+Quote Post
whale_nik
сообщение Sep 3 2016, 00:36
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483



Мне кажется основные тормоза и загрузка это инициализация битовой матрици все время по новой это 2 640 000 байт
Если бы как то не заносить значения по новой а двигать область памяти этой матрицы, прибавляя справа по одному столбцу, там же все на указателях, нельзя так сделать ? Память как то закольцевать )
Go to the top of the page
 
+Quote Post
jcxz
сообщение Sep 3 2016, 03:01
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 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) *
Если бы как то не заносить значения по новой а двигать область памяти этой матрицы, прибавляя справа по одному столбцу, там же все на указателях, нельзя так сделать ? Память как то закольцевать )

Я Вам это советовал ещё несколько сообщений назад. Но видно "чукча - не читатель..."
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Sep 3 2016, 06:09
Сообщение #12


фанат дивана
******

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



Цитата(whale_nik @ Sep 3 2016, 02:26) *
Сделал как советуете, все равно жесть как медленно и жрет кучу процессорного времени (
Может не так что сделал ?

Так у вас таймер молотит раз в миллисекунду! Это 1000FPS, конечно жрёт. Сделайте, 100ms, и будет всё нормально.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
k155la3
сообщение Sep 3 2016, 08:42
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Курить в сторону направления, заданного jcxz sm.gif

Перемещая окна винды, очевидно, что скроллинг реализовать можно. Так как сама ОС это делает.

ТС можно также попробовать посмотреть в сторону оптимизации алгоритма вывода на отображение
нарисованного тем или иным способом. Я имею ввиду конвейерную подготовку данных и их отображение.
( Пока виртуально отрисовывается массив, уже готовый образ отображается другим потоком).

Кроме того, если ОНО сдвигается, то нет смысла перерисовывать 99.999 информации.
Достаточно вывести правый "столбик", который "новый". Эти 99.999 изображения уже на экране, их выводить не нужно, достаточно
только указать драйверу сместить указатель отображения левого верхнего угла массива в видео-памяти.
Как до него добраться - это уже спортивный вопрос sm.gif


Go to the top of the page
 
+Quote Post
_pv
сообщение Sep 3 2016, 08:48
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 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.
а совсем правильно сложить это сразу в память видеокарты, тогда и сдвиги и отрисовка процессор никак не нагрузят
Go to the top of the page
 
+Quote Post
whale_nik
сообщение Sep 3 2016, 09:38
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 364
Регистрация: 25-09-08
Пользователь №: 40 483



Я правильно понял, что
если создать две одинаковые матрицы, и потом по очереди копировать одну в другую со сдвигом , прибавляя новые данные ? Так можно скопировать ?
Можно примерчик плиз ?
Я так понимаю это glCopyPixels ?

Цитата(AHTOXA @ Sep 3 2016, 10:09) *
Так у вас таймер молотит раз в миллисекунду! Это 1000FPS, конечно жрёт. Сделайте, 100ms, и будет всё нормально.


Эта штука вообще должна летать со скоростью пули по хорошему, как на локаторе С-400 )
со 100 мс пока зкран весь сдвинется родить можно будет )

Сообщение отредактировал whale_nik - Sep 3 2016, 09:42
Go to the top of the page
 
+Quote Post

5 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 23:10
Рейтинг@Mail.ru


Страница сгенерированна за 0.01471 секунд с 7
ELECTRONIX ©2004-2016