Автор Тема: Каким яп можно быстро манипулировать пикселями? (выбор яп)  (Прочитано 1988 раз)

Оффлайн m.A

  • Житель
Привет. Вот приспичило мне обрабатывать некими алгоритмами массив точек(пикселей) области экрана. Чтобы была анимация неких генерируемых процессов в реальном(хотелось бы быстро чтобы наглядно) времени. Встал вопрос выбора подходящего инструмента - языка программирования. Подходящего для задачи и подходящего такому программисту, как я(в коде ниже возможна куча ошибок).
Для теста скорости отрисовки конкретным языком(библиотекой) решил просто рисовать массив точек черного или белого цвета. Как белый шум на экране аналогового тв, когда нет сигнала. И посмотреть сколько кадров в секунду вообще возможно рисовать. Ведь я еще даже не буду обрабатывать массив точек по нужному мне алгоритму, просто рандом(белый ИЛИ черный).
Попробовал Free Pascal(Lazarus). Если в лоб, то очень медленно. С разрешением поля 800х600 всего 3.5 к/с(кадров в секунду).
Рисую 60 циклов и считаю за какое время отрисовалось:
Код
begin
  myBitmap := TBitmap.Create;
  myBitmap.SetSize(800, 600);

  M1 := Now;
  for Count := 0 to 60 do
  begin
    for x := 0 to 800 do
      for y := 0 to 600 do
      begin
        if Random > 0.5 then
          myBitmap.Canvas.DrawPixel(x, y, TColorToFPColor(clWhite))
        else
          myBitmap.Canvas.DrawPixel(x, y, TColorToFPColor(clBlack));
      end;
    PaintBox1.Canvas.Draw(0, 0, myBitmap);
    //myBitmap.Free;
  end;
  M2 := Now;
  fps := 60 / (MilliSecondsBetween(M1, M2) / 1000);
  labCap := FloatToStr(fps);
  Label1.Caption := labCap;
end;

Медленно. Погуглил. Есть у Free Pascal быстрые библиотеки для манипуляции пикселями. Немного замороченные, не осилил. Да и как-то не понравилось в целом.

======================================
Ну, наверное, чистый С с какой-нибудь графической библиотекой покажет скорость? Наткнулся как раз на интересный фреймворк raylib. Код на С:
Код
#include "raylib.h"

int main(void)
{
    const int screenWidth = 1600;
    const int screenHeight = 900;
   
    InitWindow(screenWidth, screenHeight, "WhiteNoise window");

    while (!WindowShouldClose())
    {
        int x, y, rnd;
        BeginDrawing();
            for (x = 0; x < screenWidth; x++) {
                for (y = 0; y < screenHeight; y++) {
                    rnd = GetRandomValue(0, 1);
                    if(rnd==1) DrawPixel(x, y, RAYWHITE);
                    if(rnd==0) DrawPixel(x, y, BLACK);
                }
            }
            DrawFPS(0, 0); 
        EndDrawing();
    }
    CloseWindow();
    return 0;
}
С, при большем разрешении поля 1600х900 даёт всего-то 10 к/с. Интересно, что ГСЧ там не очень хороший, изображение(картинка1) как бы смещается вправо-вверх. Но это претензии не к скорости. Язык С дает всего 10 кадров? Наверное не правильную библиотеку выбрал. Или не умею его готовить.

======================================
Посмотрел, что может FreeBasic. Старый Демон плохого не посоветует же? Код:
Код
Dim As Integer screenWidth, screenHeight
screenWidth = 1600
screenHeight = 900
Screenres screenWidth, screenHeight, 32

Dim As Integer x, y, rand

Do
    If Inkey = Chr$(27) Then Exit Do 
    For x = 0 To screenWidth
        For y = 0 To screenHeight
            rand = Rnd
            If rand = 1 Then
                Pset (x, y), Rgb(255,255,255)
            Else
                Pset (x, y), Rgb(0,0,0)
            End If
        Next y
    Next x
Loop
End
Как подсчитывать в FreeBasic к/с не нашел. Но визуально около 10 к/с. И еще синхронизация с монитором не совпадает, плывет. Почитал документацию. Использовал буфер, чтобы синхронизация не плыла. Рисую 600 циклов и просто засекаю отдельным секундомером:
Код
Dim As Integer screenWidth, screenHeight
screenWidth = 1600
screenHeight = 900
ScreenRes screenWidth, screenHeight, 32

Dim As Integer x, y, rand, count

Dim image As Any Ptr = ImageCreate( screenWidth, screenHeight, RGB(0, 0, 0) )

