OpenGL之鏡面反射光

OpenGL之鏡面反射光

鏡面反射產生閃耀的光輝,此光照效果很有趣,需要分別設置光源材質.

光源和材質 簡介
Light_Specular[] = {1.0f,1.0f,1.0f,1.0f};

glLightfv(light,GL_SPECULAR, Light_Specular);

鏡面反射光顏色{r,g,b,a}分量
Material_Specular[] = {1.0f,1.0f,1.0f,1.0f};

glMaterialfv(GL_FRONT,GL_SPECULAR, Material_Specular);

材質的鏡面反射光顏色,反射出去的顏色不大於材質顏色

{1.0f,1.0f,1.0f,1.0f}:光照完全反射出去,

glMaterialf (GL_FRONT,GL_SHININESS,10); 鏡面反射光聚焦度

0:不聚焦

128:高度聚焦

函式示例

  1. float Light_Specular[] = {0f,1.0f,1.0f,1.0f};// 鏡面反射光分量
  2. float Light_Position[] = {0f,0.0f,1.0f,1.0f};// 燈光位置
  3. glLightfv(light,GL_SPECULAR, Light_Specular);// 鏡面反射光分量
  4. glLightfv(light,GL_POSITION, Light_Position);// 光源位置
  5. Material_Specular[] = {0f,1.0f,1.0f,1.0f};// 鏡面反射光材質
  6. glMaterialfv(GL_FRONT,GL_SPECULAR, Material_Specular);// 鏡面反射光材質
  7. glMaterialf (GL_FRONT,GL_SHININESS,10);// 鏡面反射光聚焦度

鏡面反射光程式示例,行星發出閃耀的光輝,而衛星繞行星旋轉並且發光,分別使用聚光燈和定點光.但無使用環境光.下載程式

  1. 按(/)鍵增加或減小聚光燈焦點指數
  2. 按</>鍵增加或減小聚光燈張角
  3. 按+/-鍵增加或減小多邊形表面的鏡面反射光聚焦度
  4. 按123鍵切換衛星的顏色與光線(紅綠藍)
  5. 按SPACE(空格)鍵啟用或禁用聚光燈
  6. 按UP/DOWN鍵衛星上下移動
  7. 按LEFT/RIGHT鍵衛星左右移動
  8. 按F1鍵打開幫助
  9. 按ESC鍵重置聚光燈參數

 

OpenGL之材質

OpenGL之材質

OpengGL為多邊形設置材質屬性,根據紅綠藍RGB的分量而確定反射光顏色:如下表:

材質 光源的光顏 反射光顏色, 簡介
綠色(0,1,0) 白色(1,1,1) 綠色(0,1,0) 只反射綠光
綠色(0,1,0) 紅色(1,0,0) 黑色(0,0,0) 只反射黑光

 

材質 簡介
void glMaterialf(GLenum face, GLenum pname, GLfloat param); 為多邊形設置材質屬性用於光照計算,它是全局性的, 影響所有繪製的多邊形,直到在次調用
void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); glMaterialf()數組版本

 

face 簡介
GL_FRONT 材質僅應用於多邊形正面
GL_BACK 多邊形反面
GL_FRONT_AND_BACK 多邊形的正反面

 

pname 數值 簡介
GL_AMBIENT {r,g,b,a} 材質的環境光顏色
GL_DIFFUSE {r,g,b,a} 材質的散射光顏色
GL_AMBIENT_AND_DIFFUSE {r,g,b,a} 同時設置材質的環境光和散射光顏色
GL_SPECULAR {r,g,b,a} 材質的鏡面反射光顏色,反射出去的顏色不大於材質顏色

{1.0f,1.0f,1.0f,1.0f}:光會完全反射出去

GL_SHININESS 0-128 鏡面反射光指數

0:不聚焦

128:高度聚焦

GL_EMISSION {r,g,b,a} 材質的反射光顏色

設置多邊形材質的環境光和散射光,函式示例:

  1. glEnable(GL_LIGHTING); // 啟用光照
  2. float white[] = {0f,1.0f,1.0f,1.0f};// 白色
  3. glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white);// 設置材質

OpenGL之聚光燈

OpenGL之聚光燈

聚光燈:在定點光源的基礎加上光線輻射方向,因此光線呈圓錐.

聚光燈參數 範圍 簡介
GL_SPOT_DIRECTION (x,y,z) 聚光燈指向/方向3D矢量

默認值:(0,0,-1)

