新手思路 phong簡單光照模型繪製

2021-08-25 04:32:34 字數 4090 閱讀 7093

第一步:熟悉opengl

程式設計。

製作乙個會旋轉的圓錐體,並加入貼圖。

第二步:讀取複雜物體表面的頂點資訊。已知複雜物體表面是由乙個個三角麵片構成的三角網格圖形。

讀出點、線、面資訊,然後繪製頂點。

第三步:在給定模型的基礎上,在取消光照情況下,首先嘗試自己計算漫反射光照的值。

設定光源位置lightposition(

三維座標)

、光源顏色值lightshiness

、漫反射係數值diffuse(rgb

格式),

同時可由函式求出每個頂點的屬性(

包括頂點座標pvertex,

頂點法線向量等),

然後將lightposition

與頂點座標pvertex

的各座標軸的值想減,

求得光源向量,

然後與頂點法線向量求點積,

得到cos

值,然後利用公式i=diffuse*cos*lightshiness

求得作用於頂點的漫反射光照值i(rgb

格式)。

為了簡化計算,光源使用平行光。初始位置為(0,0,1)。

首先在cscenegraph3d

類中定義了光源位置、光源顏色值(

即光強)

、漫反射係數三個變數,並在cscenegraph3d

類的建構函式cscenegraph3d

::cscenegraph3d()

中初始化。為了能在cmesh3d

類中訪問到這三個變數,需要編寫乙個函式實現傳值操作,這個函式是新增在cmesh3d

類中,命名為drawme(glfloat* fdiffuse,glfloat* flightness,glfloat*flightpos);

然後在cscenegraph3d

類中的gldraw()

函式中新增如下**:

glfloat m_lightpos = ;

((cmesh3d*)pobject3d)->drawme(m_fdiffu,m_flightness,m_lightpos);

pobject3d->gldraw();

最後在cmesh3d

類中的glbuildlist()

函式中實現計算漫反射光照值。

第四步:光源位置不變,物體旋轉。

物體旋轉時,法向改變,則有多少個頂點cpu

需要重複計算多少次,這樣耗時巨大,所以想到另一種方法,就是在利用glrotate()

進行物體旋轉時求出其旋轉矩陣,然後求其逆矩陣,再和光源方向做點積,這種方法保證只計算一次光源方向,提高了cpu

利用率。

在cmeshview

::ontimer()

函式中求旋轉物體時轉換矩陣的逆矩陣inv_matrix

,將上面的glrotatef

順序倒著寫,並使旋轉角度求反,即由正變負。然後將inv_matrix

傳遞到cmesh3d類。

傳值:cmeshdoc* pdoc = getdocument();

cmesh3d *pmesh = (cmesh3d *)pdoc->m_scenegraph.getat(0);

pmesh->sendinversematrix(inv_matrix);

其中sendinversematrix

函式為:

void sendinversematrix(glfloat *inv_matrix)

第五步:讓光源位置移動,使其圍繞物體旋轉

在cscenegraph3d

類中新增成員函式spindisplay()

使光源繞y

軸旋轉,

則x 、z

值改變。然後在cmeshview

::ontimer()

中呼叫此函式。

為了清晰地看到光源是如何移動的,繞著什麼方向移動的,我設定了一條紅色的線(

從原點到光源位置)

,當光源繞y

軸旋轉時若從正前方看模型,則此條線在螢幕上會顯示為一條直線,所以我將平面(x,0,z)

轉換為(x,-z,0)

平面,即是將俯檢視向上旋轉90

度,使我們能在螢幕正前方看到俯檢視,此時繪製的線移動時顯示為移動乙個圓周。

glcolor3f(1,0,0);

glbegin(gl_lines);

glvertex3f(0,0,0);

glvertex3f(10*m_light_parallel.x(),-10*m_light_parallel.z(),0);//

保證看到俯檢視

glend();

