Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.02.07;
Скачать: CL | DM;

Вниз

Вывода битмапа по маске и под углом   Найти похожие ветки 

 
Evgnevius ©   (2009-12-01 18:56) [0]

Подскажите, пожалуйста, как это делать, а то OpenGL для меня - тёмный лес, однако нужно именно с её помощью, так как очень важна скорость. С помощью средств GDI всё у меня получается прекрасно, однако тормозит. Помогите, кто знает как.


 
Evgnevius ©   (2009-12-01 20:39) [1]

Само наличие маски не обязательно, хотя создать чёрно-белую маску с градиентом для меня не проблема - главное, чтобы часть точек битмапа выводилась с заданной прозрачностью по отношению к фону.


 
antonn ©   (2009-12-01 21:29) [2]


> С помощью средств GDI всё у меня получается прекрасно, однако
> тормозит.

покажи код


 
Evgnevius ©   (2009-12-01 22:28) [3]

procedure DrawBar(Bmp: PBmp; Cols: CL_TColConstruction; XC, YC, Side: Integer; Angle: Extended); stdcall;
var
 I, J, W2, X, Y, K, L, XI, YJ: Integer;
 Poz, Len: Int64;
 Tmp: TBmp;
begin
 Tmp := TBmp.Create;
 Tmp.Assign(Bmp^);
 with Bmp^ do              
   begin
   K := 2;
   Side := Side * K;
   XC := XC * K;
   YC := YC * K;
   Len := Side * K * 10;
   W2 := Side div 2;
   L := Length(Cols) - 1;
   for I := 0 to Side do
     for J := 0 to Side do
       begin
       CL_RotateXY(X, Y, I + XC - W2, J + YC - W2, XC, YC, Angle);
       case CL_GetSector(Pi / 4, W2, W2, I, J, 4) of
         2, 4: Poz := 40 * Abs(W2 - I);
         1, 3: Poz := 40 * Abs(W2 - J);
       end;
       XI := X div K;
       YJ := Y div K;
       Cols[L].Color := PComp_GetPixel(@Tmp, XI, YJ);
       PComp_PutPixel(Bmp, XI, YJ, SimpleLinear(Cols, Len, Poz));
       end;
   end;
   Tmp.Free;
end;


 
Andy BitOff ©   (2009-12-01 22:28) [4]

> antonn ©   (01.12.09 21:29) [2]

=)


> Evgnevius ©   (01.12.09 18:56) [0]

Ага, покажи.


 
Evgnevius ©   (2009-12-01 22:34) [5]

А вот ниже я привёл специфические функции, использованные в приведённой выше процедуре

type
 CL_TColStructure = record
   Color: TColor;
   ColPart, GradPart: Real;
 end;
 CL_TColConstruction = array of CL_TColStructure;

procedure CL_RotateXY(var NewX, NewY: Integer;  X, Y, X0, Y0: Integer; Angle: Real; R: Real = -1); stdcall;
var
 A: Real;
begin
 if R = -1 then R := Sqrt(Sqr(X - X0) + Sqr(Y - Y0));
 if R <> 0 then
   begin
   A := ArcCos((X - X0) / R);
   if Y > Y0 then
     A := 2 * Pi - A;
   A := A + Angle;
   NewX := Round(X0 + R * Cos(A));
   NewY := Round(Y0 + R * Sin(A));
   end;
end;

var
 A, A1, R: Extended;
function CL_GetSector(A0, CX, CY, X, Y: Extended; S: Word): Integer; stdcall;
begin
 CL_DecartToPhase_E(A, R, CX, CY, X, Y);
 A1 := A - A0;
 if A1 >= 0 then A1 := A1 - Trunc(A1 / TwoPi) * TwoPi else A1 := A1 - (Trunc(A1 / TwoPi) - 1) * TwoPi;
 Result := Trunc(A1 * S / TwoPi) + 1;
end;

function SimpleLinear(Cols: CL_TColConstruction; Len, Poz: Int64): TColor; stdcall;
var
 L, N, P, TS: Integer;
 S: Extended;
begin
 L := Length(Cols);
 S := Len / (L - 1);
 if Poz > Len then Poz := Len;
 N := Trunc(Poz / S);
 P := Round(Poz - N * S);
 TS := Trunc(S);
 if P > TS then P := TS;
 Result := Linear(Cols[N].Color, Cols[N + 1].Color, TS, P);
end;