GL_SPOT_EXPONENT 0-128 焦點/指數:光線從焦點到圓錐的邊界,光的強度不斷衰減,直到邊界消失.

指數越大焦點越小

指數越小焦點越大

GL_SPOT_CUTOFF 0.1-90 圓錐面與指向軸的角度(圓錐角),所以聚光燈的張角為圓錐角的2倍.

張角=圓錐角*2

聚光燈函式使用示例

  1. float Spot_Direction[] = {0f,0.0f,-1,0.0f}; // 聚光燈的指向
  2. float Light_Ambient[] = {0f,1.0f,1.0f,1.0f};// 環境光
  3. float Light_Diffuse[] = {0f,1.0f,1.0f,1.0f};// 散射光
  4. float Light_Position[] = {0f,0.0f,1.0f,1.0f};// 光源位置
  5. glEnable(GL_LIGHTING); // 啟用光照
  6. glLightfv(light,GL_AMBIENT, Light_Ambient);// 環境光分量
  7. glLightfv(light,GL_DIFFUSE, Light_Diffuse);// 散射光分量
  8. glLightfv(light,GL_POSITION,Light_Position);// 光源位置
  9. glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 0f); // 設置聚光燈的角度
  10. glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION, Spot_Direction); // 設置聚光燈的
  11. glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0f); // 設置聚光燈的指數
  12. glEnable(GL_LIGHT0); // 啟用燈光

聚光燈程式示例,可分別設定張角與焦點.下載

  1. 按(/)鍵增加或減小聚光燈焦點指數
  2. 按[/]鍵增加或減小聚光燈張角
  3. 按+/-鍵增加或減小聚光燈亮度
  4. 按SPACE(空格)鍵啟用或禁用聚光燈
  5. 按UP/DOWN鍵正方體繞X軸旋轉
  6. 按LEFT/RIGHT鍵正方體繞Y軸旋轉
  7. 按F1鍵打開幫助
  8. 按ESC鍵重置聚光燈參數

 

OpenGL之法線

OpenGL之法線

法線:即垂直於其表面的單位矢量

OpenGL在進行光照運算前需先計算法線,光與表面相交的角度利用法先計算出反射角度,結合光照與材質計算表面的顏色

法線函式 簡介
void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); 設置法線

(nx,ny,nz):法線坐標分量

法線函式示例

glBegin(GL_POLYGON);

glNormal3f(0.0f,1.0f,0.0f);// 法線

glVertex3f( 0.5f, 0.5f, 0.5f);

glVertex3f( 0.5f, 0.5f,-0.5f);

glVertex3f(-0.5f, 0.5f,-0.5f);

glVertex3f(-0.5f, 0.5f, 0.5f);

glEnd();

法線的計算 簡介
A*B=(Ax*Bz-Az*By, Az*Bx-Ax*Bz, Ax*By-Ay*Bx) 矢量A和B叉積方程

計算兩個3D向量的法線(叉積)

void Cross(float pa[3], float pb[3], float pc[3],float normal[3])

{

float va[3],vb[3];//矢量1,矢量2

float length;//矢量長度

// 計算矢量1

va[0] = pa[0] – pb[0];

va[1] = pa[1] – pb[1];

va[2] = pa[2] – pb[2];

// 計算矢量2

vb[0] = pb[0] – pc[0];

vb[1] = pb[1] – pc[1];

vb[2] = pb[2] – pc[2];

// 計算叉積

normal[0] = va[1]vb[2] – va[2]vb[1];

normal[1] = va[2]vb[0] – va[0]vb[2];

normal[2] = va[0]vb[1] – va[1]vb[0];

// 計算長度

length = sqrt(normal[0]normal[0] + normal[1]normal[1] + normal[2]*normal[2]);

// 計算單位矢量

normal[0] = normal[0] / length;

normal[1] = normal[1] / length;

normal[2] = normal[2] / length;

}

法線演示程式,旋轉正方體觀看光照的變化如上圖:下載

  1. 按+/-鍵增加或減小光照亮度
  2. 按SPACE(空格)鍵啟用或禁用光照
  3. 按UP/DOWN鍵正方體繞X軸旋轉
  4. 按LEFT/RIGHT鍵正方體繞Y軸旋轉
  5. 按Z+LEFT/Z+RIGHT鍵正方體繞Z軸旋轉
  6. 按F1鍵打開幫助
  7. 按ESC鍵重置模型旋轉角度

 

OpenGL之光照

OpenGL之光照

