Animowany Flat Bump Mapping
The Structorr
<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
pic_tab: Array [0..400,0..300] of Byte; // tablica wysokości obrazka
...
//----- wczytujemy obrazek
Pic:=TBitmap.Create;
Pic.LoadFromFile('tex.bmp');
Pic.PixelFormat:=pf8bit;
//----- generujemy tablicę wysokości naszego obrazka
for i:=0 to Pic.Height-1 do begin
PPic:=Pic.ScanLine[i];
for j:=0 to Pic.Width-1 do begin
pic_tab[j,i]:=PPic[j];
end;
end;
Pic.Free; // zwalniamy obrazek (nie będzie już potrzebny)</code>
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.
```
var
kolo_tab: Array [0..256,0..256] of Byte;
...
//----- generujemy kółeczko
for i:=0 to 256 do begin
for j:=0 to 256 do begin
sq:=round(2*sqrt((i-128)*(i-128)+(j-128)*(j-128)));
if sq>255 then sq:=255;
sq:=255-sq;
kolo_tab[j,i]:=sq;
end;
end;</code>
Teraz musimy naszym kółeczkiem poruszać. Skorzystamy z funkcji sin i cos:
```
var
lx,ly: array [0..2] of Integer; //tablice dla 3 kółeczek
ruchx,ruchy: array [0..2] of real;
w,h: Integer;
...
//----- zmienne do pola poruszania się kółeczek
h:=bufor.Height div 2; // połowa wysokości obrazka
w:=(bufor.Width div 2)*3; // połowa długości obrazka * 3 bity na pixel
//----- obliczamy trasę ruchu naszych kółeczek
ruchy[0]:=ruchy[0]+0.11; ruchx[0]:=ruchx[0]+0.15;
lx[0]:=round(w*cos(ruchx[0]))+w;
ly[0]:=round(h*sin(ruchy[0]))+h;</code>
A teraz serce naszego programu - procedura rysująca nasz bumpmapping:
```
procedure TBumpForm.Bump(x,y: Array of Integer);
var
i,j: Integer;
tx,ty: Integer;
kx,ky: Integer;
r,g,b: Integer;
P: PByteArray;
iX: Integer;
begin
for i:=0 to bufor.Height-1 do begin
P:=bufor.ScanLine[i];
j:= 0;
repeat
iX:=j div 3;
r:=0; g:=0; b:=0;
ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];
//--------- kolor czerwony
tx:=j-x[0];
ty:=i-y[0];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then r:=kolo_tab[tx+128,ty+128];
//--------- kolor zielony
tx:=j-x[1];
ty:=i-y[1];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then g:=kolo_tab[tx+128,ty+128];
//--------- kolor niebieski
tx:=j-x[2];
ty:=i-y[2];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then b:=kolo_tab[tx+128,ty+128];
//--------- przypisanie poszczególnym bitom wartości r, g, b
P[j]:=b;
P[j+1]:=g;
P[j+2]:=r;
inc(j,3);
until j > (bufor.Width - 1)*3;
end;
//----- i rysujemy
BumpForm.Canvas.StretchDraw(rect(0,0,BumpForm.ClientWidth,BumpForm.ClientHeight),bufor);
end;</code>
Zastosowana tu jest prosta sztuczka. Mianowicie w każdym punkcie obrazka liczymy przyrosty na osi X i Y.
```
ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];</code>
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.
```
tx:=j-x[0];
ty:=i-y[0];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then r:=kolo_tab[tx+128,ty+128];</code>
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>
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
pic_tab: Array [0..400,0..300] of Byte; // tablica wysokości obrazka
...
//----- wczytujemy obrazek
Pic:=TBitmap.Create;
Pic.LoadFromFile('tex.bmp');
Pic.PixelFormat:=pf8bit;
//----- generujemy tablicę wysokości naszego obrazka
for i:=0 to Pic.Height-1 do begin
PPic:=Pic.ScanLine[i];
for j:=0 to Pic.Width-1 do begin
pic_tab[j,i]:=PPic[j];
end;
end;
Pic.Free; // zwalniamy obrazek (nie będzie już potrzebny)</code>
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.
```
var
kolo_tab: Array [0..256,0..256] of Byte;
...
//----- generujemy kółeczko
for i:=0 to 256 do begin
for j:=0 to 256 do begin
sq:=round(2*sqrt((i-128)*(i-128)+(j-128)*(j-128)));
if sq>255 then sq:=255;
sq:=255-sq;
kolo_tab[j,i]:=sq;
end;
end;</code>
Teraz musimy naszym kółeczkiem poruszać. Skorzystamy z funkcji sin i cos:
```
var
lx,ly: array [0..2] of Integer; //tablice dla 3 kółeczek
ruchx,ruchy: array [0..2] of real;
w,h: Integer;
...
//----- zmienne do pola poruszania się kółeczek
h:=bufor.Height div 2; // połowa wysokości obrazka
w:=(bufor.Width div 2)*3; // połowa długości obrazka * 3 bity na pixel
//----- obliczamy trasę ruchu naszych kółeczek
ruchy[0]:=ruchy[0]+0.11; ruchx[0]:=ruchx[0]+0.15;
lx[0]:=round(w*cos(ruchx[0]))+w;
ly[0]:=round(h*sin(ruchy[0]))+h;</code>
A teraz serce naszego programu - procedura rysująca nasz bumpmapping:
```
procedure TBumpForm.Bump(x,y: Array of Integer);
var
i,j: Integer;
tx,ty: Integer;
kx,ky: Integer;
r,g,b: Integer;
P: PByteArray;
iX: Integer;
begin
for i:=0 to bufor.Height-1 do begin
P:=bufor.ScanLine[i];
j:= 0;
repeat
iX:=j div 3;
r:=0; g:=0; b:=0;
ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];
//--------- kolor czerwony
tx:=j-x[0];
ty:=i-y[0];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then r:=kolo_tab[tx+128,ty+128];
//--------- kolor zielony
tx:=j-x[1];
ty:=i-y[1];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then g:=kolo_tab[tx+128,ty+128];
//--------- kolor niebieski
tx:=j-x[2];
ty:=i-y[2];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then b:=kolo_tab[tx+128,ty+128];
//--------- przypisanie poszczególnym bitom wartości r, g, b
P[j]:=b;
P[j+1]:=g;
P[j+2]:=r;
inc(j,3);
until j > (bufor.Width - 1)*3;
end;
//----- i rysujemy
BumpForm.Canvas.StretchDraw(rect(0,0,BumpForm.ClientWidth,BumpForm.ClientHeight),bufor);
end;</code>
Zastosowana tu jest prosta sztuczka. Mianowicie w każdym punkcie obrazka liczymy przyrosty na osi X i Y.
```
ky:=Pic_tab[iX,(i-1)]-Pic_tab[iX,(i+1)];
kx:=Pic_tab[(iX-1),i]-Pic_tab[(iX+1),i];</code>
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.
```
tx:=j-x[0];
ty:=i-y[0];
tx:=(tx+kx)div 3;
ty:=ty+ky;
if (abs(tx)<128) and (abs(ty)<128) then r:=kolo_tab[tx+128,ty+128];</code>
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>
swietne :)
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ąć).
Co to jest bumpmapping? jaki efekt
efekt graficzny =]
Co to jest bumpmapping? :-|
no te archiwum to raczej rar ale i tak sie nie otworzy :///////////////////
Fajnie, ale masz źle spakowane archiwum i nie da sie go otworzyć :(.
albo sam pisales albo zerżnołeś .... 6
[dopisane]
< delphi > i </ delphi > twoim przyjacielem :)