Phong stínování je model pro výpočet osvětlení trojrozměrných objektů, včetně polygonálních modelů a primitiv, a také metoda pro interpolaci osvětlení přes celý objekt.
Modely jsou obvykle definovány sadou plochých, konvexních ploch , ačkoli většina skutečných 3D objektů má hladké, zakřivené povrchy. Zakřivený povrch je tedy nakreslen jako žebrovaná polygonová síť; aby tato síť vypadala hladce, používá se ten či onen způsob interpolace osvětlení vrcholů polygonální sítě .
Pokud je použito Gouraudovo stínování , pak se výpočet barvy provede u každého vrcholu každé plochy a poté se vypočítaná barva interpoluje přes celou plochu. V důsledku toho nebudou vykreslena světla , která by se měla objevit uprostřed mnohoúhelníku – při interpolaci barev vrcholů není možné jasnější osvětlení středu mnohoúhelníku.
Phongovo stínování interpoluje normální vektor [1] . K nalezení normálového vektoru v libovolném bodě na povrchu se použije normalizovaný vážený součet normálových vektorů ploch, ke kterým tento bod patří:
Výpočetní cena Gouraudova nebo Phongova stínování závisí na počtu vrcholů a počtu fragmentů obrazu. Moderní grafický hardware používá druhou metodu, vypočítává barvu každého fragmentu (tj. pixelu) spíše než každého vrcholu.
Součástí osvětlení Phong je i model osvětlení Phong, tzn. algoritmus pro výpočet osvětlení v daném bodě. Jedná se o model lokálního osvětlení, tzn. bere v úvahu pouze vlastnosti daného bodu a světelných zdrojů, ignoruje vlivy rozptylu, čočky, odrazů od sousedních těles.
Phongové stínování vyžaduje relativně málo zdrojů, ale většina optických jevů je ignorována nebo počítána s hrubou aproximací.
Jiné modely osvětlení mohou lépe zohledňovat materiálové vlastnosti (místní Oren-Nayar, Cooke-Torrens, anizotropní modely) nebo složité optické jevy (globální modely), ale vedou ke zvýšené režii.
Výpočet osvětlení Phong vyžaduje výpočet intenzity barev tří složek osvětlení: pozadí (okolní), rozptýlené (rozptýlené) a lesklé odlesky (zrcadlení). Složka pozadí je hrubá aproximace světelných paprsků rozptýlených sousedními objekty a poté dosáhnoucích daný bod; zbývající dvě složky simulují rozptyl a odraz přímého záření.
kde
je normálový vektor k povrchu v bodě
- dopadající paprsek (směr ke zdroji světla)
- odražený paprsek (směr dokonale odraženého paprsku od povrchu)
— faktor osvětlení pozadí
— koeficient oslnění
— koeficient difúzního osvětlení
V OpenGL pipeline se intenzita barvy fragmentu vypočítá pro každý světelný zdroj zvlášť, poté se výsledky sečtou a sečte se světlo vyzařované tělem (GL_EMISSION).
Algoritmus výpočtu osvětlení Phong lze ilustrovat pomocí následujících shaderů :
Vertex shader měnící se vec3n ; měnící se vec3 v ; void hlavní ( void ) { v = vec3 ( gl_ModelViewMatrix * gl_Vertex ); n = normalizovat ( gl_NormalMatrix * gl_Normal ); gl_Position = ftransform (); } Shader fragmentů měnící se vec3n ; měnící se vec3 v ; void hlavní ( void ) { vec4 výsledek = vec4 ( 0,0 ); for ( int li = 0 ; li < gl_MaxLights ; ++ li ) { vec3 viewPos = gl_LightSource [ li ]. pozici . w * v ; vec3 l = normalizovat ( gl_LightSource [ li ]. pozice . xyz - viewPos ); vec3 e = normalizovat ( - v ); vec3 r = normalizovat ( - odrážet ( l , n )); vec4 Iamb = gl_FrontLightProduct [ li ]. okolní ; vec4 Idiff = gl_FrontLightProduct [ li ]. difuzní * max ( tečka ( n , l ), 0,0 ); Idiff = svorka ( Idiff , 0,0 , 1,0 ); vec4 Ispec = gl_FrontLightProduct [ li ]. zrcadlový * pow ( max ( tečka ( r , e ), 0,0 ), gl_FrontMaterial . lesklost ); Ispec = svorka ( Ispec , 0,0 , 1,0 ); vysledek += Iamb + Idiff + Ispec ; } gl_FragColor = gl_FrontLightModelProduct . sceneColor + výsledek ; }Kde je hodnota
gl_FrontLightModelProduct . sceneColorje ekvivalentní
gl_FrontMaterial . emise + gl_FrontMaterial . ambient * gl_LightModel . okolní