OpenGL光的顏色由紅綠藍(RGB)的分量確定,當光照到表面時,由表面的材質的確定反射的光的顏色(RGB).

OpenGL光有四類 簡介
環境光 無特定照射方向,太陽光
漫射光 有照射方向的光,遇表面光將朝反方向照射, 如燈光不受相機位置影響.
反射光 有照射方向,遇表面光將朝反方向照射.如亮光但受相機位置影響.
放射光 只增加物體的亮度

 

OpenGL光照影響因素 簡介
光源 環境光、漫射光、反射光、放射光
材質 確定反射光RGBA值
法線 由表面的頂點計算方向
相機位置 當光折射時, 相機位置影響反射光的計算

 

光的顏色、位置、方向的設定:
void glLightfv (GLenum light, GLenum pname, const GLfloat *params);

 

glLightfv()參數 簡介
light GL_LIGHT0~ GL_LIGHT7

OpenGL最多可以指定8個光源

pname 光源的參數名見下表
Params 光源的參數值

 

光源的參數名Pname 簡介
GL_AMBIENT 環境光向所有方向照射
GL_DIFFUSE 漫射光具有方向,碰撞到FACE會進行反射
GL_SPECULAR 鏡面反射光
GL_POSITION 光的位置
GL_SPOT_DIRECTION 聚光燈的矢量方向
GL_SPOT_EXPONENT 聚光燈的指數
GL_SPOT_CUTOFF 聚光燈的邊界
GL_CONSTANT_ATTENUATION 衰減值係數常量
GL_LINEAR_ATTENUATION 線性衰減值係數
GL_QUADRATIC_ATTENUATION 二次衰減值係數

 

環境光 簡介
Pname=GL_AMBIENT 環境光
Params=(x,y,z,w) 顏色分量
w=alpha w=0透明

w=1實體

float Light_Ambient[] = { 1.0f,1.0f,1.0f,1.0f};

glLightfv(GL_LIGHT0,GL_AMBIENT, Light_Ambient);

亮白的環境光示例

 

漫射光 簡介
GL_DIFFUSE 漫射光
Params=(x,y,z,w) 顏色分量
w=alpha w=0透明

w=1實體

float Light_Diffuse[] = { 1.0f,1.0f,1.0f,1.0f};

glLightfv(GL_LIGHT0,GL_DIFFUSE, Light_Diffuse);

亮白的漫射光示例

 

光源的位置 簡介
Pname= GL_POSITION 設定光源的位置
Params=(x,y,z,w) 向量或坐標
w=0 定向光源(x,y,z)為向量定義光的照射方向,如太陽.
W=1 定點光源(x,y,z)為坐標定義光源的位置,如燈泡.
float Light_Position[] = {0.0f,0.0f,0.0f,1.0f };

glLightfv(GL_LIGHT0,GL_POSITION,Light_Position);

光源的位置設在原點

 

光衰減(OpenGL支持三類光衰減) 默認值 簡介
ATTENUATION 光線隨著距離的增大其強度減小,但只適用於定點光源,但定向光源是無窮遠的設置衰減是無意義.

衰減因子*光強度 = 光衰減

GL_CONSTANT_ATTENUATION 1.0f 衰減值係數常量
GL_LINEAR_ATTENUATION 0.0f 線性衰減值係數
GL_QUADRATIC_ATTENUATION 0.0f 二次衰減值係數

光照亮度演示程式,定點光源並且全方位輻射.如上圖:下載

  1. 按+/-鍵增加或減小光照亮度
  2. 按SPACE(空格)鍵啟用或禁用光照
  3. 按UP/DOWN鍵正方形繞X軸旋轉
  4. 按LEFT/RIGHT鍵正方形繞Y軸旋轉
  5. 按Z+LEFT/Z+RIGHT鍵繞Z軸旋轉
  6. 按F1鍵打開幫助
  7. 按ESC鍵重置模型旋轉角度

 

OpenGL之漸變

OpenGL之漸變

OpenGL可對每個頂點設定不同的顏色,令模型產生漸變效果.

漸變函式示例:

  1. glShadeModel(GL_SMOOTH);啟用漸變
  2. glBegin(GL_QUADS);繪畫四邊形
  3. glColor3f(0f, 0.0f, 0.0f);glVertex3f(0.0f, 0.0f, 0.0f);黑色
  4. glColor3f(0f, 0.0f, 1.0f);glVertex3f(0.0f, 0.0f, 1.0f);藍色
  5. glColor3f(0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);紫紅色
  6. glColor3f(0f, 0.0f, 0.0f);glVertex3f(1.0f, 0.0f, 0.0f);紅色
  7. glEnd();
