Перейти к содержанию
    

Програмирование графики

Народ, надо вывести двумерный массив данных 1000*800 в виде точек на image (прогаю в buildere)

причем надо его сдвигать на одну координату скоростью 0,1сек ( с вводом новых )

Если делать тупо в лоб то страшные тормоза, посоветуйте куда копать, явно есть методы быстрого вывода,

задача для меня вновье.

Те в итоге видим экран 1000*800, по нему ползет изображение, которое обновляется справа на одну линию все время.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

быстрые методы это аппаратно через 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();
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Я пока просто точки ставил :rolleyes:

Изменено пользователем whale_nik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Типа такого надо )

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

post-40483-1472752779_thumb.jpg

Изменено пользователем whale_nik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Типа такого надо )

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

Открываете MSDN на разделе Windows GDI\Bitmap Functions. Изучаете всё, что касается семейства BitBlt-функций.

Создаёте memory device context, рисуете в нём (только с умом - не перерисовывая каждый раз туеву хучу точек, а дорисовывая только новый участок точек), затем из memory device context перекидываете картинку (с необходимым сдвигом) за пару операций BitBlt (или родственных) на screen device context.

И если всё так сделаете, загрузка CPU будет близкая к нулю, даже на слабом CPU.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если делать тупо в лоб то страшные тормоза, посоветуйте куда копать, явно есть методы быстрого вывода,

задача для меня вновье.

Пример на дельфи, на билдер сами адаптируете.

 

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);

 

Всё!

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Сделал как советуете, все равно жесть как медленно и жрет кучу процессорного времени (

Может не так что сделал ?

Builder 6.0

Project1.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Открываете 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....надо погуглить

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

у 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;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется основные тормоза и загрузка это инициализация битовой матрици все время по новой это 2 640 000 байт

Если бы как то не заносить значения по новой а двигать область памяти этой матрицы, прибавляя справа по одному столбцу, там же все на указателях, нельзя так сделать ? Память как то закольцевать )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

у openGL есть glDrawPixels.

а вот winAPI функции лучше запихать в... <Гусары, МОЛЧАТЬ!>

И Ваш код будет таким-же тормознутым как и предыдущих дельфи-"специалистов". Главная ошибка: перерисовывать попиксельно каждый раз весь экран. Рисовать по пикселам нужно минимум - только обновлённую часть. Старую часть изображения просто копировать ...Blt-функциями.

Сомневаюсь, что у OpenGL будет выигрыш по сравнению с WinAPI-шными BitBlt/PatBlt/....

В своё время много времени потратил на оптимизацию подобной задачи: переделывал изначальный свой WinAPI-вариант (через BitBlt/PatBlt/...) на DirectDraw. Получил абсолютно то же самое время работы. Сделал вывод, что при возможности, WinAPI-шные BitBlt/PatBlt/... вызывают изнутри DirectX, поэтому и не видно разницы во времени работы. Думаю что с OpenGL будет то же самое.

Конечно в том, что ставить точки лучше не по одной, а пачкой - Вы правы. В WinAPI по-моему тоже есть подобная функция.

 

Если бы как то не заносить значения по новой а двигать область памяти этой матрицы, прибавляя справа по одному столбцу, там же все на указателях, нельзя так сделать ? Память как то закольцевать )

Я Вам это советовал ещё несколько сообщений назад. Но видно "чукча - не читатель..."

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал как советуете, все равно жесть как медленно и жрет кучу процессорного времени (

Может не так что сделал ?

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

ТС можно также попробовать посмотреть в сторону оптимизации алгоритма вывода на отображение

нарисованного тем или иным способом. Я имею ввиду конвейерную подготовку данных и их отображение.

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

 

Кроме того, если ОНО сдвигается, то нет смысла перерисовывать 99.999 информации.

Достаточно вывести правый "столбик", который "новый". Эти 99.999 изображения уже на экране, их выводить не нужно, достаточно

только указать драйверу сместить указатель отображения левого верхнего угла массива в видео-памяти.

Как до него добраться - это уже спортивный вопрос :)

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И Ваш код будет таким-же тормознутым как и предыдущих дельфи-"специалистов".

не будет,

нынче скопировать пару МБайт из памяти в память это долго??? на моём довольно древнем компе, которому лет 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.

а совсем правильно сложить это сразу в память видеокарты, тогда и сдвиги и отрисовка процессор никак не нагрузят

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я правильно понял, что

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

Можно примерчик плиз ?

Я так понимаю это glCopyPixels ?

 

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

 

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

со 100 мс пока зкран весь сдвинется родить можно будет )

Изменено пользователем whale_nik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...