function Linear(BC, EC: TColor; Len, Poz: Int64): TColor; stdcall;
begin
 if Len = 0 then
   begin
   Result := BC;
   Exit;
   end;
 if Poz < 0 then
   begin
   Result := BC;
   Exit;
   end else
 if Poz > Len then
     begin
     Result := EC;
     Exit;
     end;
 CL_GetRGB(BC, R1, G1, B1);
 CL_GetRGB(EC, R2, G2, B2);
 Rh := ((R2 - R1) * Poz) div Len;
 Gh := ((G2 - G1) * Poz) div Len;
 Bh := ((B2 - B1) * Poz) div Len;
 R := R1 + Rh;
 B := B1 + Bh;
 G := G1 + Gh;
 Result := RGB(R, G, B);
end;


 
Evgnevius ©   (2009-12-01 22:36) [6]

а, и вот ещё:

procedure CL_DecartToPhase_E(var Angle, Radius: Extended; X0, Y0, X, Y: Extended); stdcall;
begin
 Radius := Sqrt(Sqr(X - X0) + Sqr(Y - Y0));
 if Radius <> 0 then Angle := ArcCos((X - X0) / Radius) else
   begin
   Angle := 0;
   Exit;
   end;
 if Y <= Y0 then Angle := 2 * Pi - Angle;
end;


 
Andy BitOff ©   (2009-12-01 22:37) [7]

А это - PComp_GetPixel, PComp_PutPixel


 
Evgnevius ©   (2009-12-01 22:39) [8]

вместо них используйте Bmp.Canvas.Pixels[X, Y]


 
Evgnevius ©   (2009-12-01 22:40) [9]

procedure CL_GetRGB(C: TColor; var R, G, B: Integer); stdcall;
begin
 if C > $FFFFFF then C := $FFFFFF;
 if C < 0 then C := 0;
 R := GetRValue(C);
 G := GetGValue(C);
 B := GetBValue(C);
end;


 
Andy BitOff ©   (2009-12-01 22:43) [10]

> Evgnevius ©   (01.12.09 22:39) [8]

Вот в этом и проблема. Сейчас тебе antonn © расскажет как надо работать с пикселями. От себя могу посоветовать http://www.delphimaster.ru/articles/pixels/


 
Andy BitOff ©   (2009-12-01 22:44) [11]

А в целом для задачи я бы взял GDI+


 
Evgnevius ©   (2009-12-01 22:45) [12]

не спасибо, с пикселями у нас всё впорядке - PComp_GetPixel и PComp_PutPixel написаны на основе ScanLine
А мне нужно именно на OpenGL


 
Evgnevius ©   (2009-12-01 22:51) [13]

Скорость очень важна - доли секунды - это много
Прорисовка вообще не имеет значения, самое медленное здесь - это математические операции, выполняемые с помощью ЦП, а не ГП


 
Sapersky   (2009-12-01 23:04) [14]

Потенциально на софтвере можно получить такую скорость:
http://sapersky.narod.ru/files/FastLIBv389i.rar (пример Rotozoom)
Там, правда, 8 бит, 24 (есть в FastFX.Rotate) будет раза в 2-3 медленнее. Ещё на скорость влияет использование сглаживания и размер результирующей (исходной в меньшей степени) картинки.
Насчёт "маски" не вполне понял, то ли фиксированная альфа нужна, то ли альфа-канал. Ну это тоже можно прикрутить.


 
antonn ©   (2009-12-01 23:40) [15]

Ниче не покажу, если надо на ОГЛ :) сбило с толку "битмап". ОГЛ ведь в окно рендерит (хоть и можно снять с dc скриншот).
можно попробывать софтваре сообразить, но было бы лучше скинуть тестовый проект с уже наработанным, дабы посравнивать - а есть ли смысл.


 
Evgnevius ©   (2009-12-02 00:02) [16]

Я мне нужно на контекст OpenGL выводить битмап с использованиаем маски прозрачности и под углом


 
Sapersky   (2009-12-02 00:36) [17]

Книга Краснова по OGL:
http://d3dengine.narod.ru/books.html


 
Evgnevius ©   (2009-12-02 13:26) [18]

Sapersky, спасибо. У меня есть эта книга... Но толку от этого мало.


 
RWolf ©   (2009-12-02 14:25) [19]

Приемлемый FPS для случая вращения картинки умеренного размера можно получить и без применения OpenGL.
Если, конечно, не считать синусы с косинусами для каждой точки, как в приведённом коде.


 
Evgnevius ©   (2009-12-02 15:02) [20]

Попробую поянить подробнее. В общем, мне нужно создать битмап и вывести его так, чтобы его края не были в виде лесенки при поворотах. Поэтому нужно просто сглаживать края, а это можно сделать, если использовать маску вывода (хоть альфа-канал, хоть как его назови). Картинка должна меняться в реальном времени, поэтому важна скорость.


 
Evgnevius ©   (2009-12-02 15:07) [21]

