>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Gouraud shading
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Gouraudovo stínování je poněkud složitější než předešlé - hlavně
výpočtově, ale dá se v pohodě zvládnout tak, aby běžel real-time.
Stínované objekty vypadají mnohem realističtěji - plynulý přechod
barev - na hranách světlejší a směrem od zdroje světla intenzita
klesá. Prostě žůžo.
O co jde ???
Jak jsem tvrdil u Flat-shadingu, každý polygon má svůj normálový
vektor. A podle úhlu mezi normálem a vektorem světla se určí barva.
Dobře. Pro hranaté objekty to funguje zcela bezpečně. Jenže - co
když chceme, aby objekt vypadal zakulaceně ?
Kreslit to po malilinkatých polygůnkách je holá sebevražda.
Tak někoho chytrého napadlo - co kdyby se z normálových vektorů
sousedních stran udělal ARITMETICKÝM PRŮMĚREM normálový vektor,
právě společný pro tyto dvě (a samozřejmě i více) stran, a pak se
mezi těmito dvěma normály plynule přecházelo (tzn. Interpolovalo) ?
Matematicky je to sice nesmysl, protože bod nemůže mít normálový
vektor (zkuste to udělat :-) - ale funguje to a má to docela hezký
výsledek.
BTW: Někde jsem slyšel používat slovo pseudonormál pro normálový
vektor na bod ... tenhle pojem je docela výstižnej a líbí
se mi, takže ho budu používat.
Takže ... postup :
• spočítejte si normály ve všech vrcholech objektu
• pro všechny vrcholy (zní to hrozně) vyberte ze sousedních stěn
normály a sečtěte je - a vydělte počtem těch normálů (třeba u
krychle by to měly bejt 3) a dostanete pseudonormály.
Viz obrázek:
Interpolace pseudonormálů
• udělejte skalární součin tohohle vektoru (pseudonormálu) s
vektorem světla pro každý vrchol stěny
• tím vlastně získáte barvu, přesněji řečeno intenzitu - a pak
už jenom ...
"...interpolovat, interpolovat, interpolovat..."
(citát V.I. TiTania ;-))
Termín vlastní interpolace je vysvětlen o hodně níž ...
(Vlastní barva se vypočítá z intenzity násobené počtem barev, které
chceme tělesu "věnovat" a přičteme k tomu případné posunutí v
paletě.)
Vlastně musíte interpolovat mezi intenzitama ve vrcholech, a
následně když jedete po "scan-lajně" ... radši to nakreslim ...
Intepolace
Takže - aby bylo jasno - to červený je scanline - podél téhle čáry
interpolujeme ty intenzity. Vrcholy jsem nepopisoval, ale je snad
jasný, že kde je intenzita I1 je taky vrchol V1 a tudíž i souřadnice
X1 a Y1. OK ? A jak vypočítáme Ix a Iy ? A jak mezi nima
interpolovat ?
Není nic jednoduššího. Asi takhle (vzorce vysvětlím níže) :
Ix = (I4 - I1) / (Y4 - Y1) * (Yc-Y1) + Y1
Iy = (I3 - I2) / (Y3 - Y2) * (Yc-Y2) + Y2
... a interpolace mezi Ix a Iy
II = (Iy - Ix) / (XX2 - XX1) * (Xc-XX1) + XX1
kde II je intenzita bodu, Xc a Yc jeho souřadnice na obrazovce.
Jak jsem se k tomu dostal ? Logická úvaha : mám dvě intenzity, mezi
kterýma chci plynule přejít, znám počet těch přechodů, tudíž si
spočtu rozdíl mezi těma intenzitama, vydělim ho počtem přechodů
(rozdíl souřadnic) a potom mám dvě cesty :
a) počítám to podle předešlých rovnic, tzn. vynásobím tenhle "step"
(jak bych ho nazval) momentální souřadnicí zmenšenou o posunutí vůči
počátku souřadnic a pak znova přičtu to posunutí, ale to už k
hotovýmu výpočtu.
b) tenhle výpočet vyhodím ven z cyklu, nainicializuju si proměnnou
nazvanou třeba X_P a potom jenom při každém průběhu cyklu přičítám
hodnotu "step" ...
Pseudokód by mohl vypadat takhle :
for (Yc = ? ; Yc<= ?; Yc++ )
{
...
step = (Iy - Ix) / (XX2 - XX1) ;
for (Xc= XX1; Xc <= XX2 ; Xc++)
{
X_P += step;
Putpixel(Xc,Yc,(X_P*škála)+barevný_posun);
}
...
}
Pozn: Nikdo nezakazuje použití fixed-point !!!
INTERPOLACE
^^^^^^^^^^^
Ohledně tohohle termínu je hodně dotazů. Zkusím tento přiblbý termín
vysvětlit - pak stejně zjistíte, že se jedná o tak triviální věc, že
si tak hrdý název nezaslouží...
Interpolace je (dalo by se říci) plynulý přechod od jedné hodnoty ke
druhé. Máme třeba pole s počáteční hodnotou A a koncovou B. Mezi
těmahle hodnotama jsou jakési "díry" - a právě ty chceme dopočítat
tak, abychom plynule přešli od hodnoty A k hodnotě B. Nakreslim :
čísla políček
+---+---+---+---+---+---+---+---+---+----+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
+---+---+---+---+---+---+---+---+---+----+
| A | ? | ? | ? | ? | ? | ? | ? | ? | B |
+---+---+---+---+---+---+---+---+---+----+
pole (vektor) od A do B a mezi tim interpolací počítané hodnoty
A jak že to spočítáme ? Jsou 2 způsoby :
1) Add = (B-A) / (počet_políček)
a do každého políčka dosadíme hodnotu předešlého + Add
(tzn. aritmetická posloupnost)
Tzn: 2 číslo bude A+Add
3 číslo bude A+Add+Add
...
2) Pole_číslo_X = (B-A)/(počet_políček) * (X) + A
Easy, no ?
Teď sem se do toho zamotal - takže ještě radši shrnu postup :
• výpočet normálů pro všechny vrcholy objektu
• vybrat normály, které jsou pro daný vrchol společné
• udělat z těchto normálů aritmetickým průměrem pseudonormály
• spočítat Intenzitu, tj. skalární součin mezi pseudonormálem a
vektorem světla
• interpolace Intenzity mezi vrcholy
• interpolace interpolované Intenzity podél scanline, výpočet
barvy (sakra - to je formulace - no prostě budete interpolovat
tu intenzitu, kterou ste získali interpolací Intenzity mezi
vrcholama - jasný ?)
• vykreslení bodu
výheň