Форум: "Начинающим";
Текущий архив: 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