RWolf, Синусы и арксинусы нужны для поворота каждой точки. Так что, изходя из написанного мной и, вообще, поставленной задачей, выход один - это увеличение скорости построения изображения, а для этого есть только один способ: использовать возможности видеокарты. А то, что я тут выложил - это просто жёсткий напряг для центрального процессора.


 
RWolf ©   (2009-12-02 15:12) [22]


> Синусы и арксинусы нужны для поворота каждой точки.

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


 
Evgnevius ©   (2009-12-02 15:43) [23]

Углы одинаковые, а координаты разные, поэтому, изходя из заданного угла разсчитываются координаты для каждой точки выводимого изображения


 
RWolf ©   (2009-12-02 16:21) [24]

но синусы-то зачем при этом пересчитывать?
угол поворота изображения — константа.


 
Рамиль ©   (2009-12-02 16:33) [25]

Если уж на то пошло, угол можно выставить API SetWorldTransform, зачем изобретать велосипед?

> Углы одинаковые, а координаты разные, поэтому, изходя из
> заданного угла разсчитываются координаты для каждой точки
> выводимого изображения

Поворот выполняется умножением вектора на заранее просчитанную матрицу.
http://www.compgraphics.info/2D/affine_transform.php

P. S. Непоколебима тяга людей к изобретению велосипедов :)


 
Sapersky   (2009-12-02 17:23) [26]

А то, что я тут выложил - это просто жёсткий напряг для центрального процессора.

Это крайне нерациональное использование мощностей ЦП.
Я [14] для кого писал?

У меня есть эта книга... Но толку от этого мало.

То, что тебе нужно, называется "наложение текстуры". В разделе "спецэффекты", вроде.


 
antonn ©   (2009-12-02 17:24) [27]


> Попробую поянить подробнее. В общем, мне нужно создать битмап
> и вывести его так, чтобы его края не были в виде лесенки
> при поворотах. Поэтому нужно просто сглаживать края, а это
> можно сделать, если использовать маску вывода (хоть альфа-
> канал, хоть как его назови). Картинка должна меняться в
> реальном времени, поэтому важна скорость.

Маска тут не совсем нужна. Я увеличиваю изображение в 2/3/4 раза, поворачиваю его, а потом уменьшаю в 2/3/4 раза (выбирая средний цвет из "кубиков" 2*2 пикселей (3*3/4*4)), получается с антиалиасингом (суперсемплинг типа :)), в том числе и альфаканал "плавно" уменьшается, и по нему уже рисую.
в ОГЛ ведь есть свои инструменты для поворотов.


 
Sapersky   (2009-12-02 17:29) [28]

Можно без увеличения/уменьшения. Я уже объяснял здесь:
http://delphimaster.net/view/18-1231614795/


 
antonn ©   (2009-12-02 17:33) [29]


> Sapersky   (02.12.09 17:29) [28]

а оно точно даст такой же результат как и при повороте и уменьшении? :)


 
antonn ©   (2009-12-02 17:34) [30]


> Sapersky   (02.12.09 17:29) [28]

просто интересно, можешь собрать примерный проект, даже через canvas.pixels[]?


 
Sapersky   (2009-12-02 19:05) [31]

а оно точно даст такой же результат как и при повороте и уменьшении? :)

Полагаю, близкий к увеличению/уменьшению в 2 раза. Алгоритм фактически тот же самый - результирующий пиксель определяется 4-мя исходными.
Кстати, "железо" работает именно так. Ещё мипмэппинг/трилинейка используется при сильном уменьшении (анизотропка только для наклонных поверхностей).

можешь собрать примерный проект, даже через canvas.pixels[]?

Ну ты обленился... у тебя же есть свои функции вращения, всего-то дел - прикрутить к ним код интерполяции из той ветки. Хотя с т.з. производительности рекомендуется fixed point, как в фастлибе.


 
antonn ©   (2009-12-02 19:17) [32]

понял почему оно мне казалось "не то":
я увеличиваю поворачиваемый битмап, и увеличиваю бекграунд куда он ляжет, поворачиваю битмап, рисую его на увеличенном буфере бекграунда, уменьшаю этот бутерброд, и бличу обратно. Таким образом при повороте в месте границ спрайта он смешается с фоном, у тебя в формуле нет смешений с бекграундом. И вот тут вопрос будет, про который мне лень думать :)
[B][S]
[S][S]

допустим в кубик пикселей попадет пиксель бекграунда, как выше. Тогда результирующий цвет пикселя будет ([B]+[S]+[S]+[S])/4, а в твоем примере получается ([S]+[S]+[S]+[S_clear])/4? ([S_clear] - это часть спрайта за его границей - с нулевой альфой например. Собсно из-за этого я и бличу большой увеличенный спрайт на большой бекграунд, иначе при уменьшении будет суммироваться "прозрачная" область спрайта, из-за этого будет кайма)


 
antonn ©   (2009-12-02 19:38) [33]

