Phong shading este un model pentru calcularea luminii obiectelor tridimensionale, inclusiv modele poligonale și primitive, precum și o metodă de interpolare a luminii asupra întregului obiect.
Modelele sunt de obicei definite de un set de fețe plate și convexe , deși majoritatea obiectelor 3D reale au suprafețe netede, curbate. Astfel, suprafața curbată este desenată ca o plasă poligon cu nervuri; pentru ca această plasă să arate netedă, se folosește una sau alta metodă de interpolare a iluminării vârfurilor rețelei poligonale .
Dacă se folosește umbrirea Gouraud , atunci calculul culorii este efectuat la fiecare vârf al fiecărei fețe, iar apoi culoarea calculată este interpolată pe întreaga față. Ca rezultat , evidențierile care ar trebui să apară în mijlocul poligonului nu vor fi desenate - la interpolarea culorilor vârfurilor, este imposibilă o iluminare mai strălucitoare a centrului poligonului.
Umbrirea Phong interpolează vectorul normal [1] . Pentru a găsi vectorul normal într-un punct arbitrar de pe suprafață, se folosește suma ponderată normalizată a vectorilor normali ai fețelor cărora le aparține acest punct:
Costul de calcul al umbririi Gouraud sau Phong depinde de numărul de vârfuri și, respectiv, de numărul de fragmente de imagine. Hardware-ul grafic modern folosește a doua metodă, calculând culoarea fiecărui fragment (adică pixelul) mai degrabă decât fiecare vârf.
Iluminarea Phong include și modelul de iluminat Phong, adică. algoritm pentru calcularea luminii la un punct dat. Acesta este un model de iluminat local, de ex. ia în considerare doar proprietățile unui punct dat și ale surselor de lumină, ignorând efectele împrăștierii, lentilelor, reflexiilor din corpurile învecinate.
Umbrirea Phong necesită relativ puține resurse, dar majoritatea fenomenelor optice sunt ignorate sau calculate cu o aproximare aproximativă.
Alte modele de iluminat pot ține mai bine cont de proprietățile materialelor (modele locale Oren-Nayar, Cooke-Torrens, anizotrope) sau de fenomene optice complexe (modele globale), dar conduc la creșterea costului general.
Calculul luminii Phong necesită calculul intensității culorii celor trei componente de iluminare: fundal (ambient), difuz (difuz) și lumini lucioase (speculare). Componenta de fundal este o aproximare aproximativă a razelor de lumină împrăștiate de obiectele învecinate și apoi ajungând la un punct dat; celelalte două componente simulează împrăștierea și reflectarea radiației directe.
Unde
este vectorul normal la suprafață în punct
- fascicul incident (direcția către sursa de lumină)
- fascicul reflectat (direcția unui fascicul perfect reflectat de la suprafață)
— factor de iluminare de fundal
— coeficientul de strălucire
— coeficient de iluminare difuză
În conducta OpenGL, intensitatea culorii fragmentului este calculată pentru fiecare sursă de lumină separat, apoi se adună rezultatele și se adaugă lumina emisă de corp (GL_EMISSION).
Algoritmul de calcul al luminii Phong poate fi ilustrat folosind următoarele shadere :
Vertex shader variind vec3 n ; variind vec3 v ; void principal ( gol ) { v = vec3 ( gl_ModelViewMatrix * gl_Vertex ); n = normalize ( gl_NormalMatrix * gl_Normal ); gl_Position = ftransform (); } Fragment shader variind vec3 n ; variind vec3 v ; void principal ( gol ) { rezultat vec4 = vec4 ( 0,0 ); pentru ( int li = 0 ; li < gl_MaxLights ; ++ li ) { vec3 viewPos = gl_LightSource [ li ]. pozitia . w * v ; vec3 l = normalize ( gl_LightSource [ li ]. position . xyz - viewPos ); vec3 e = normalize ( - v ); vec3 r = normalize ( - reflect ( l , n )); vec4 Iamb = gl_FrontLightProduct [ li ] . ambiental ; vec4 Idiff = gl_FrontLightProduct [ li ]. difuz * max ( punct ( n , l ), 0,0 ); Idiff = clemă ( Idiff , 0,0 , 1,0 ); vec4 Ispec = gl_FrontLightProduct [ li ]. speculară * pow ( max ( punct ( r , e ), 0,0 ), gl_FrontMaterial . strălucire ); Ispec = clemă ( Ispec , 0,0 , 1,0 ); rezultat += Iamb + Idiff + Ispec ; } gl_FragColor = gl_FrontLightModelProduct . sceneColor + rezultat ; }Unde este valoarea
gl_FrontLightModelProduct . sceneColoreste echivalent cu
gl_FrontMaterial . emisie + gl_FrontMaterial . ambient * gl_LightModel . înconjurător