漸變 簡介
void glShadeModel (GLenum mode); 設定模型漸變模式(mode)

獲取當前使用的漸變模式

  1. GLenum mode;
  2. glGetIntegerv( GL_SHADE_MODEL,&mode);
漸變模式(mode) 簡介
GL_FLAT 單調,只應用單色
GL_SMOOTH 漸變(默認)

 

GL_FLAT單調顏色應用 簡介
GL_POINTS 應用最後一個頂點的顏色
GL_LINES
GL_TRIANGLES
GL_QUADS
GL_LINE_LOOP 應用分段的第二個頂點的顏色
GL_LINE_STRIP
GL_TRIANGLE_STRIP 應用最後一個頂點的顏色
GL_TRIANGLE_FAN
GL_ GL_QUAD_STRIP
GL_POLYGON 應用第一個頂點的顏色

漸變演示程式:下載

  1. 按UP/DOWN鍵繞X軸旋轉
  2. 按LEFT/RIGHT鍵繞Y軸旋轉
  3. 按Z+LEFT/Z+RIGHT鍵繞Z軸旋轉
  4. 按F1鍵打開幫助
  5. 按ESC鍵模型旋轉角度重置
  6. 按SPACE鍵切換漸變模式

 

OpenGL之屬性

OpenGL之屬性

OpenGL擁有幾百個狀態,通過屬性堆棧的壓棧和出棧,保存與恢復狀態變量.

函式 簡介
void glPushAttrib (GLbitfield mask); 把當前狀態壓入堆棧

Mask:掩碼,保存指定屬性分組

void glPopAttrib (void); 屬性堆棧出棧並恢復狀態

 

掩碼mask 屬性分組
GL_ALL_ATTRIB_BITS 所有屬性分組的OpenGL的狀態變量
GL_VIEWPORT_BIT 視口狀態變量
GL_ENABLE_BIT 以啟用的狀態變量
GL_FOG_BIT 煙霧狀態變量
GL_LIGHTING_BIT 燈光狀態變量
GL_LINE_BIT 直線狀態變量
GL_POINT_BIT 質點狀態變量
GL_POLYGON_BIT 多邊形狀態變量
GL_TEXTURE_BIT 紋理狀態變量

 

OpenGL之變換

OpenGL之變換

渲染3D場景時頂點在最終被渲染到屏幕上之前需經過四類變換

變換(TRANSFORMATION) 簡介
視圖變換(VIEW transformation) 設定攝影機CAMERA的位置
模型變換(MODEL transformation) 移動、旋轉、縮放多邊型模型,將模型局部坐標轉為世界坐標.
投影變換(PROJECTION transformation) 設定視口面積和裁剪平面,用於確定那些多邊型模型位於視口之內.
視口變換(Viewport transformation) 將剪切坐標影射到2D視口(屏幕)
模型視圖變換(modelview transformation) OpenGL將視圖變換與模型變換組合成單獨的模型視圖變換

視圖變換(VIEW transformation) 即攝影機的設定有三種放法,先將觀察矩陣載入單位矩陣glLoadIdentity();相機為於原點,朝向為負Z軸,上方向量為正Y軸.

視圖變換(VIEW transformation) 簡介
gluLookAt () 設定攝影機的位置和方向
glRotatef ()與glTranslatef() 攝影機CAMERA固定在原點,使用旋轉和平移在世界坐標中移動所有模型

模型變換(MODEL transformation)是指通過平移、縮放、旋轉將模型定位與定向

模型變換(MODEL transformation) 簡介
平移glTranslatef() 模型沿向量進行移動
旋轉glRotatef() 模型繞向量進行旋轉
縮放glScalef() 在XYZ三軸指定不同縮放係數放大或縮小模型

投影變換(PROJECTION transformation)是指設定視口面積和裁剪平面,它在模型變換與視圖變換之後執行,用於確定那些多邊型模型位於視口之內.在設定投影之前需要選擇投影矩陣堆棧glMatrixMode(GL_PROJECTION);和載入單位矩陣glLoadIdentity();OpenGL支持兩類投影

投影變換(PROJECTION transformation) 簡介
透視投影

glFrustum()

gluPerspective()

用於3D世界的顯示與真實世界一樣, 多邊型模型呈現近大遠小
正交投影

glOrtho()

gluOrtho2D()

不考濾與攝影機的距離,顯示多邊型模型真實的大小,常用於CAD軟件和2D遊戲