вот что я имел ввиду: http://desksoft.ru/index.php?downloads=attachments&id=243


 
Sapersky   (2009-12-02 20:41) [34]

Проверил на Фастлибе - действительно кайма получается. Хотя мне казалось, что не должна - альфа у краевых пикселей тоже уменьшается вместе с RGB, но видимо недостаточно уменьшается.
Спрайты с плавными границами (иконки Висты) рисуются нормально.
Интересно, есть ли подобные проблемы у "железных" игровиков. Мне кажется - должны быть, так что можно у них поспрашивать.
Вот, например, в текстуре с персонажем из конкурса Battle альфа по краям в основном размытая.


 
antonn ©   (2009-12-02 21:01) [35]


> альфа у краевых пикселей тоже уменьшается вместе с RGB,
> но видимо недостаточно уменьшается.

дело не в альфе, каналы RGB все равно обсчитываются с "прозрачным" цветом на спрайте, а альфа отдельно. Можно, конечно, добавить в твой код умножение канала на альфу - но тогда будет зачернение. При выводе может сразу не будет заметно, но потом может помешать.

Я не разбирал работу железного поворота, но думал что они работают по тому же принципу, ведь если просто поворачивать спрайт, а потом рисовать - кайму бы завно заметили :) вообще это решается тем, что видимые каналы "протягиваются" в стороны, как вот тут: http://desksoft.ru/index.php?downloads=attachments&id=244 , тогда привращении все должно быть пучком :)


 
antonn ©   (2009-12-02 21:04) [36]

зато получается "бесплатный" cel-шейдинг, если спрайт на черном фоне %)


 
Evgnevius ©   (2009-12-09 01:22) [37]

Косинусы можно не пересчитывать? А сканирование пикселей битмапа у меня что - по углам должно проходить? Я в массиве перебираю все пиксели, битмапа, узнаю фазовые координаты относительно центра вращения для каждой точки, а затем осуществляю поворот путём увеличения угла на заданный. После этого по вновь полученным фазовым координатам, я получаю декартовы. Скорость приемлема для одноразового построения битмапа, но не для моей задачи. Для меня скорость в полсекунды - с лишком много. Мне хотя бы 0.1 с. Вот и ищу помощь у видеокарты. А про матрицы поворота - спасибо, но они не помогут. Также придётся перебирать каждую точку... Этот перебор и есть главный тормоз не смотря на то, что используется ScanLine.


 
Рамиль ©   (2009-12-09 13:08) [38]

Такой скорости не хватит?
procedure TForm1.FormCreate(Sender: TObject);
 X: xForm;
 Alpha, IncAlpha: double;
 bm: Graphics.TBitmap;    

...

begin
 Alpha:=0;
 IncAlpha:=2*Pi/365;
 bm := Graphics.TBitmap.Create;
 bm.LoadFromFile("c:\lazarus\projects\test.bmp");
 X.eDx:= Self.Width / 2;
 X.eDy:= Self.Height / 2;
 SetGraphicsMode(Self.Canvas.Handle, GM_ADVANCED);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 X.eM11:=cos(Alpha);
 X.eM12:=sin(Alpha);
 X.eM21:=-sin(Alpha);
 X.eM22:=cos(Alpha);
 SetWorldTransform(Self.Canvas.Handle, X);
 Self.Canvas.Draw(-bm.Width div 2 , -bm.Height div 2, bm);
 Alpha := Alpha + IncAlpha;

end;                        


 
Рамиль ©   (2009-12-09 13:10) [39]

X: xForm;
Alpha, IncAlpha: double;
bm: Graphics.TBitmap;  

не туда вставил, надеюсь, понятно, что это поля формы или глобальные переменные.


 
Evgnevius ©   (2009-12-09 14:31) [40]

а что такое xForm?



Страницы: 1 2 вся ветка

Текущий архив: 2010.02.07;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.012 c
4-1228799718
Skyle
2008-12-09 08:15
2010.02.07
Непонятки с USB сканером с эмуляцией COM. Не работает RXFLAG.


1-1236890859
Tatarin
2009-03-12 23:47
2010.02.07
Спецсимволы HTML


15-1259840977
Insor
2009-12-03 14:49
2010.02.07
Чем составлен данный дамп БД?


2-1260419453
novai
2009-12-10 07:30
2010.02.07
Парсер строки


11-1211311083
Vinum
2008-05-20 23:18
2010.02.07
Крутим колесико над PaintBox