Ddraw с Delphix: пиксельное построение с практическими рекомендациями - PullRequest
3 голосов
/ 21 февраля 2012

Я использую Delphi 7 и Delphix, чтобы иметь возможность рисовать и создавать поверхность для воспроизведения с пикселями.

так что в триггере кнопки я использую это:

for i:=1 to 100 do
for j:=1 to 100 do
dxdraw1.Surface.Pixels[i,j]:=250;

, где dxdraw1 - поверхность рисования.

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

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

Также это медленно. Я где-то читал это:

»...

DXDraw.Surface.Canvas.Pixels[X,Y]:=clBlue;
DXDraw.Surface.Canvas.Release;

... "

и после этого:

»... Просто помните, что эта функция очень медленная. Он блокирует и разблокирует поверхность в каждом наборе пикселей ... не очень удобно. PixelDX и TurboPixel не делают, вы вручную блокируете поверхность, делаете все пиксельные операции, а затем разблокировать его .. в 1000 раз быстрее. ... "

Как использовать эти функции? Я не могу их найти (и я понятия не имею, так как я новичок в этом)? Как сначала заблокировать, а затем разблокировать?

U P D A T E:

Хорошо, я использовал undelphix, но в прямоугольнике я не вижу результат, он все еще остается черным:

procedure TForm1.BitBtn1Click(Sender: TObject);
var
i,j :integer;
begin
 dxdraw1.Surface.Lock;
 for i:=1 to 150 do
  for j:=1 to 150 do
   dxdraw1.Surface.Pixel[i,j]:=100;
 dxdraw1.Surface.Unlock;
end;

U P D A T E 2:

Это работает, но происходит это странно: чтобы увидеть результат, мне нужно «спрятать» окно приложения под другим окном или программой и свернуть это окно, чтобы увидеть результат. Если я перемещу приложение, то результат исчезнет, ​​и он останется пустым. Есть идеи?

1 Ответ

1 голос
/ 23 февраля 2012

Я не в курсе Delphi-X, но я много использовал сырые библиотеки DirectX в своей программе Life32.

Вот как это работает за кулисами:

  1. Вы получаете блокировку экрана.
  2. Возвращает указатель на память, в которую вы можете записать, все, что будет записано в этом блоке памяти, появится на экране.
  3. Вся система будет заморожена (!) До тех пор, пока вы не вызовете разблокировку.

Указатель памяти на шаге 2 можно рассматривать как указатель непосредственно на видеопамять.
Это зависит от вас, чтобы знать:
- бит на пиксель;
- количество пикселей в направлении x и y;
- заполнение байтов в конце каждой строки развертки;
- если число бит на пиксель меньше 24, вы будете работать не со значениями RGB, а с палитрой;
- если вы напишите после конца экрана, произойдет непредсказуемое (!)

DelphiX устарел
Я рекомендую вам использовать unDelphiX: http://www.micrel.cz/Dx/
Это гораздо более продвинутый и имеет гораздо больше возможностей.

Вы можете просто использовать:

DXDraw1.Surface.Lock; //special version Lock without any parameters
try
  for xy:= 0 to Min(DXDraw1.Height, DXDraw1.Width) - 1 do begin
    //silly example, unDirectX has line drawing routines
    DXDraw1.Surface.Pixel[xy, xy]:= TheColor;
  end; {for xy}
finally
  DXDraw1.Surface.Unlock;
end;

Поскольку вы вызывали lock до доступа к массиву пикселей, он не будет заключать вызов в пару lock - unlock.

Внимание
Всегда тратите минимально возможное время между вызовами lock и unlock, потому что вся ваша система будет зависать, пока дисплей заблокирован.
Также убедитесь, что Delphi не прерывает , а не в исключительных ситуациях при отладке кода внутри поля lock, поскольку ваша система будет заморожена без возможности ее восстановления.

Примечание
В вызове pixel все еще есть некоторые издержки, потому что значение color переводится в формат, определяемый BytesPerPixel для вашего дисплея.
Также [x,y] координаты переводятся в адрес памяти.
В Life32 я решил написать 8 различных процедур рисования для каждой возможной глубины пикселя.
И делаю собственное рисование блоков 16x16, таким образом избегая преобразования адресов для каждого пикселя.

Не рисуй, пока тебе не придется
Поскольку DirectX очень быстрый, его легко рисовать намного быстрее, чем видит глаз, используйте таймер высокого разрешения (входит в unDirectX), чтобы ограничить рисование до x кадров в секунду.
не используйте сообщения Windows, такие как WM_PAINT, чтобы сделать основной рисунок, но do перерисовывайте при получении входящего сообщения WM_PAINT.

...