Egenskygge og glatting
Gouraud
OpenGL benytter Gouraudshading [1] . Utgangspunktet er at vi har beregnet intensiteten i alle hjørner i et polygon. Med intensitet mener vi hvilken styrke som skal tillegges den røde, blå og grønne lyskomponenten i det aktuelle punktet. Dette vet vi at vi gjør ved å angi normaler i hjørnene, f.eks. slik:
glBegin(GL_TRIANGLE_STRIP); for(ix=0;ix< N ix++) { glNormal3f(..); glVertex3f(..); } glEnd();
Hvis vi konsentrerer oss om en av de trekantene som dannes, vil OpenGL på grunnlag av de lyskildene som er angitt, materialegenskapene, normalene og hjørnene beregne intensiteten i hvert av hjørnene. Gouraud shading er å finne en måte å beregne intensiteten i et vilket som helst punkt i trekanten basert på verdien i hjørnene.
Dette gjøres ved interpolasjon: Ia er resultatet av en interpolering mellom I1 og I2, og Ib er resultatet av en interpolering mellom I2 og I3.
Vi tenker oss at flaten genereres linje for linje og intensiteten i hvert punkt langs linja beregnes etter resonnementet nedenfor:
Beregningen kan effektiviseres i praksis ved å gå nærmere inn på beregningene fra en linje til den neste.
De to kulene nedenfor illustrerer forskjellen på en en flat skygge og en glatt (gouraud) flate.
På kula til venstre er hver flate for seg beregnet med en konstant, flat intensitet. Legg merke til en effekt som skyldes øyet: Macband-effekten. Det ser ut som om skillet mellom flatene står ut. Dette skyldes at øyet forsterker forskjellen mellom naboflater.
Vi kan skru av og på Gouraudshading i OpenGL:
/* on */ glShadeModel(GL_SMOOTH); /* off */ glShadeModel(GL_FLAT);
Glatting over flere flater oppnår vi ved at en rekke av tegnekommandoene i OpenGL lager sammensatte flater og at en normal som oppgis i et hjørne anvendes i alle de flatene som deler dette hjørnet. F.eks.:
glBegin(< mode >); for(ix=0;ix< N ix++) { glNormal3f(..); glVertex3f(..); } glEnd();
Der mode blant annet kan ha følgende verdier og effekter:
Hvis vi analyserer dette nærmere, kan vi se for oss to måter å angi normaler på. Vi tar som utgangspunkt at vi ønsker å framstille en "rundet", glatt overflate ved hjelp av flater (F1,F2,F3,F4).
Vi kan ta normalen i hver flate og bruke normalene fra flate n-1 og n som en normaler i flate n. Dersom vi har små flater og/eller svak krumming vil dette gi god glattingseffekt. | |
Vi kan bruke normaler som er gjennomsnitt av flatenormalene i et fellespunkt mellom grenseflater. Dette er tydelig en bedre strategi. En strategi for å implementere dette tilskrives Newell. Du kan søke etter denne i litteraturen. |
Skjøting
Når vi har skrudd på glatting med
glShadeModel(GL_SMOOTH);
og bruker f.eks.:
glBegin(GL_TRIANGLE_STRIP); for(ix=0;ix< N ix++) { glNormal3f(..); glVertex3f(..); } glEnd();
tar OpenGL seg av glattingen over de flatene som skapes mellom glBegin og glEnd. Ofte er vi i den situasjonen at vi må bruke flere slike glBegin - glEnd konstruksjoner for å skape en sammenhengende flate. Hvis vi ønsker at denne samlede flaten skal glattes, må vi selv ta ansvaret for å skjøte på en glatt måte. Dette kan vi gjøre ved å bruke strategien med "midlede" normaler, som angitt ovenfor, i skjøtene.
En torus, smultring, er et tydelig eksempel der dette behovet oppstår. Vi kan lage bånd rundt torusen med GL_TRIANGLE_STRIP, men vi har ingen automatisk måte å glatte mellom båndene.
På figuren til venstre er det ikke er gjort noe forsøk på å skjøte mellom båndene, mens på figuren til høyre er normalene interpolert som angitt ovenfor.
Phong
Et alternativ til Gouraudshading er Phongshading [2] . I dette tilfellet beregnes en interpolering av normalene i hvert punkt og hele intensitetsberegningen gjøres på nytt basert på den nye normalen. Dette er en mer krevende metode, men den har noen klare fordeler. Vi skal drøfte dette litt nedenfor.
Noen vurderinger
Gouraudshading har noen begrensninger det er viktig å være klar over. En konsekvens av metoden er at lyskilder som ikke berører et hjørne i en flate ikke får noen effekt på flaten
En spotlight plassert som på figuren ovenfor vil ikke gi noen effekt på flaten siden lyset ikke påvirker intensitetsberegninger i noen av hjørnene.
På figuren nedenfor ser vi noen effekter av Gouraud-shading.
Fra venstre mot høyre ser vi:
- En kule med flat skyggelegging. Merk macband effekten
- En kule med glatt skyggelegging
- En kule med flat skyggelegging og en spotlight plassert som en hodelykt hos betrakteren
- Samme oppsett med glatt skyggelegging
Alle kulene er, i tillegg til hodelykten, belyst fra en kilde oppe til høyre med retningsbestemt lys uten avgrensning av lyskjeglen.
Vi kan prøve oss med to strategier for å bedre resultatet.
- Vi kan øke antall flater kraftig
- Vi kan modulere spotlighteffekten slik at selve lyskjeglen får en "mykere" kontur.
Disse effektene er demonstrert nedenfor.
Kula til venstre har bare fått økt antall flater, mens de to andre kulene har varierende grad av "myk" avgrensning av lyskjeglen. Lyskjeglen settes ved
glLighti(GL_LIGHT2, GL_SPOT_EXPONENT, m_SpotExp);
der m_SpotExp kan være i området [1,128]. Større tall gir mykere overgang.
Modulen Bordlampe demonstrerer spotlights og effekten på flater.