Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вывода битмапа по маске и под углом [D7, XP]


Страницы:   1 2 3

Evgnevius ©   (2009-12-01 18:56:00) 

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


Sapersky   (2009-12-12 19:24:00) [1]

Evgnevius ©   (09.12.09 01:22) [37]

М-да, похоже, чукча катастрофически не читатель.
Ткну носом в фастлибовский код (вариант без сглаживания). Разницу с твоим в кол-ве операций замечаешь?

for y:=0 to Dst.Height-1 do begin
 dy:=cy-y;
 sdx:=(ax+(isin*dy))+xd;
 sdy:=(ay-(icos*dy))+yd;
 for x:=0 to Dst.Width-1 do begin
   dx:=sdx shr 16;
   dy:=sdy shr 16;
   if(dx<Src.Width)and(dy<Src.Height)then pc^:=Src.Pixels24[dy,dx];
   Inc(sdx,icos);
   Inc(sdy,isin);
   Inc(pc);
 end;
 pc:=Ptr(Integer(pc)+Dst.Gap);
end;

Теория, если коротко, такова:
1) Вращение - это аффинное преобразование, и сводится к операции умножения на матрицу (уже писали). Точнее, конкретно для вращения (+ пропорционального масштабирования) достаточно иметь два коэфф-та, синус-косинус, ну и смещение (ещё два числа).
2) Для поддержки масштабирования/сглаживания удобнее считать обратное преобразование, т.е. результирующая картинка считается неповёрнутой, а из исходной пиксели выбираются с поворотом.
3) Можно упростить формулу преобразования за счёт того, что последовательно считаются соседние по горизонтали пиксели, и в результате свести всё к двум сложениям на пиксель.
4) Желательно использовать fixed point (эмуляцию дробных чисел целыми), т.к. с плавающей точкой Round тормозит.

Хотя сотни FPS на высоких разрешениях результирующей картинки этот код может не потянуть (старичок P3-1200, 800*600, 8 бит: без сглаживания - 70 FPS, со сглаживанием - 40), но по сравнению с твоим - в десятки-сотни раз быстрее.

Видеокарта, конечно, повернёт быстрее, но там свои проблемы. Передача данных в видеопамять не мгновенна, а если понадобится в обратном направлении (для доп. обработки на CPU) - наверняка растеряешь на этом всё ускорение, разве что на самых последних картах оно не очень тормозит (GF GTS, возможно GF 8000-9000 серий). Как вариант - перенести вообще всю обработку картинок на видеокарту (шейдеры, GPGPU...). Но это, прямо скажем, непросто, а для каких-то специфических алгоритмов может быть вообще невозможно.


Рамиль_   (2009-12-12 16:28:00) [2]

GDI+ за глаза.
Почитайте книжку про компьютерную графику, будет намного легче.


Evgnevius   (2009-12-12 00:10:00) [3]

Ладно, ребят. Вижу, что все вы хотите мне помочь, однако, как я понял, специалисты по OpenGL на этот топик не заходили. Придётся исхитряться


Evgnevius   (2009-12-11 23:10:00) [4]

Несколько тысяч - это конечно многовато. Скорее - несколько сотен раз. А зачем - это уже зависит от поставленной задачи. Если хотите, можете поглядеть, на наше творчество 2-х летней давности, то, что мы сделали без использования OpenGL, чисто на ресурсах процессора.

www.ntlab.su


antonn   (2009-12-09 16:05:00) [5]

не стоит выкидывать процессор, он не так уж плох :)
если нужно выводить с последующим отображением на экране, то зачем делать это несколько тысяч раз?


Evgnevius   (2009-12-09 15:59:00) [6]

Рамиль, спасибо за ваше терпение. Я нажимал Ctrl и щёлкал. Кроме того, нажимал ещё и F1.
antonn, Если фастлиб не использует видеокарту, то спасибо. Процессор не хочу напрягать, так как пишу плагин, в котором на одном битмапе другой должен выводиться в разных пропорциях и с разными углами поворотов от нескольких сотен до нескольких тысяч раз. Координаты вывода для каждого битмапа должны пересчитываться динамически. Спасибо за предложенную помощь.


antonn   (2009-12-09 15:48:00) [7]


> Этот перебор и есть главный тормоз не смотря на то, что
> используется ScanLine.

попробуй фастлиб


Рамиль   (2009-12-09 15:28:00) [8]


> а что такое xForm?

Матрица аффинного преобразования (в виде рекорда).     XFORM = record
         eM11 : Single;
         eM12 : Single;
         eM21 : Single;
         eM22 : Single;
         eDx : Single;
         eDy : Single;
      end;
    LPXFORM = ^XFORM;
    _XFORM = XFORM;
    TXFORM = XFORM;
    PXFORM = ^XFORM;

   
Трудно нажать Ctrl и щелкнуть?


Evgnevius   (2009-12-09 14:31:00) [9]

а что такое xForm?


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

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

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


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

Такой скорости не хватит?
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;                        


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

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


antonn   (2009-12-02 21:04:00) [13]

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


antonn   (2009-12-02 21:01:00) [14]


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

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

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


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

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


antonn   (2009-12-02 19:38:00) [16]

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


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

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

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


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

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

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

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

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


antonn   (2009-12-02 17:34:00) [19]


> Sapersky   (02.12.09 17:29) [28]

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


antonn   (2009-12-02 17:33:00) [20]


> Sapersky   (02.12.09 17:29) [28]

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


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо