2D Бампмэппинг ( Bumpmapping )

2D Бампмэппинг ( Bumpmapping ) 2D Бампмэппинг ( Bumpmapping ) Чтобы сделать правильный 2d бампмэппинг надо посчитать нормаль для каждого пиксела в bumpmap (карте высот) и для вычисления цвета каждого пиксела использовать угол между источником света и данной нормалью. Для бампмэппинга в нашем случае используется источник света, бесконечно близкий к освещаемой плоскости: координаты нормали nx и ny просто разность высот между соседними пикселaми в bumpmap по осям X и Y. Так как нормаль - просто вектор направления, и ее длина равна единице, то nz=1-sqrt(nx2 + ny2). 1. Заранее вычисляем интенсивность света (light map) по вышеприведенной формуле. (Световое пятно с максимальной интенсивностью в центре). Полагаем как обычно, что интенсивность зависит от n_z. Пусть размер таблички будет для удобства 256x256. 2. Подбирая из lightmap интенсивность по формуле: outvalue = lightmap[n_x+128][n_y+128] (если использовать нормали в диапазоне -128...+127) мы получим корректную картину освещения для бесконечно близкого источника. n_x = bumpmap[x+1][y] - bumpmap[x-1][y] n_y = bumpmap[x][y+1] - bumpmap[x][y-1] Конечный цвет определяется так: outvalue:=lightmap[(n_x-(lightx-currentx))][(n_y-(lighty-currenty))]. Также нужно проверить, находимся ли мы внутри диапазона lightmap. Вот пример:

Program Bumpy_Surface;
{Hичего не USES}
type Tscr=array[0..199,0..319] of byte;
  SegmentT = Array[0..65534] of byte;
  Virseg = ^SegmentT;
var
scr:Tscr absolute $A000:0000;
buf:Tscr;
 ilx,ily:integer;
 i,j,k,nx,ny,nz,rx,ry,x,y,lx,ly,x1,y1:integer;
 tx,ty,tz:real;
var segm,offs:integer;
 Segment : Virseg;
 litemap : word;
Procedure SetUpSegment(VAR segname:virseg;VAR add : word);
begin GetMem (Segname,65534); add := seg (Segname^); end;
Procedure wait; assembler;
asm mov dx,3DAh;
@l1:in al,dx;and al,08h;jnz @l1;
@l2:in al,dx;and al,08h;jz @l2;end;
Procedure SetMode (Mode:word);assembler; asm mov ax,Mode; int 10h end;
Procedure FillBox(x,y,w,h:integer; color:byte);
var i,j,k:integer;
begin for i:=y to y+h-1 do for j:=x to x+w-1 do buf[i,j]:=color; end;
Procedure Print(x,y:integer; s:string; xs,ys:integer; color:byte);
var i,j,k,c,px,py:integer; b:byte;
begin px:=x;py:=y; for k:=1 to length(s) do begin c:=ord(s[k]);
for i:=0 to 7
 do begin b:=mem[segm:offs+c*8+i]; for j:=0 to 7 do begin
if b shl j and 128<>0
  then FillBox(x,y,xs,ys,color); x:=x+xs; end;
x:=px; y:=y+ys; end; y:=py; px:=px+xs*8; x:=px; end;
end;
Procedure SetGradientPalette; var k,r,g,b:byte;
begin asm mov dx,03c8h; xor al,al;out dx,al;end;
r:=0; g:=0; for k:=0 to 255 do begin b:=(k*63 div 255);
{r:=b; g:=b;{} if k>200 then begin r:=r+1;g:=g+1;end;
asm mov dx,03c9h; mov al,r;out dx,al;
mov al,g;out dx,al; mov al,b;out dx,al end;
end;end;
Procedure Blur;
var i,j,k:integer;
begin for i:=0 to 199 do for j:=0 to 319 do
buf[i,j]:=(buf[i-1,j]+buf[i+1,j]+buf[i,j-1]+buf[i,j+1]) div 4;
end;
Procedure ASMBumpmapping;assembler;
asm
{few times faster ;) }
  mov ax, seg buf
  mov es,ax
  mov ax, offset buf
  mov bx,320*3
  add ax,bx
  mov di,ax
  mov si,bx
  mov dx,199
  sub dx,5
@1: mov cx,320
@2: xor bh,bh; xor ah,ah;
  mov al, es:[di+1]
  mov bl, es:[di-1]
  sub ax,bx
  sub ax,320; add ax,cx; add ax,lx; add ax,128;
  cmp ax,255; jc @ok1; mov ax,255; @ok1:
  push ax
  xor ah,ah;
  mov al, es:[di+320]
  mov bl, es:[di-320]
  sub ax,bx
  sub ax,197; add ax,dx; add ax,ly; add ax,128;
  cmp ax,255; jc @ok2; mov ax,255; @ok2:
  pop bx
  mov bh,bl; mov bl,al
  push es
  mov ax, litemap
  mov es,ax
  and bx,0FFFEh
  mov bx,[es:bx]
  mov ax, 0A000h
  mov es,ax
  mov [es:si],bx
  pop es
  inc di
  inc si
  loop @2
  dec dx;
  jnz @1
  mov ax,$0a000
  mov es,ax
  xor ax,ax
  mov [es:si-1],ax
end;{asm Bumpmaping}
Procedure Bumpmapping;
begin
{Bumpmapping}
for y:=0+3 to 199-3 do begin
for x:=0 to 319 do begin
nx:=buf[y+1,x]-buf[y-1,x];
ny:=buf[y,x+1]-buf[y,x-1];
nx:=nx-x+lx;
ny:=ny-y+ly;
nx:=nx+128;
ny:=ny+128;
if (nx<0) or (nx>255) then nx:=0;
if (ny<0) or (ny>255) then ny:=0;
scr[y,x]:=mem[litemap:nX+nY*256]; end;
end;{ Bumpmapping }
end;
BEGIN
{Достанем адрес знакогенератора}
asm
mov ax,$1130;
mov bh,03h;
int 10h;
mov segm,es;
mov offs,bp;
end;
{установим режим и палитру}
setmode($13); setgradientpalette;
{Cгенерируем световое пятно}
SetUpSegment(Segment,litemap);
for y:=0 to 255 do for x:=0 to 255 do begin
tX:=(x-128)/128.0;
tY:=(y-128)/128.0;
tZ:=1-sqrt(tX*tX+tY*tY);
if (tZ<0) then tZ:=0; mem[litemap:x+y*256]:=round(tz*254); end;
{ Очистим буфер }
fillchar(buf,64000,0);
{набросаем точек}
 for i:=0 to 10000 do fillbox(random(320),random(200),1,1,255);
{...и размоем их}
blur;
{Hапишем текст}
 print(60,65,'BUMPY',5,5,255);
 print(47,115,'SURFACE',4,4,255);
{...и опять размоем}
blur;blur;blur;
ilx:=5;ily:=5;
ly:=100;lx:=80;
REPEAT
{move(buf,scr,64000);}
 wait;
{Bumpmapping;}
ASMBumpmapping;
 lx:=lx+ilx;if (lx>320) or (lx<0) then ilx:=-ilx;
 ly:=ly+ily;if (ly>200) or (ly<0) then ily:=-ily;
UNTIL port[$60]=1;{ESC}
{сбросим буфер клавиатуры}
memw[$000:$041a]:=memw[$000:$041c];
setmode($3);
END.

http://algolist.manual.ru

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...