26
Tags:
c++
Skrevet af
Bruger #1474
@ 11.08.2008
Phong ShadingPhong er nok den mest kendte reflektions model. Phong shadingen bruger Lambert modellen til at beregne diffuse farven. Phong vil derfor få overfladerne i scene til at se blanke ud. Tilføj følgende Phong funktion til renderings klassen og brug den i stedet for Lambert funktionen. Her er den matematiske formel for Phong reflektions model:
Her er koden:
//Denne funktion vil beregne Phong reflektions model
LIGHTCOLOR RENDER::Phong( VECTOR & RayNear, VECTOR & RayFar, VECTOR & Ray, VERTEX & V1, VERTEX & V2, VERTEX & V3, GEOMETRY & Geometry, LIGHT & Light )
{
//Diffuse: Lambert
//Interpolerer vertex normalerne for vores trekant
VECTOR N = Geometry.InterpolateNormals( Ray, V1, V2, V3 );
N.Normalize();
//Find vores fragment
VECTOR V;
V.FollowLine( RayNear, RayFar, Ray.Z );
//Find vores lys vektor og normalisér den
VECTOR L = Light.Position.Sub( V );
L.Normalize();
//Find intensiteten ved at tage prik produktet af vores lys vektor og normal
double Diffuse = L.Dot( N );
//Specular: Phong reflektions model
//Lav en reflektions
VECTOR R( 2.0 * N.X * Diffuse - L.X, 2.0 * N.Y * Diffuse - L.Y, 2.0 * N.Z * Diffuse - L.Z, 1 );
V.X = -V.X;
V.Y = -V.Y;
V.Z = -V.Z;
V.Normalize();
double Specular = R.Dot( V );
if ( Specular > 1 )
Specular = 1;
else
if ( Specular < 0 )
Specular = 0;
// 32 = Alpha * Shininess
Specular = pow( Specular, 32 );
//Gem Diffuse of Specular farverne
LIGHTCOLOR Result;
Result.Diffuse.SetValues( Diffuse * Light.Color.Diffuse.R, Diffuse * Light.Color.Diffuse.G, Diffuse * Light.Color.Diffuse.B );
Result.Specular.SetValues( Specular * Light.Color.Specular.R, Specular * Light.Color.Specular.G, Specular * Light.Color.Specular.B );
//Husk at afklippe vores farve værdier mellem 0 og 1
Result.Diffuse.Clamp( 0, 1 );
Result.Specular.Clamp( 0, 1 );
return Result;
}
Renderingen vil nu se således ud:
Du har sikkert bemærket at teksturen er meget pixeleret. Det skyldes vores meget simple måde at aflæse vores pixels i teksturen. Der er findes forskellige måder at lave en mere detaljeret aflæsning af teksturen. Bilineær aflæsning er nok den mest kendte af dem alle. Den er utrolig let at implementere, så jeg har faktisk allerede gjort det i vores GetPixel funktion i TGA klassen. I stedet for kun at aflæse én bestemt pixel i teksturen vil bilineær algoritmen også aflæse alle omkring liggende pixels og finde gennemsnits farven af dem. Du kan lave en bilineær aflæsning ved at sætte parameteren: BilinearFilter, til True når du kalder TGA klassens GetPixel funktion fra renderings klassens: ShadePixel, funktion. Renderingen vil se således ud med bilineær tekstur aflæsning:
Der er utrolig meget at fortælle endnu omkring Raytracing. Vi har slet ikke diskuteret algoritmer for optimering af Raytracing. Renderingstiden er forholdsvis acceptabel for små simple scener som denne artikel har behandlet. Hvis du ønsker at rendere mere komplekse scener vil du opleve en utrolig lang vente tid. Raytracing kan blive optimeret meget uden forringelse af billedekvaliteten. Der er en god stykke vej endnu til at få en professionel software rendering ud af det kode denne artikel har introduceret. Der er en masse visuelle effekter der vil være interessant og sjov at implementere. Det mest utrolige ved software rendering, er, at du slet ikke bruger grafikkortet. Det hele bliver udregnet at computerens CPU. Det betyder at du har 100% frihed til dine renderinger. Forhåbenligt har denne artikel givet dig et lille indblik i Raytracing og givet dig lyst til at gå videre med din helt egen software rendering. Måske en dag vil dit renderingsprogram være det software alle de profesionelle animatorer vælger at bruge i fremtiden.
Denne artikel har fungeret som en slags appetitvækker. Vi har med hast været inde på nogle store og meget komplekse områder. Det er helt klart anbefalsværdigt at du på egen hånd går disse emner helt i bund. Her er en liste over interessante emner der kan udvide din rendering og gøre dit software mere attraktiv:
Rendering af flere typer lyskilder: Spotlight, Directional Light!
Rendering af flere lyskilder.
Rendering af skygger.
Rendering af reflektioner og refraktioner.
Tilføjelse af Anti-aliasing.
Flere reflektions modeller: Blinn, Metal, Plastic, Velvet osv.
Rendering af bumpmaps eller normalmaps.
Rotering af geometri: Matrix bereging.
Og til sidst men ikke mindst: Optimering af renderingen.
Listen kunne sagtens udvides men de nævnte emner vil nok være mest naturligt at gå i gang med efter denne artikel.
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 (26)
coolt
Wow!
Det er ikke hverdag man falder over en så gennemført tutorial. Du forklarer tingene rigtig godt og detaljeret uden at du forventer at folk er indforstået med hvad det lige er du mener. Jeg har arbejdet med 3D før i 3D's MAX og har tit tænkt på hvordan man kunne programmere sådan noget selv. Så du skal virkelig have mange tak for at vise mig hvordan man evt. kunne gøre det.
Keep up the good work
5/5 point
P.S. Lige et lille spørgsmål... Hvor har du alt din viden fra?
Mange tak for jeres kommentar.
Jeg har min viden fra forskellige bøger, websites og selvfølgeligt mit universitet. Jeg er netop blevet færdig som: Computer Spil Programmør på et Engelsk universitet. Da jeg altid har arbejdet med real-time rendering, har jeg i et stykke tid gået og fået lyst til at prøve software rendering. Håber at I kan drage nytte af min artikel.
Genialt! Det var lige hvad jeg havde brug for!
Søren du laver generalt DE BEDSTE artikler!
Jeg har et forslag til din vektor klasse. Jeg benytter operator overloading til ting som at addere, subtrahere og skalarproduktet. Jeg synes det gør brugen af vektorer meget mere overskuelig
Ellers thumbs up.
Jeg plejer også at bruge operator overloading i mine vektor klasser men jeg ville skrive C++ koden så den let kunne sammenlignes med Delphi koden (Se den samme artikel for Delphi:
http://www.udvikleren.dk/Delphi/Article.aspx/319/ ). Operator overloading er en forholdsvis ny feature i Delphi derfor har jeg ikke inkluderet den i Delphi versionen. I tilfælde af at en C++ programmør er interesseret i at lære Delphi (eller modsat) eller bare er interesseret i at se forskellen mellem de to sprog burde disse artikler være et godt udgangspunkt.
Mange tak for jeres kommentar. Hold jer endelig ikke tilbage hvis I har forslag, kritik eller ros
PS: Glem nu ikke rate mine artikler
Dejligt at kunne læse noget på dansk ;-) Super godt skrevet.
Hmm, god artikel, men ringe du har lavet PRÆCIS den samme artikel, bare med C++!
Undskyld men Delphi!
*Mener
Jonas:: Hvorfor ser du det som et negativt ting at have en artikel der viser implementationen i flere sprog? Skal Delphi udviklere ikke havde chancen for at implementere denne artikel?
Mange tak for rosen.
Jeg modtager gerne ris såvel som ros
Mener bare at du har lavet 2 af de samme artikler og fået dobblet point for det, du kunne bare ha' lavet det hvor artikel navnet var: "3D software rendering med C++ og Delphi"
Men synes det er ret mærkeligt
Hvorfor skulle jeg blande to sprog sammen når de er delt i to adskilte teknologier på dette forum? I så fald hvilken udviklings teknologi skulle jeg så poste dem under?
Er det fordi du mener at jeg har fået for mange points for de artikler?
Hvorfor skulle jeg blande to sprog sammen når de er delt i to adskilte teknologier på dette forum? I så fald hvilken udviklings teknologi skulle jeg så poste dem under?
Er det fordi du mener at jeg har fået for mange points for de artikler?
Jep
Jamen så må du jo snakke med de admins der har ansvar for artikeler her på forummet og tage problemstilling op hos dem. Det kan jeg næsten ikke gøre noget ved. Håber trods alt du kan bruge mine artikler til noget.
Det kan jeg da
SIKKERT! Artiklen er meget god
Men synes bare det er urætfærdigt at man får Up for begge
Jonas:
De der UP, er det ikke bare nogle tal, og så ikke mere i det?
Altså jeg laver altid Forumindlæg uden point..
Hey. Virkelig gennemført beskrivelse, og tror bestemt at jeg skal ha undersøgt mere på emnet.
Anyway. Har et par spørgsmål:
Den første kodestump på s. 4, som starter således: "//Den officelle TGA fil header!". Skal den gemmes som TGA.h? For hvis det er tilfældet så prøver den jo på at include sig selv
Og kan det her på udvikleren lade sig gøre at hente de filer som bliver brugt/lavet i artiklerne? For det ville da være en fordel hvis man sidder ligesom mig og roder rundt i hvordan det hele skal sidde sammen så man har en virkende bund at starte på, og at man ved fejl evt. ved fejl ved at det ikke er koden, men noget setup
Og til sidst. Dette burdet ikke have noget problem med at compile på en ubuntu-installation?
mvh. martin
Hej Martin,
Stukturen som jeg har kaldt for: FILEHEADER, er den officielle TGA fil header. Den skal ligge øverst i header filen TGA.h således den kan genkendes af TGA klassen. Du kan godt lægge den i en separat header fil, hvis du har lyst til det, men så skal den selvfølgelig inkluderes i TGA header filen inden TGA klassen defineres. Jeg vil nok anbefale at lægge den inden i selve TGA klassen da denne TGA fil format kun benyttes af TGA klassen! Med andre ord så er alt koden i den refererede tekst boks implementeringen af hele TGA klassen og kan skrives i en header fil eller en header med tilhørende cpp fil.
Angående kilde kode, du kan sende mig en udvikler post her på forummet med din mail adresse. Så vil jeg sende projektet til dig i en zip fil.
Alle andre er selvfølgelig også velkommen til at sende mig deres mail adresse.
Projektet skulle være platforms uafhængig. Der bliver ikke brugt nogle operative kommandoer eller API'er af nogen form, så ja, hvis din kompiler ellers kan kompile ganske almindelige console applikationer, så burde du også kunne kompilere dette projekt. Lad mig vide hvis du støder ind i nogle problemer.
Søren Klit Lambæk
Rigtig god artikel.
Du har dog glemt at fortælle at man skal huske at ændre RenderImage til at bruge den nye ShadePixel()
RGBA Color = ShadePixel(RayNear, RayFar, RayPixel, *V1, *V2, *V3, GeometryList[J], Texture, PointLight);
Og Phong laver compile errors
Da du her
RGBA VertexColor = Geometry.InterpolateVertexColors(Ray, V1, V2, V3);
parser V1, V2 og V3 til InterpolateVertexColors funktionen. Den ta'r vectors, men V1, V2 og V3 er vertexes.
Eller... Nu bliver jeg forvirret.
Error 1 error C2664: 'GEOMETRY::InterpolateNormals' : cannot convert parameter 2 from 'VECTOR' to 'VERTEX &' renderer.cpp 91
Nej, okay. er omvendt. Funktionen forventer vertexes, men V1, V2 og V3 er vectors.
Hvordan den være?
Denne side er da håbløst bugged.
Hvordan [b]skal[/b] den være?
Hej Morten, jeg er ikke helt med paa hvad du mener. Baade InterpolateNormals() og InterpolateColors() tager vertexer (Vertices). Kan du ikke give mig noget mere sammenhaengene kode saa jeg kan se mere detaljeret hvad du goer. Tak
Du skal være
logget ind for at skrive en kommentar.