Wednesday, November 27, 2013

Phong болон Blinn-Phong ийн гэрлийн тусгалын загварууд

Phong болон Blinn-Phong ийн тусгалын загварууд хоёулаа diffuse гэрлийн тусгалыг загварчилахдаа хялбар ambient болон Lambertian тусгалын томъёог ашигладаг, харин specular гэрлийн ойлтыг тооцооллохдоо ялгаатай байдаг.

Phong

Specular гэрлийн ойлтын хүчин зүйлс нь аль дээр үед Warnock(1969) ийн томъёонд хэрэглэгдэж байсанч дараагаар нь Phong(1973, 1975) илүү сайжруулж өгсөн байдаг. Энэ томъёонд гэрлийн толбо их харагдаг яагаад гэвэл гэрлийн тусгалын векторын дагуу specular гэрлийн ойлтын утга нь хамгийн их байдаг. Phong болохоор гэрлийн тусгалын вектор болон eye-vector буюу камерийн харж байгаа чиглэлийн эсрэг чиглэл дэх вектор хоёрын хооронд үүссэн өнцөгийг тооцоололдоо хэрэглэдэг. Энэ өнцөгийн утга хамгийн бага байвал specular ойлтын утга нь илүү хурц харагдах өнгө болдог. Specular гэрлийн ойлтын утга нь камерийн харах чиглэлтэй хамааралтай байдаг бол diffuse гэрлийн тусгалын утга нь үүнтэй хамааралгүй.

Гэрлийн тусгалын векторын чиглэлийг дараах томъёогоор тооцож олох боломжтой.
    r = 2 * dot(n, l)n - l
энд l бол ирж байгаа гэрлийн эх үүсвэрлүү чиглэсэн вектор бол n нь объектийн гадаргуун нормал вектор юм харин dot() гэсэн функц бол бидний мэдэхээр хоёр векторын хоорондох скаляр үржвэр болно, барууныхан ихэнхидээ dot product гэж нэрлээд заншчихсан. l болон n үүдийг хоёуланг нормчилсон байх ёстой, нормчилох гэдэг нь векторын урт нь нэгж буюу 1 тэй тэнцүү болгохыг хэлнэ, үүнийг пифагорын томъёогоор хялбархан шийдэж болно.
GLSL-д reflect(vec l, vec n) гэдэг функц бий, энэ функц болохоор саяны бичсэн томъёог бодож өгдөг функц юм, хэрэв гэрлийн чиглэлийн векторын эсрэг чиглэлийн вектор хэрэглэхээр болвол reflect(-l, n) гэх маягаар хэрэглэж болно.

Үүний дараа гэрлийн тусгалын векторыг хэрэглэж скаляр үржвэр олоод камерлүү чиглэсэн векторыг энэ хоёр векторуудын хоорондох өнцөгөөс косинус авах байдлаар гаргаж авна. Specular гэрлийн эрчийн (specular intensity) утгыг дараах томъёог хэрэглэж олно :
    s = dot(r, e) ^ cSpec
энд r бол гэрлийн тусгалын вектор, e бол тусгалын цэгээс камерлуу чиглэсэн вектор харин cSpec бол specular зэрэгт дэвшүүлэгч утга энэ нь юу гэсэн үг вэ гэхээр объектийн материал бүрт зориулж specular гэрлийн ойлтыг загварчилсан зэрэгт юм. cSpec утга нь их байх тусмаа гэрлийн толбо илүү жижигхэн бөгөөд цэвэрхэн харагддаг.

Хэрэв view-огторгуй буюу камерийн байрлалыг тооллын эх болгож авсан координатын систем дотор гэрлийн утгыг тооцоолбол илүү хялбарчилсан байдалтай болгож болно. Энэ бол view-огторгуй доторхи камерийн байрлалаас тусгалын цэг хүртлэх векторын эсрэг чиглэл дэх векторыг камерийн чиглэлийн вектороор төлөөлүүлэн ашиглах явдал юм. Энэ тохиолдолд камерийг хязгааргүй хол оршин байгаа гэж төсөөлөх хэрэгтэй болдог бөгөөд камерийн бүх векторууд нь параллел болно.

