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

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

Как правильно нарисовать дым? [D6, Win2k]


Sour Smile ©   (2006-02-22 20:16:00) 

Задний план (фон) представляет собой весьма тёмное (подвальное) помещение в виде кирпичной кладки, с еле различимыми стыками между кирпичами.

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

Клуб дыма - это квадратный, 32-битный bmp-спрайт. Спрайт дыма полностью белый (все цветовые компоненты R,G,B всех пикселей=255), а альфа-компонент в форме овала (в средине спрайта альфа=255, постепенно уменьшаясь к краям на ноль).

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

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

Выходит, что я неправильно накладываю дым на фон...
А как это сделать правильно?


antonn   (2006-02-28 07:09:00) [1]

Gorger ©   (28.02.06 4:29) [4]
Антон, простите, но Ваша либа уступает LibPNG.

определенно. Хотя бы тем, что не поддерживает png, имеет код, насыщеный проверками, и, соотвественно, хромающей производительностью:)
но одно но, мой код не тащит за собой библиотеку, и для рисования 32х битных битмапов его хватает:)


Gorger   (2006-02-28 04:29:00) [2]

Юзайте либу LibPNG. Антон, простите, но Ваша либа уступает LibPNG.


antonn   (2006-02-23 17:53:00) [3]

Sour Smile   (23.02.06 17:23) [2]
Аргумент Alfa2 я как раз и ввёл для эффекта растворения.

хы-хы, _dd:= 100/(255*100); не просто так, у меня через такое чудо общая прозрачность наложения высчитывалась. жирным отмечено процентная видимость, т.е. при 0 ничего не увидишь. Думаю, это было нужно? :)


Sour Smile   (2006-02-23 17:23:00) [4]

Привет antonn :)

Спрайт дыма я вывожу с помощью твоей же, слегка модифицированной процедуры:

procedureCopyBitmapAlfa(_B_in, _B_out: TBitmap; _x ,_y: Integer; Alfa2: Integer = 255);
const
 MaxPixelCountA = MaxInt divSizeOf(TRGBQuad);
 MaxPixelCount = MaxInt divSizeOf(TRGBTriple);
type
 PRGBArray = ^TRGBArray;
 TRGBArray = array[0..MaxPixelCount-1] ofTRGBTriple;
 PRGBAArray = ^TRGBAArray;
 TRGBAArray = array[0..MaxPixelCountA-1] ofTRGBQuad;
var
 x, y: Integer;
 _r, _b, _g, _Alfa: Integer;
 w_in, h_in, w_out, h_out, tmp, x_cor, y_cor, x_corS, y_corS: Integer;
 RowOut: PRGBArray;
 RowIn: PRGBAArray;
 _d, _dd: double;

begin
  case_B_in.PixelFormat of
   pf24bit:
    begin
     _B_out.Canvas.CopyRect(Rect(_x, _y, _B_in.Width+_x, _B_in.Height+_y), _B_in.Canvas, _B_in.Canvas.ClipRect);
    end;
   pf32bit:
    begin
     w_in:=_B_in.Width;
     h_in:=_B_in.Height;
     w_out:=_B_out.Width;
     h_out:=_B_out.Height;
      if(_x)>w_out-1 thenexit; if(_x+w_out)<0 thenexit;
      if(_y)>h_out-1 thenexit; if(_y+h_out)<0 thenexit;

      if_x<0 thenx_corS:=abs(_x) elsex_corS:=0;
      if_y<0 theny_corS:=abs(_y) elsey_corS:=0;
      if(_x+w_in)>w_out thenx_cor:=_x+w_in-w_out elsex_cor:=0;
      if(_y+h_in)>h_out theny_cor:=_y+h_in-h_out elsey_cor:=0;

     y_cor:=h_in-1-y_cor;
     tmp:=w_in-1-x_cor; _dd:=100/(255*100);
      fory:=y_corS toy_cor do
      begin
       RowOut:= _B_out.ScanLine[y+_y];
       RowIn:= _B_in.ScanLine[y];
        forx:=x_corS totmp do
        begin
         _Alfa:=RowIn[x].rgbReserved+Alfa2-255;
          if_Alfa>=255 then
          begin
           RowOut[x+_x].rgbtRed   := RowIn[x].rgbRed;
           RowOut[x+_x].rgbtGreen := RowIn[x].rgbGreen;
           RowOut[x+_x].rgbtBlue  := RowIn[x].rgbBlue;
          end else
          if_Alfa>0 then
          begin
           _d:=_Alfa*_dd;

           _r:= trunc(RowOut[x+_x].rgbtRed+(RowIn[x].rgbRed-RowOut[x+_x].rgbtRed)*_d);
            if_r>255 then_r:=255 else if_r<0 then_r:=0;

           _g:= trunc(RowOut[x+_x].rgbtGreen+(RowIn[x].rgbGreen-RowOut[x+_x].rgbtGreen)*_d);
            if_g>255 then_g:=255 else if_g<0 then_g:=0;

           _b:= trunc(RowOut[x+_x].rgbtBlue+(RowIn[x].rgbBlue-RowOut[x+_x].rgbtBlue)*_d);
            if_b>255 then_b:=255 else if_b<0 then_b:=0;

           RowOut[x+_x].rgbtRed:=_r;
           RowOut[x+_x].rgbtGreen:=_g;
           RowOut[x+_x].rgbtBlue:=_b;
          end;
        end;
      end;
    end;
  end;
end;


Аргумент Alfa2 я как раз и ввёл для эффекта растворения.


> antonn ©   (22.02.06 21:16) [1]
>
> и основной цвет дыма можно сделать не белым, а серым, а
> альфаканал немного высветлить.

Высветлять больше некуда, в центре спрайта дыма (в месте наибольшего скопления) альфа=255


antonn   (2006-02-22 21:16:00) [5]

я так понял, что на кирпичную кладку "наносится белая текстура".
какая формула вычисления цвета пикселя?
должна быть такая, примерно (для одного канала из RGB):
кирпич:=кирпич+trunc((дым-кирпич)*(альфаканал_дыма/255));
и основной цвет дыма можно сделать не белым, а серым, а альфаканал немного высветлить.


Наверх

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