![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно нарисовать дым? [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));
и основной цвет дыма можно сделать не белым, а серым, а альфаканал немного высветлить.