Programowanie w języku Delphi » Gotowce

Animowany Flat Bump Mapping

<html>
<body>

Cześć!



Nie znalazłem do tej pory w gotowcach programiku, który pozwalałby uzyskać efekt bumpmappingu.

Postanowiłem więc trochę posiedzieć i naprawić to niedopatrzenie. Zaczynamy:



Potrzebny nam będzie 8-bitowy obrazek. Tworzymy z niego mapę wysokości, przy czym kolor biały to punkt

najwyższy a kolor czarny - najniższy. Ponieważ obrazek jest 8-bitowy nasze wartości będą zawierać się w

przedziale 0-255.


  var
<BR>    pic_tab: Array [0..400,0..300] of Byte; // tablica wysokości obrazka
<BR>...
<BR>  //----- wczytujemy obrazek
<BR>  Pic:=TBitmap.Create;
<BR>  Pic.LoadFromFile('tex.bmp');
<BR>  Pic.PixelFormat:=pf8bit;
<BR>  //----- generujemy tablicę wysokości naszego obrazka
<BR>  for i:=0 to Pic.Height-1 do begin
<BR>    PPic:=Pic.ScanLine[i];
<BR>    for j:=0 to Pic.Width-1 do begin
<BR>      pic_tab[j,i]:=PPic[j];
<BR>    end;
<BR>  end;
<BR>  Pic.Free; // zwalniamy obrazek (nie będzie już potrzebny)




Potrzebne będzie także kółeczko które będzie symulowało światło padające na obrazek. Możemy je

narysować w jakimś programie graficznym i wygenegować mapę wysokości tak jak w przypadku obrazka ale

my posłużymy się faktem, że dla okręgu mamy zależność:

        r2=x2+y^2

teraz łatwo wyliczymy r. Wartość sq oznacza odległość danego punktu od środka koła.


<BR>  var
<BR>    kolo_tab: Array [0..256,0..256] of Byte;
<BR>  ...
<BR>  //----- generujemy kółeczko
<BR>  for i:=0 to 256 do begin
<BR>    for j:=0 to 256 do begin
<BR>      sq:=round(2*sqrt((i-128)*(i-128)+(j-128)*(j-128)));
<BR>      if sq&gt;255 then sq:=255;
<BR>      sq:=255-sq;
<BR>      kolo_tab[j,i]:=sq;
<BR>    end;
<BR>  end;




Teraz musimy naszym kółeczkiem poruszać. Skorzystamy z funkcji sin i cos:


<BR>  var
<BR>    lx,ly: array [0..2] of Integer;     //tablice dla 3 kółeczek
<BR>    ruchx,ruchy: array [0..2] of real;
<BR>    w,h: Integer;
<BR>  ...
<BR>  //----- zmienne do pola poruszania się kółeczek
<BR>  h:=bufor.Height div 2; // połowa wysokości obrazka
<BR>  w:=(bufor.Width div 2)*3; // połowa długości obrazka * 3 bity na pixel
<BR>  //----- obliczamy trasę ruchu naszych kółeczek
<BR>  ruchy[0]:=ruchy[0]+0.11; ruchx[0]:=ruchx[0]+0.15;
<BR>  lx[0]:=round(w*cos(ruchx[0]))+w;
<BR>  ly[0]:=round(h*sin(ruchy[0]))+h;




A teraz serce naszego programu - procedura rysująca nasz bumpmapping:


<BR>procedure TBumpForm.Bump(x,y: Array of Integer);
<BR>var
<BR>  i,j: Integer;
<BR>  tx,ty: Integer;
<BR>  kx,ky: Integer;
<BR>  r,g,b: Integer;
<BR>  P: PByteArray;
<BR>  iX: Integer;
<BR>begin
<BR>  for i:=0 to bufor.Height-1 do begin
<BR>    P:=bufor.ScanLine[i];
<BR>    j:= 0;
<BR>    repeat
<BR>      iX:=j div 3;
<BR>      r:=0; g:=0; b:=0;
<BR>      ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
<BR>      kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];
<BR>      //--------- kolor czerwony
<BR>      tx:=j-x[0];
<BR>      ty:=i-y[0];
<BR>      tx:=(tx+kx)div 3;
<BR>      ty:=ty+ky;
<BR>      if (abs(tx)&lt;128) and (abs(ty)&lt;128) then r:=kolo_tab[tx+128,ty+128];
<BR>      //--------- kolor zielony
<BR>      tx:=j-x[1];
<BR>      ty:=i-y[1];
<BR>      tx:=(tx+kx)div 3;
<BR>      ty:=ty+ky;
<BR>      if (abs(tx)&lt;128) and (abs(ty)&lt;128) then g:=kolo_tab[tx+128,ty+128];
<BR>      //--------- kolor niebieski
<BR>      tx:=j-x[2];
<BR>      ty:=i-y[2];
<BR>      tx:=(tx+kx)div 3;
<BR>      ty:=ty+ky;
<BR>      if (abs(tx)&lt;128) and (abs(ty)&lt;128) then b:=kolo_tab[tx+128,ty+128];
<BR>
<BR>      //--------- przypisanie poszczególnym bitom wartości r, g, b
<BR>      P[j]:=b;
<BR>      P[j+1]:=g;
<BR>      P[j+2]:=r;
<BR>    inc(j,3);
<BR>    until j &gt; (bufor.Width - 1)*3;
<BR>  end;
<BR>  //----- i rysujemy
<BR>  BumpForm.Canvas.StretchDraw(rect(0,0,BumpForm.ClientWidth,BumpForm.ClientHeight),bufor);
<BR>end;






Zastosowana tu jest prosta sztuczka. Mianowicie w każdym punkcie obrazka liczymy przyrosty na osi X i Y.


<BR>  ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
<BR>  kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];




Jeśli wzdłuż tych osi jest jakaś pochyłość to wyrażenia będą miały jakąś wartość dodatnią lub ujemną. Teraz

te przyrosty dodajemy do pozycji w tablicy kolo_tab.


<BR>  tx:=j-x[0];
<BR>  ty:=i-y[0];
<BR>  tx:=(tx+kx)div 3;
<BR>  ty:=ty+ky;
<BR>  if (abs(tx)&lt;128) and (abs(ty)&lt;128) then r:=kolo_tab[tx+128,ty+128];




I to już koniec. Pełny kod można zassać tutaj.

Gdyby ktoś miał jakieś uwagi lub pomysły bardzo proszę o komentaż.



Program powstał na bazie kursu C++ pana Wiktora Zychla ukazującego się w CD-Action.


</body>
</html>

8 komentarzy

The Structorr 2003-07-03 21:01

Faktycznie plik był uszkodzony (coś poszło nie tak przy uploadzie). Nowa wersja pod
http://4programmers.net/download.php?id=1015
Dodałem tam jeszcze możliwość sterowania światłem za pomocą myszy (trzeba kliknąć).

tomaszos 2003-07-03 18:29

Co to jest bumpmapping? jaki efekt

ZIOMBER 2003-07-03 14:14

efekt graficzny =]

luKLem 2003-07-03 14:06

Co to jest bumpmapping? :-|

ZIOMBER 2003-07-03 12:54

no te archiwum to raczej rar ale i tak sie nie otworzy :///////////////////

Dominik 2003-07-03 11:44

Fajnie, ale masz źle spakowane archiwum i nie da sie go otworzyć :(.

Drajwer 2003-07-03 09:49

albo sam pisales albo zerżnołeś .... 6

[dopisane]
< delphi > i </ delphi > twoim przyjacielem :)