For count = 1 To 600
   For x = 0 To screenWidth
      For y = 0 To screenHeight
         rand = Rnd
         If rand = 1 Then
            PSet image, (x, y), RGB(255, 255, 255)
         Else
            PSet image,  (x, y), RGB(0, 0, 0)
         End If
      Next y
   Next x
   
   Put (0, 0), image, PSet
   
Next count
End

FreeBasic: 600 циклов за ~45 секунд. ~13 к/с. FreeBasic медленный.

======================================
Что там далее? Попробовал язык Processing (Java):
Код
void setup() {
  size(1600, 900);
  frameRate(60);
  background(0);
}

void draw() {
  if (keyCode == ESC) exit();
  int rnd;
  for (int x = 0; x < width; x++)
  {
    for (int y = 0; y < height; y++)
    {
      rnd = (int)random(2);
      if(rnd==1) set(x, y, color(255,255,255));
      else set(x, y, color(0,0,0));
    }
  }
  String txt = String.format("Window 1   %6.2fps", frameRate);
  windowTitle(txt);
  println(frameRate);
  text(frameRate,0,0);
}

Processing: 32 к/с! Это рекорд, Java быстрее всех. А если еще переписать так:

Код
void setup() {
  size(1600, 900);
  frameRate(60);
  background(0);
}

void draw() {
  if (keyCode == ESC) exit();
  loadPixels();

  for (int i = 0; i < pixels.length; i++) {
    float rand = random(255);
    color c = color(rand);
    pixels[i] = c;
  }

  updatePixels();
  println(frameRate);
  text(frameRate, 0, 0);
}

То здесь получаем 53 к/с. Выбираю Processing.

Может кто-то перепишет примеры кода правильнее, чтобы быстрее было? Я где-то ошибся? Может кто-то напишет код на другом языке/фреймворке? Алгоритм я думаю понятен. Еще напишу, что хочется писать алгоритм обработки массива(вместо rand), а не  длиннющие портянки кода инициализации и работы с OpenGl напрямую.

Оффлайн Samovar

  • Житель
Цитировать
Посмотрел, что может FreeBasic. Старый Демон плохого не посоветует же?
FreeBasic: 600 циклов за ~45 секунд. ~13 к/с. FreeBasic медленный.
Считай так... не вопрос :) Java все равно проиграет :) хотя, х.з. ... у всякого ЯП есть подводные камни...
Даже на конструкторе  GameEditor  мне попадался пример с симуляцией жидкости попиксельно (но там виртуальная машина Cи стоит, даже,а не Си)... и это работает быстро, т.к.
 OpenGL...
-------
Пока я не буду с тобой спорить... но как будет время разобраться и проверить, обязательно вернусь к этому вопросу.

Оффлайн Anchoret

  • Житель
Когда все это дело делалось на слабых машинах, то имитировалась через строчная развертка - чтобы более плавно все это дело появлялось на экране. Например на древнем ZX Spectrum кроме того, что все писалось на ассемблере, была некая экранная память - диапазон адресов экранного адресного пространства. Вот в эту "экранку" все напрямую и выгружалось строками байтов. Но это седая древность, тогда еще не было различных разрешений экрана и пр.. Как это все сейчас возможно реализовать в самом понятном для компе языке мне не ведомо)

Оффлайн Samovar

  • Житель
Anchoret, на Freebasic и так, и этак и через укакзатель на видобуфер... и прямой к нему доступ через poke()...или ассемблер...
Просто у меня нет времени с этим ковыряться сейчас... я ж не программист, а любитель  :)

Оффлайн LanuHum

  • Житель
Как дилетант могу предложить C++ openGL . Можно поковыряться в  projectM Visualizer
An open-source library for music visualization using Milkdrop-style presets and shaders
https://github.com/projectM-visualizer

Оффлайн Samovar

  • Житель

Цитировать
Привет. Вот приспичило мне обрабатывать некими алгоритмами массив точек(пикселей) области экрана. Чтобы была анимация неких генерируемых процессов в реальном(хотелось бы быстро чтобы наглядно) времени. Встал вопрос выбора подходящего инструмента - языка программирования. Подходящего для задачи и подходящего такому программисту, как я(в коде ниже возможна куча ошибок).
Для теста скорости отрисовки конкретным языком(библиотекой) решил просто рисовать массив точек черного или белого цвета. Как белый шум на экране аналогового тв, когда нет сигнала. И посмотреть сколько кадров в секунду вообще возможно рисовать. Ведь я еще даже не буду обрабатывать массив точек по нужному мне алгоритму, просто рандом(белый ИЛИ черный).
Попробовал Free Pascal(Lazarus). Если в лоб, то очень медленно. С разрешением поля 800х600 всего 3.5 к/с(кадров в секунду).
Именно из-за графики я и выбрал Freebasic. Да и с детства знаю этот ЯП.
Есть свои нюансы, естественно... но всё работает "из коробки" :)
Позже отпишусь по твоему вопросу более подробно... ты не запрещаешь прерывания, когда производишь отрисовку в видеобуфер: Screenlock, Scsreenunlock, потому у тебя и медленно... да куча там ещё вещей...

