3D software rendering med Delphi

Tags:    delphi
Skrevet af Bruger #1474 @ 11.08.2008

Lys klasse

Indtil nu har vi bare aflæst geometriske farver og renderet en simpel Gauraud shading. Vi vil gøre vores rendering meget mere realistisk ved at tilføje en lyskilde. Den mest enkle lyskilde er en PointLight. Hvis du forestiller dig en nøgen pære der lyser lige kraftig i alle retninger, så vil du havde en god ide om, hvad der menes med PointLight. Den indeholder en position som kan repræsenteres af en vektor. Vi vil også få brug for en farve til vores lyskilde. Faktisk får vi brug for mere end blot én farve. Vi skal i alt bruge tre farver som hedder følgende:

1) Ambient
2) Diffuse
3) Specular

Ambient farven er egenlig snyd. Den findes ikke i den virklige verden men er noget man i sin tid har bestemt der skulle indføres for at opnå en mere realistisk effekt. I den virklige verden vil det oftest aldrig blive helt mørkt. Der vil som regl altid være en lille smule lys der ganske svagt bliver reflekteret rundt. Selv en mørk nat er stort set aldrig helt mørkt. Stjernene og ikke mindst månen vil reflektere lys og vil oplyse ganske svagt. Den virtuelle verden er meget mere simpelt anlagt. Enten er der lys eller også er der ikke noget lys. For at ungå at denne kunstige og urealistisk belysning har man derfor valgt at indføre ambient lyset.

Diffuse farven kan ganske enkelt opfattes som lystes egenlige grundfarve. Det er derfor den mest dominerende farve af dem alle.

Specular farven kan få overflader til at se blanke ud. Kun når lyskilden står i en reflekterende vinkel mod observatøren, som i vores tilfælde er vores kamera eller viewport, vil specular farven være synlig.

Jeg har valgt at lave en speciel farve klasse for vores lyskilde. Den ser således ud:

Fold kodeboks ind/udKode 


Lad os se, hvordan hele vores lys klasse kommer til at se ud:

Fold kodeboks ind/udKode 


For at beregne lysfaldet for en trekant skal vi bruge vertex klassens normal. Vi har én normal defineret for hver vertex. En normal er som regl altid vinkelret mod trekantens flade. Eller med andre ord, så vil normalen stikke ud fra trekantens flade med en vinkel på 90 grader.



For at beregne lysfladen vil man skulle finde vinklen mellem lyskilde og normal. Denne vinkel kan let beregnes ved at tage et prik produkt af normalen og lysretningen. Det vil give et cosinus vinkel. Denne funktion er allerede implementeret i vektor klassen og hedder: Dot, fordi prik produkt på engelsk hedder: dot product. Længden af normalen skal være en enhed lang. Funktionen: Normalize, som også ligger i vektor klassen, vil normalisere en vektor. Det vil sige at den sætter længden på en vektor til præcis 1 enhed. Hvis man ikke husker at normalisere en normal vil man ofte få en uønsket resultat.

Der findes et hav af forskellige materialer og lyskilder i den virklige verden der alle opføre sig på deres helt egen måde. Plastik reflektér lys på en anden måde end f.eks metal. Selv indenfor forskellige metal og plastik arter reflektér lys forskelligt. Når det kommer til stykket så er der ingen der har en korrekt formel på, hvordan lys bliver reflekteret af de forskellige materialer og overflader i forbindelse med computer genereret grafik. Vi kan højst sige at noget ligner eller ikke ligner. Lad os kigge lidt på de mest klassiske reflektions modeller.

Lambert Shading

Lambert reflektions model er grundstenen til langt de fleste reflektions modeller af lys. Den benytter kun ambient og diffuse komponenterne. De fleste reflektions modeller er kun fokuseret omkring specular farven. Her er den matematisk formel for Lambert:



Umiddelbart kan denne formel se lidt skræmmende ud, hvis man ikke er så matematisk stærk, men den er faktisk ikke så slem at oversætte til kode. Vi vil lave en funktion i vores renderings klasse som vi kalder for Lambert:

Fold kodeboks ind/udKode 


Som du kan se returner funktionen en lysfarve klasse. Denne funktion vil blive kaldt fra ShadePixel funktion så lad os tilpasse den funktion.

Fold kodeboks ind/udKode 


Lad os tilføje lyskilden til vores lille scene.

Fold kodeboks ind/udKode 


Glem ikke at definer lyskilden i renderings klassen samt at frigøre den fra hukommelsen i klassens destruktion.

Fold kodeboks ind/udKode 


Siden prototypen er blevet udvidet med en ekstra parameter, skal vores nye lyskilde tilføjes til kommandoen i funtionen: RenderImage. Renderingen skulle nu gerne se således ud:




Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (2)

User
Bruger #14855 @ 17.06.09 15:33
Hmm, god artikel, men ringe du har lavet PRÆCIS den samme artikel, bare med C++!
User
Bruger #1474 @ 29.06.09 19:03
Koden er jo ikke den samme!
Du skal være logget ind for at skrive en kommentar.
t