Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2010.02.07;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.59 MB
Время: 0.007 c
15-1259997701
begin_flasher
2009-12-05 10:21
2010.02.07
Shockwave Flash


4-1228802818
DimonS
2008-12-09 09:06
2010.02.07
Как реализовать чтение iButton?


1-1236164057
dmitry1208197320
2009-03-04 13:54
2010.02.07
Управление размерами картинки при её вставке в Word


15-1259647471
Serhio
2009-12-01 09:04
2010.02.07
Delphi. Проблемы с ведением лога в xls файле


2-1260482915
Aleks
2009-12-11 01:08
2010.02.07
динамически создаваемые объекты как их удалить?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский