Другое > Программирование (любое)
Каким яп можно быстро манипулировать пикселями? (выбор яп)
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
Навигация
Перейти к полной версии