遊戲製作詳解自----OpenGL入門教程(九)(轉)

post0發表於2007-08-12
遊戲製作詳解自----OpenGL入門教程(九)(轉)[@more@]

  OpenGL中用表面來表示物體,一個物體就是一組平面。光線照射在平面上會產生反射,入射線與反射線的角平分線就是法線,它垂直於平面。面法線有兩種可能的方向,我們稱面有兩側。當描述封閉物體的外表面時,法線應該從內部指向外部;而表示在物體內部時,法線應該從外部指向內部。

  用glNormal*(N_Vector);指定當前法向向量。此後的頂點都會使用該法向,直到再次改變。

  

  面的法向向量是怎麼確定的呢?右手手指沿頂點順序握拳,拇指豎立所指方向即為一個面的法向,如果面對該平面,以逆時針序指定頂點,則法向指向你。當你用這樣的順序指定平面的頂點時,OpenGL能夠正確的計算出法向向量。法矢與頂點座標一樣要經過模型視矩陣變換,這樣物體座標系內的法向向量就可以正確的變成世界座標系內的法向向量,保證最終生成的影像是正確的。

  

  當一個頂點屬於多個平面時,該頂點的法嚮應該取所在所有平面法向的平均值,以使表面稜角部份平滑自然的,否則會有一道黑線。

  

  我們把平面的法向所指一側稱為前面,另一側稱為後面,可以為兩側分別指定不同的屬性,所以glMaterial*命令的第一個引數必須是GL_FRONT/GL_BACK/GL_FRONT_AND_BACK之一。

  

  下面這組圖片展示了法向對場景的影響,角度表示影像是繞Y旋轉多少後觀察到的:

  

  頭兩行中兩三角法向從兩者之間指向外部,簡稱外法向。

  前三角的面法向(0,0,1),後三角的面法向(0,0,-1),光射線方向(0,0,-1)

  第一行中,前三角,後三角呈現的是其GL_FRONT部份的材質

  第二列中,兩個三角形的前後關係已經反過來了。

  

  三四兩行中兩三角法向從兩者外部指向兩者之間的內部,簡稱內法向。

  前三角的面法向(0,0,-1),後三角的面法向(0,0,1),光射線方向(0,0,-1)。

  

  第五行前兩圖中兩三角法向相同均為(0,0,1)。

  

  外法向的平面組可用來表示物體外觀(外表面),第五行最後一張圖則是這樣表示的一個立方體。

  內法向則適於表示從內部觀察物體(燈光、視點均在內部,內表面),程式從略。

  

  雙三角場景的

  繪製程式程式碼如下:

  

  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  glEnable(GL_LIGHTING);glEnable(GL_DEPTH_TEST);

  

  glEnable(GL_COLOR_MATERIAL);

  glEnable(GL_LIGHT0);

  glLoadIdentity();

  glRotatef(rot,0,1,0);//全域性變數rot即為旋轉角度

  glBegin(GL_TRIANGLES);

  glNormal3f(0.0,0.0,1.0);//法向與光射線指向同側

  glColor3f(1.0,0.0,0.0);

  glVertex3f(-1.0,0.0,-0.30);

  glColor3f(0.0,1.0,0.0);

  glVertex3f(0.0,1.0,-0.30);

  glColor3f(0.0,0.0,1.0);

  glVertex3f(1.0,0.0,-0.30);

  

  

  glNormal3f(0.0,0.0,-1.0);//法向與光射線指向相反

  glColor3f(1.0,0.0,0.0);

  glVertex3f(-1.0,0.0,0.0);

  glColor3f(0.0,1.0,0.0);

  glVertex3f(0.0,1.0,0.0);

  glColor3f(0.0,0.0,1.0);

  glVertex3f(1.0,0.0,0.0);

  glEnd();

  使用OpenGL預設的光照(光源在0,0,1沿-Z軸方向的白色平行光)和預設的平行投影。為簡化程式碼,開啟了GL_COLOR_MATERIAL直接用glColor設定頂點材質。另外為便於閱讀圖片做了減肥。

  以上圖片是在PII266/FireGL 1000pro/Win2000環境下獲取的。

  

  這兩段程式碼都放在TOpenGL Panel的OnPaint事件裡執行。

  

  檢討:右邊程式碼的法向全反了,如果你執行它就會發現雖然看起來仍是一個立方體,但是前後左右上下全都反過來了。這是因為各面法向朝裡,前面的後側對著我們,它不可見,看到的前面實際是後面前側,而正常情況下後面應該會被前面擋住。

  

  

  立方體場景的

  繪製程式程式碼如下:

  

  glBegin(GL_QUADS);

  glNormal3f(0,0,-1);

  glColor3f(1,0,0);

  glVertex3f(0,0,0);

  glVertex3f(1,0,0);

  glVertex3f(1,1,0);

  glVertex3f(0,1,0);

  

  glNormal3f(-1,0,0);//右

  glColor3f(0,1,0);

  glVertex3f(1,0, 0);

  glVertex3f(1,0,-1);

  glVertex3f(1,1,-1);

  glVertex3f(1,1, 0);

  

  glNormal3f(0,-1,0);//上

  glColor3f(0,0,1);

  glVertex3f(0,1, 0);

  glVertex3f(1,1, 0);

  glVertex3f(1,1,-1);

  glVertex3f(0,1,-1);

  

  glNormal3f(0,0,1); //後

  glColor3f(1,1,0);

  glVertex3f(0,1,-1);

  glVertex3f(1,1,-1);

  glVertex3f(1,0,-1);

  glVertex3f(0,0,-1);

  

  glNormal3f(1,0,0);//左

  glColor3f(0,1,1);

  glVertex3f(0,1, 0);

  glVertex3f(0,1,-1);

  glVertex3f(0,0,-1);

  glVertex3f(0,0, 0);

  

  glNormal3f(0,1,0);//下

  glColor3f(1,0,1);

  glVertex3f(0,0,-1);

  glVertex3f(1,0,-1);

  glVertex3f(1,0, 0);

  glVertex3f(0,0, 0);

  glEnd()

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951755/,如需轉載,請註明出處,否則將追究法律責任。

相關文章