Оффлайн Striver

  • Житель
  • недоинженер, полупрограммист
    • http://striver00.ru
По хорошему не должно быть НИКАКИХ попиксельных записей/чтений в видеопамять. Вся индивидуальная работа  с отдельными пискселями должна вестись с буфером в обычной памяти, а после всех циклов нужно выгружать этот буфер в видеопамять одной командой. Именно так, насколько я понял, работает второй (а, может, и первый тоже, тонкостей библиотеки Processing не знаю) вариант программы на яве, поэтому он быстрее всех и получился.

Наверное, альтернативой этому могла бы быть возня с пикселями через шейдеры чисто внутри видеопамяти, но тогда и алгоритмы придётся на glsl писать.

Оффлайн LanuHum

  • Житель
Не знаю, чем вы тут занимаетесь, но, мне кажется стоит посмотреть в сторону готовых графических библиотек. Зачем рисовать на экране, если можно рисовать в окне в полно экранном режиме в уже приспособленных для этих целей программах
https://www.opennet.ru/docs/RUS/gtk_plus/x2486.html
или Simple C++ OpenGL program to draw points on a 2D canvas :
Код
#include<GL/glut.h>

void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);

glBegin(GL_POINTS);
glVertex2f(10.0, 10.0);
glVertex2f(150.0, 80.0);
glVertex2f(100.0, 20.0);
glVertex2f(200.0, 100.0);
glEnd();
glFlush();
}

void myinit() {
glClearColor(1.0, 1.0, 1.0, 1.0);
glColor3f(1.0, 0.0, 0.0);
glPointSize(5.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
}

void main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Points");
glutDisplayFunc(display);

myinit();
glutMainLoop();
}

Оффлайн Samovar

  • Житель
Цитировать
Не знаю, чем вы тут занимаетесь, но, мне кажется стоит посмотреть в сторону готовых графических библиотек.
Ответ на твой вопрос, Ланухумыч:

Цитировать
Еще напишу, что хочется писать алгоритм обработки массива(вместо rand), а не  длиннющие портянки кода инициализации и работы с OpenGl напрямую.

Оффлайн Samovar

  • Житель
Цитировать
По хорошему не должно быть НИКАКИХ попиксельных записей/чтений в видеопамять. Вся индивидуальная работа  с отдельными пискселями должна вестись с буфером в обычной памяти, а после всех циклов нужно выгружать этот буфер в видеопамять одной командой.
Абсолютносогласен.

Оффлайн LanuHum

  • Житель
А, что массивы и циклы в опенГЛ запрещены?
А каким способом желающий собирается объявлять цвет всех пикселей в двух словах?

Оффлайн Samovar

  • Житель
Цитировать
А, что массивы и циклы в опенГЛ запрещены?
А каким способом желающий собирается объявлять цвет всех пикселей в двух словах?
в freebasic, он может на это забить... ну не надо ему OpenGL... под винду там сразу DirectX по умолчанию (если не происать рендер-движок явно)... да и может, тупо, битами и байтами манипулировать напрямую в видеобуфере, если врубится как...
Короче... вот ссылка, там дохренища инфы и примеров для freebasic: https://users.freebasic-portal.de/freebasicru/

Оффлайн Samovar

  • Житель
Вот, по теме статья:
Низкоуровневая графика в FreeBASIC
https://users.freebasic-portal.de/freebasicru/lowlevelgraphics.html

Оффлайн LanuHum

  • Житель
А, я хочу без опенгл блендер, кинь мне ссылок сделать это на фрибейсике.

Оффлайн Samovar

  • Житель
А, я хочу без опенгл блендер, кинь мне ссылок сделать это на фрибейсике.
Мозг мне и себе не выёживай, пожалуйста :) Автор темы хотел ответы, думаю, он их получил. Дальше сам пусть мыслит.

 


Яметрика

* По форуму

* Рекламный блок

* Последние вложения

1 (1).png
Скачано: 3624
Автор: LEXA ANЭGROWND
blender.png
Скачано: 3628
Автор: ipv2007
4.png
Скачано: 3629
Автор: hiroyukiss
2.png
Скачано: 3643
Автор: hiroyukiss

Скачано: 3698
Автор: Dilifa12