-
А у Вас не бывает ошибки "Canvas does not allow drawing." ? Как с ней бороться? Чем быстрее я пытаюсь делать вывод на форму тем больше и больше их выскакивает... =((
> Beermonza © (06.08.09 18:55) [199]
Было бы интересно... =)
-
Для начала вывод GDI, ...все знакомы уже )) Var
DCs: HDC;
...
DCs := GetDC(Form1.Handle);
BitBlt(DCs, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY);
ReleaseDC(Form1.Handle, DCs);
DeleteDC(DCs); ...если на экран, то так: Var
DCs: HDC;
...
DCs := GetDC(0);
BitBlt(DCs, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY);
ReleaseDC(0, DCs);
DeleteDC(DCs); X, Y - координаты начала отрисовки; W, H - габариты изображения; {битмап} - картинка, в указанном формате. Теперь как задать битмапы. По идее нужно два по размеру зоны отрисовки, первый - невидимый кадр, что потом выводится на экран, второй - статическая подложка, ...в играх используется как поверхность некоторой игровой карты. Чтобы быстро рисовать нужно двойной доступ к битмапам, как стандартный, в котором можно применить Canvas, так и через указатель на данный в памяти. Это способ через CreateDIBSection(): Var
BInfo: tagBITMAPINFO;
PointerBuf: Pointer;
BufScr: PChar;
BufLine: Integer;
...
BInfo.bmiHeader.biSize := SizeOf(tagBITMAPINFOHEADER);
BInfo.bmiHeader.biWidth := W; BInfo.bmiHeader.biHeight := H; BInfo.bmiHeader.biPlanes := 1; BInfo.bmiHeader.biBitCount := 24; BInfo.bmiHeader.biCompression := BI_RGB;
Buf := TBitmap.Create();
Buf.Handle := CreateDIBSection(Canvas.Handle, BInfo, DIB_RGB_COLORS, Pointer(BufScr),0,0);
PointerBuf := Pointer(BufScr);
BufLine:=W*3;
If BufLine mod 4 <> 0 then BufLine:=((BufLine div 4)+1)*4; А если проще, то вот так: GetMem(BufScr, H*W*3);
PointerBuf := Pointer(BufScr);
BufLine:=W*3;
If BufLine mod 4 <> 0 then BufLine:=((BufLine div 4)+1)*4; В любой момент заполнить массив буфера можно вот так, правда не быстро, но при возможности: FillChar(BufScr^, W*H*3, 0);
Теперь трюки. Допустим у нас есть подложка Back и буфер Buf, полный размер буфера известен BufLength := (H*W*3) div 8; - для ровного счета. Указатели мы получили в начале создания. Вот так быстро переносим одно изображение в другое: asm
push esi
push edx
mov ecx, BufLength
mov esi, PointerBack
mov edx, PointerBuf
@@mix:
movq xmm0, [esi] movq [edx], xmm0
add esi, 8
add edx, 8
loop @@mix
pop edx
pop esi
emms
end; Остальное попробую сначала упростить, потом покажу. Пример работы показать не могу, ибо это игра, делается еще. Вы можете сами проверить без проблем.
-
Вот так рисуем в памяти на буфере кадра, ...это для целого изображения спрайта, без обрезки: type
TRGB = packed record
R: Byte;
B: Byte;
G: Byte;
end;
PRGB = ^TRGB;
Var
C, yy: Integer;
Bits, MapBits: PChar;
TexLine: Integer;
TexPoint, MapPoint, BufPoint: PChar;
TexPixel, MapPixel, BufPixel: PRGB;
const C1: int64 = $FFFFFFFFFFFFFFFF;
SW := ;
SH := ;
C := ((SW+1)*3) div 8;
If C > 0 then
Begin
Bits := ;
MapBits := ;
TexLine := ;
X := 10;
Y := 10;
TexPoint := Bits;
MapPoint := MapBits;
BufPoint := BufScr + (H - 1 - X) * BufLine + Y * 3;
asm pxor xmm7, xmm7
movq xmm3, C1
PUNPCKLBW xmm3, xmm7
end;
For yy:=0 to SH-1 do
Begin
TexPixel := PRGB(TexPoint);
MapPixel := PRGB(MapPoint);
BufPixel := PRGB(BufPoint);
asm
push edi
push esi
push edx
push ecx
mov ecx, C
mov esi, [TexPixel]
mov edx, [BufPixel]
mov edi, [MapPixel]
@@1:
cmp dword ptr [edi], 0
jne @@mix
cmp dword ptr [edi+4], 0
je @@Next
@@mix:
movq xmm0, [esi] PUNPCKLBW xmm0, xmm7
movq xmm1, [edx] PUNPCKLBW xmm1, xmm7
psubw xmm0, xmm1
movq xmm2, [edi] PUNPCKLBW xmm2, xmm7
pmullw xmm0, xmm2 psrlw xmm0, 8 paddw xmm1, xmm0
pand xmm1, xmm3
packuswb xmm1, xmm1
movq [edx], xmm1
@@next:
add esi, 8
add edx, 8
add edi, 8
loop @@1
pop ecx
pop edx
pop esi
pop edi
end;
TexPoint := TexPoint + TexLine;
MapPoint := MapPoint + TexLine;
BufPoint := BufPoint - BufLine;
end;
asm
emms
end;
end; Рисует ООЧЕНЬ быстро. Теперь момент, как и что за текстуры я использую и загружаю. В основном это PNG-файлы, ...полное сохранение цветов, альфа-канал и весят сравнительно мало. Вот так это происходит: uses
PNGImage; ...
type
BGR = packed record
B: Byte;
G: Byte;
R: Byte;
end;
TBGR = array [word] of BGR;
Var
PNGimg: TPNGObject;
y: Integer;
i, j: Word;
Bits: ^TBGR;
Alpha: PByteArray;
TexBits, MapBits: PChar;
...
PNGimg := TPNGObject.Create;
PNGimg.LoadFromFile();
...
For i := 0 to PNGimg.Height - 1 do
Begin
Bits := PNGimg.Scanline[i];
Alpha := PNGimg.AlphaScanline[i];
For j := 0 to PNGimg.Width - 1 do
Begin
y := j*3 + (i*(PNGimg.Width*3));
TexBits[y] := Chr(Bits[j].B);
TexBits[y + 1] := Chr(Bits[j].G);
TexBits[y + 2] := Chr(Bits[j].R);
MapBits[y] := Chr(Alpha[j]);
MapBits[y + 1] := Chr(Alpha[j]);
MapBits[y + 2] := Chr(Alpha[j]);
end;
end; TexBits и MapBits заполняются параллельно, и как видно, на первый взгляд, MapBits не рационально большой, хотя в исходном варианте в PNG он в 3 раза меньше по объему, ...но, это, только вещь кажущаяся ))) ...в отрисовке на ассемблере с MMX очень важно, чтобы данные шли параллельно, тогда легко забирая и обрабатывая по 8 байт скорость отрисовки увеличивается, нежели при расчете 3-х байт текстуры и 1-го байта маски. Есть еще один плюс такого увеличения массива маски, у нас есть независимое управление альфа-каналом по его трем составляющим R, G и B, т.е. можно, например, указать прозрачным какой-то один цвет а остальные оставить не прозрачными, в общем, варианты все, которые существуют. Надеюсь нет ошибок, упрощал без проверки, извините, если сразу не заработает, придется изучить и покопаться.
-
такой ерундой мы тоже занимались: http://pda.delphimaster.net/?id=1200150296&n=7PS я хз сколько ужрет у меня проца полноэкранное формирование кадра (тоже игру пишу :) ), просто там бамп, лайтмапы (причем они так же 32 битные), если надо рефракция (обычно типа колыхания водной поверхности, но тормозит нещадно в больших размерах).
-
У меня на Core 2 Duo 1,8GHz моя нещадно-огромная сцена ворочиется максимум на 30-40% загрузки CPU и 25 fps, и это еще не победа, работы ведутся.
-
На счет копирования одного изображения в другое, по одному размеру обоих, то я быстрее алгоритма, что показал, не придумал еще, ...особенно, когда идет массивный цикл сбора кадра, время копирования подложек ощутимо влияет на скорость общего вывода. А отрисовка не самая идеальная, ...нужно подумать, отправить за циклы всю статику, или полустатику, пока нет времени этим заниматься. Но и так уже кое-что ))
Кстати, antonn, а что за формула для линзы применена, ...все искал, как-то не попал на то, от чего оттолкнуться. Заметил формулу, по которой я смешиваю? ...result := buf + (tex-buf)*map shr 8 и по каждой компоненте цвета, грубовато для линзы?
-
> uses > PNGImage; // отличная библиотека, советую поискать
Поискал в поисковике... Часть ссылок дохлая, а остальные не устанавливаются в мою Делфи 7...
Где-нибудь есть офф.сайт у него (а то может мне просто какую-то фигню подсунули)? =))
-
-
> antonn © (07.08.09 00:01) [207] > у меня для линзы в бенчмарке маска, делал по примеру фастлиба :)
Переведи )) ...алгоритм посмотреть можно? ...ссылочку? ...я на откровенный гемор натыкаюсь с матрицами, или у тебя тоже так?
-
-
Правда это все таки не совсем линза, но похоже :)
-
Хорошо, спасибо, посмотрю.
-
Удалено модератором
-
Beermonza, а всегда нужно делать так: DCs:=GetDC(Form1.Handle);
BitBlt(DCs, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY);
ReleaseDC(Form1.Handle, DCs);
DeleteDC(DCs);
DCs:=GetDC(0);
BitBlt(DCs, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY);
ReleaseDC(0, DCs);
DeleteDC(DCs);
Я всегда так делал: BitBlt(Form1.Handle, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY); или так: BitBlt(.Canvas.Handle, 0, 0, W, H, GetDC(0), X, Y, SRCCOPY); Это хуже? А который ассемблер используется в Делфи? Tasm, Masm или какой-то свой? Я нигде не могу найти информацию по применению именно ассемблерных вставок для Делфи, а не просто по трансляторам... И не найдётся ли что-нибудь про этот MMX чтоб для начинающих было? Очень хочется разобраться в Ваших примерах... =) > очень важно, чтобы данные шли параллельно, тогда легко забирая > и обрабатывая по 8 байт скорость отрисовки увеличивается, > нежели при расчете 3-х байт текстуры и 1-го байта маски.Может "по 6 байт" или я чего-то не понял? =( А как может быть "прозрачным какой-то один цвет" я даже представить не могу... =)
-
> Может "по 6 байт" или я чего-то не понял? =(
там все равно выравнивание будет, до 4х байт, к тому же битмап может быть с альфаканалом и как раз 4 байта на пиксель - ARGB.
прозрачный цвет - transparentcolor, это св-во у TImage например :)
-
> antonn © (16.08.09 11:21) [214]
Да я про 202-й пост, предпоследний абзац (в самом конце)... =)
-
ну два пикселя разом, видимо :)
-
> CSS © (16.08.09 05:20) [213]> Beermonza, а всегда нужно делать так: > //на форму > DCs:=GetDC(Form1.Handle); > BitBlt(DCs, X, Y, W, H, {битмап}.Canvas.Handle, 0, 0, SRCCOPY); > ReleaseDC(Form1.Handle, DCs); > DeleteDC(DCs); Нет, не всегда. Это общее понятие о контексте формы и его использование. Нам нужен быстрый доступ, вот мы и получаем контекст устройства и храним его, зачем каждый раз делать одни и те же не нужные действия. Я беру контекст в OnCreate формы: DCs:=GetDC(Form1.Handle); ... освобождаю его в OnDestroy формы: ReleaseDC(Form1.Handle, DCs);
DeleteDC(DCs); ...сам BitBlt в конце процедуры построения кадра: BitBlt(DCs, X, Y, W, H, .Canvas.Handle, 0, 0, SRCCOPY); > CSS © (16.08.09 05:20) [213]> А который ассемблер используется в Делфи? Tasm, Masm или какой-то свой? > Я нигде не могу найти информацию по применению именно ассемблерных > вставок для Делфи, а не просто по трансляторам... > И не найдётся ли что-нибудь про этот MMX чтоб для начинающих было? > Очень хочется разобраться в Ваших примерах... =) Классический, Tasm не поддерживается. По MMX вот тут есть немного: http://www.gamedev.ru/code/articles/?id=4272Примеры не мои, они собраны по описаниям, оптимизированы из кусков, и помогали мне в "поисках правды", в свое время, хорошие люди, за что им спасибо. > CSS © (16.08.09 05:20) [213]> Может "по 6 байт" или я чего-то не понял? =( В MMX-технологии фишка в том, что процессор с ее поддержкой имеет 8 дополнительных 64-разрядных регистра, обычные регистры - 32-разрядные, ...т.е. мы можем ворочить сразу по 8 байт информации, вместо стандартных 4-й, ...от это значительный прирост производительности кода, при обработке параллельных массивов. Мы специально проверяем наши загруженные текстуры на предмет деления строки пикселей на 4, чтобы задать длину таким образом, чтобы было как можно меньше лишних байт, если длина окажется не четной, ...ведь работать нам с текстурами 24-битными - это по 3 байта на пиксел, альфа-канала тут нет, он отдельно. Давайте покажу структурно. Вот так идут данные в массиве PChar: это наши 8 пикселей изображения, тут 24 байта.BGR BGR BGR BGR BGR BGR BGR BGRа вот так берет эти же данные код на ассемблереBGRBGRBG RBGRBGRB GRBGRBGR - это текстура BGRBGRBG RBGRBGRB GRBGRBGR - это альфа-канал BGRBGRBG RBGRBGRB GRBGRBGR - это задний фон ...т.е. за 3 цикла он обработал по формуле смешивания 8 пикселей и наложил их на задний фон. Этот метод в 6 раз производительнее метода со сканированием ScanLine, судя по загрузке CPU. > CSS © (16.08.09 05:20) [213]> А как может быть "прозрачным какой-то один цвет" я даже представить > не могу... =) В FotoShop доводилось работать? ...в принципе это явление, когда в текстуре просвечивается только определенный тон, или все, или по выставленным уровням, эффект вычитания. Например, у вас есть текстура, полупрозрачная, значит в исходном варианте, например в PNG, 1 пиксел альфа-канала это 1 байт, ...а у нас альфа-канал - RGB, ...значит можно задать например врагмент текстуры с прозрачность не 100 100 100, а 50 100 100, в этом случае, фрагмент будет не только полупрозрачный, но и будет иной цвет прозрачности, т.е. этот альфа-канал просвечивает разные цвета по-разному. Если указать 0 100 100, то все красные тона не будет видно, а остальные останутся полупрозрачными, и т.д. и т.п. Разумеется, нужно подготавливать альфа-канал заранее, или как я показал, просто выдергивать его из PNG и разбрасывать на 3 составляющие, последующие эффекты в специальных кодах, матрицах, шаблонах, через которые пропускается массив альфа-канала.
-
Извините, увлекся, PhotoShop конечно же.
-
> Этот метод в 6 раз производительнее метода со сканированием > ScanLine, судя по загрузке CPU. >
это если последовательно перебирать строки, в случае с поворотами там разница раз в 20 будет точно :)
|