第六步:計算鏡面反射光照,最後通過數學計算公式,在計算機上程式設計實現phong

模型(簡單光照模型)。

在使用phong

模型時不考慮環境光,因為環境光對物體的影響很小,可以忽略。所以最終顏色是漫反射光照和鏡面反射光照構成的phong

模型。

cvector3d pv = *pvector; //

賦值,得到cvector3d

型別的pv

,而非cvector3d*

型別!

pv.normalizel2(1); //

法向單位化,

歸一化

glfloat fcos = (glfloat)scalar(&pv,&m_light_parallel); //

點積求得cos角

if (fcos<0.0f) fcos=0.0f;

glfloat fxx1 = m_fdiffuse[0] * m_flightness[0]*fcos;

glfloat fyy1 = m_fdiffuse[1] * m_flightness[1]*fcos;

glfloat fzz1 = m_fdiffuse[2] * m_flightness[2]*fcos;

glfloat m_specular[3]=; //

鏡面反射係數

cvector3d m_eye; //

觀察方向

m_eye.set(0.0,0.0,1.0);//

從螢幕裡面指向外面,為z

軸正向

glfloat l_v; //

光源方向和觀察方向

l_v=sqrt(pow(m_eye.x()+m_light_parallel.x(),2) +

pow(m_eye.y()+m_light_parallel.y(),2) +

pow(m_eye.y()+m_light_parallel.y(),2) );

cvector3d m_h_specular; //

公式h=

(l+v

)/ | l+v |

m_h_specular.set((m_light_parallel.x()+m_eye.x())/l_v,

(m_light_parallel.y()+m_eye.y())/l_v,

(m_light_parallel.z()+m_eye.z())/l_v);

m_h_specular.normalizel2(1);

glfloat v_r=(glfloat)scalar(&m_h_specular,&pv); //

求點積if (v_r<0.0f) v_r=0.0f;

glfloat n=5;//

鏡面高光係數(0--2000) n

越大,光斑越暗

glfloat m_v_r=pow(v_r,n); // v_r

的n次方

glfloat fxx2=m_flightness[0]*m_specular[0]*m_v_r;

glfloat fyy2=m_flightness[1]*m_specular[1]*m_v_r;

glfloat fzz2=m_flightness[2]*m_specular[2]*m_v_r;

glfloat fxx= fxx1+fxx2;

glfloat fyy=fyy1+fyy2;

glfloat fzz=fzz1+fzz2;

if (fxx>255) fxx=255;

if (fyy>255) fyy=255;

if (fzz>255) fzz=255;

::glcolor3ub(fxx,fyy,fzz);

新手思路 phong簡單光照模型繪製

第一步 熟悉opengl 程式設計。製作乙個會旋轉的圓錐體,並加入貼圖。第二步 讀取複雜物體表面的頂點資訊。已知複雜物體表面是由乙個個三角麵片構成的三角網格圖形。讀出點 線 面 資訊,然後繪製頂點。第三步 在給定模型的基礎上,在取消光照情況下,首先嘗試自己計算漫反射光照的值。設定光源位置lightp...

Phong和Blinn Phong光照模型

phong和 blinn phong 是計算鏡面反射光的兩種光照模型,兩者僅僅有很小的不同之處。1.phong模型 phone模型計算中的乙個關鍵步驟就是反射向量r的計算 上圖中的位於表面 下面 的向量 i 是原始 i 向量的拷貝,並且二者是一樣的,現在我們的目標計算出向量 r 根據向量相加原則,向...

高光反射Phong光照模型

高光反射是一種經驗模型,並不完全符合真實世界中的高光反射現象。先根據表面法線 視角方向 光源方向計算出反射方向。通過 phong 模型來計算高光反射的部分。一般都用逐畫素,得到更平滑的高光效果。公式 高光反射光線強度 入射光線顏色 高光反射顏色 max 0,視角方向 反射方向 高光反光度 case ...