>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 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ň