гэрлийн specular эрчийг(specular intensity) иймэрхүү байдлаар тооцон бодож олно.
if (dot(lightDirection, normal) > 0.0f) {
    // reflect(-l, n) = 2.0 * dot(n, l) * n - l;
    vec3 reflectionVector = reflect(-lightDirection, normal);
    float specTmp = max(dot(reflectionVector, eyeDir), 0.0f);
    float specularIntensity = pow(specTmp, specularExponent);
}

specularExponent утга бол specular гэрлийн толбоны тодролтыг(sharpness) тохируулахад оролцоно. Утга нь бага байвал specular гэрлийн толбоны ойролцоох хэсэг дээрхи гэрлийн хамрах хүрээ нь нэлээн их байдаг харин их утгатай байвал хамрах хүрээ нь багасч илүү тод гэрлийн толботой болж ирдэг.

specular гэрлийн ойлтыг тооцон олох нь яг бодит ертөнц дээр болдог гэрлийн физик харилцан үйлчилэлтэй ижилхэн биш боловч бодит байдалтай ойролцоогоор дөхөх хэмжээний үр дүнг харуулдаг. Ерөнхийдөө бодит-хугацааны(realtime) програмуудын хувьд хангалттай сайн үр дүнг үзүүлдэг гэж ойлгож болно.

Дээрхи томъёог Bi Tuong Phong гэдэг эрдэмтэн ambient болон specular гэрлийн тусгалыг хослуулан тодорхойлж өгсөн болохоор Phong-ийн гэрлийн тусгалын загвар (Phong reflection model) гэж нэрлэх нь бий. Гэхдээ бас энэ томъёог цааш нь сайжруулах боломжтой байдаг. Жишээлбэл Blinn-Phong гэрлийн тусгалын загвар(Blinn-Phong reflection model) гэж бий.




Blinn-Phong

Blinn-Phong ийн томъёо нь Blinn-ий судалгааны ажил 1977 онд бий болох үед анх гарч иржээ. Blinn нь үнэндээ Phong-оос өөр томъёог судалгааны ажилдаа дүрсэлсэн байдаг(заримдаа энэ томъёо нь Torrance-Sparrow reflection model-той тун ойролцоо) боловч тэрээр Phong-ийн томёог судалгааны материалын эхэн хэсэгт дурдаж өгчээ. Гэвч энэ томъёо нь Phong-ийн томъёог үл ялиг өөрчилсөн байдалтай болохоор үүнийг Blinn-Phong ийн shader гэж голдуу нэрлэж заншжээ.

Blinn-Phong-ийн shading загвар нь хагас вектор хэрэглэдэг. Энэ вектор бол гэрлийн чиглэлийн вектор болон камерлуу чиглэсэн вектор хоёрын хоорондох яг завсарын вектор юм. Энэ хагас вектор гадаргууны нормал вектортой илүү ойртож ирэх тусам specular гэрлийн толбо нь илүү эрчтэй харагддаг байна. Энэ хагас векторыг H = (L + V) / (|L + V|) гэж тооцож олж болно эсвэл norm(L + V) гэж олж болно. Камерийн харж байгаа чиглэлийн векторын скаляр үржвэр болон гэрлийн тусгалын вектор хоёрыг харгалзан хагас векторын скаляр үржвэр болон Phong shading model-ийн гадаргуун нормалиар солидог.  Ингэж гаргаж авсан томъёог Blinn-Phong ийн томъёо гэнэ.
if (dot(lightDirection, normal) > 0.0f) {
    vec3 halfwayVector = normalize(lightDirection + eyeDir);
    float specTmp = max(dot(normal, halfwayVector), 0.0f);
    specularIntensity = pow(specTmp, cShininess);
}

Blinn-Phong ийн томъёон дэх specular зэрэгт нь Phong-ийн томёоноос гарах үр дүнгээс ялгаатай. Яагаад вэ гэвэл Blinn-Phong томёонд тооцон бодох нь Phong-ийнхоос илүү хурдтай байдаг. Ийм болохоор Blinn-Phong ийн томёо нь хамгийн их өргөнөөр хэрэглэгддэг байнаа.