視口變換(Viewport transformation)發生在投影變換之後,視口是指渲染的2D窗口的大小和方向

視口變換(Viewport transformation) 簡介
glViewport() 每當窗口大小發生改變都要重設視口大小

矩陣堆棧

OpenGL的變換運算均對矩陣堆棧的棧頂進行操作.

OpenGL矩陣堆棧 簡介
Modelview Matrix Stack 模型視圖矩陣堆棧
Projection Matrix Stack 投影矩陣堆棧
TEXTURE Matrix Stack 紋理矩陣堆棧
ATTRIB Matrix Stack 屬性矩陣堆棧
CLIENT ATTRIB Matrix Stack 剪切屬性矩陣堆棧
NAME Matrix Stack

 

OpenGL之相機-旋轉和平移

OpenGL之相機-旋轉和平移

相機CAMERA固定在原點,通過旋轉和平移在世界坐標中移動所有模型

相機設定示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glLoadIdentity()將觀察矩陣載入單位矩陣,相機位於原點(0,0,0), 朝向為負Z軸 (0,-90,0)
  3. glRotatef(AngleZ,0f,0.0f,1.0f); 橫搖/側滾角繞Z軸旋轉
  4. glRotatef(AngleY+90,0f,1.0f,0.0f); 偏航/航向角繞Y軸旋,補償90度
  5. glRotatef(AngleX,0f,0.0f,0.0f); 傾斜/俯仰角繞X軸旋轉
  6. glTranslatef(-posX,-posY,-posZ);移動模型坐標
視圖變換(VIEW transformation) 簡介
void glRotatef (

GLfloat angle,

GLfloat x, GLfloat y,GLfloat z);

旋轉

Angle:旋轉角度

x,y,z:軸向量

void glTranslatef (

GLfloat x, GLfloat y, GLfloat z);

平移

x,y,z:偏移向量

 

旋轉
glRotatef(AngleZ,0.0f,0.0f,1.0f); Z軸 橫搖/側滾
glRotatef(AngleY+90,0.0f,1.0f,0.0f); Y軸補償+90度 偏航/航向
glRotatef(AngleX,1.0f,0.0f,0.0f); X軸 傾斜/俯仰

 

平移 簡介
glTranslatef(-posX,-posY,-posZ); 反方向移動模型坐標

相機移動程式演示:下載

  1. 按UP/DOWN鍵前後移動
  2. 按LEFT/RIGHT鍵左右旋轉,繞Y軸旋轉
  3. 小鍵盤4/6繞Z軸旋轉
  4. 小鍵盤8/2繞X軸旋轉
  5. 按F1鍵打開幫助
  6. 按ESC鍵相機返回原點

OpenGL之相機 gluLookAt()

OpenGL之相機 gluLookAt()

函式gluLookAt()允許你設定相機的位置、方向、朝上向量

相機設定示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glLoadIdentity()將觀察矩陣載入單位矩陣,相機為於原點,朝向為負Z軸,上方向量為正Y軸.
  3. gluLookAt() 相對于原點在移動相機
函式 數值 簡介
void gluLookAt (    
GLdouble eyex, 0.0f,0.0f,0.0f, 相機位置設為原點
GLdouble eyey,
GLdouble eyez,
GLdouble centerx, 0.0f,0.0f,-100.0f, 相機朝向負Z軸
GLdouble centery,
GLdouble centerz,
GLdouble upx, 0.0f,1.0f,0.0f 上方向量為正Y軸
GLdouble upy,
GLdouble upz);

 

位置和方向計算 簡介
radians = 3.141592654f * angleA / 180.0f; AngleA: Y軸角度

Radians: 弧度

pos=pos – (speed * cos(radians)); Pos:相機的位置

Speed:移動速度

target=pos+dist*cos(radians); Dist:視距

Target:相機的朝向

相機移動程式演示:下載

  1. 按UP/DOWN鍵前後移動
  2. 按LEFT/RIGHT鍵左右旋轉
  3. 按F1鍵打開幫助
  4. 按ESC鍵相機返回原點
  5. 按+鍵加大直線寬度
  6. 按-鍵減小直線寬度
  7. 按S鍵切換抗鋸齒功能
  8. 按.鍵切換四邊形點畫模式
  9. 按1鍵切換為黃色
  10. 按2鍵切換為綠色
  11. 按3鍵切換為紅色
  12. 按4鍵填充模式
  13. 按5鍵線框模式
  14. 按6鍵頂點模式