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鍵頂點模式

OpenGL之視口變換

OpenGL之視口變換

視口(Viewport)即渲染窗口大小,每當窗口大小發生改變都要使用glViewport()進行設定.視口變換在投影變換之後進行

視口設定 簡介
void glViewport(

GLint x, GLint y, 視口的左下角坐標

GLsizei width, 視口的寬度

GLsizei height); 視口的高度

視口的左下角坐標設為0,0

視口的寬高設為窗口大寬高

 

重設窗口大小,在WM_SIZE(窗口大小發生改變)消息下調用

  1. glViewport(0,0,width,height);將視口重置為新的尺寸
  2. glViewport(0,0,OpenGL_Width,OpenGL_Height);
  3. glMatrixMode(GL_PROJECTION); 設定投影矩陣
  4. glLoadIdentity();載入單位矩陣
  5. gluPerspective(0f, Width/Height,1.0f,1000.0f);
  6. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  7. glLoadIdentity();載入單位矩陣

 

OpenGL之矩陣

OpenGL之矩陣

OpenGL的變換運算均使用4×4矩陣進行.OpenGL使用堆棧保存矩陣.各種變換運算均針對棧頂進行操作.

矩陣 簡介
void glMatrixMode (GLenum mode); 設定當前矩陣堆棧
GL_MODELVIEW 模型視圖矩陣
GL_PROJECTION 投影矩陣
GL_COLOR 顏色矩陣
GL_TEXTURE 紋理矩陣

示例

  1. glMatrixMode(GL_MODELVIEW); 設定當前矩陣為模型視圖矩陣
  2. glLoadIdentity();載入單位矩陣,並且朝向負Z軸
  3. 進行其它變換
矩陣堆棧 簡介
void glPushMatrix(void); 複製當前矩陣(棧頂)並壓棧.
void glPopMatrix(void); 當前矩陣堆棧出棧並丟棄.

將當前坐標系統切換為新坐標系統,渲染完成後恢復原始坐標系統.示例:

  1. glMatrixMode(GL_MODELVIEW);設定模型視圖矩陣
  2. glPushMatrix();複製當前矩陣並壓棧.
  3. glLoadIdentity();載入單位矩陣
  4. glTranslatef(x,y,x);移動坐標系
  5. glPopMatrix();出棧,恢復源始坐標系統

不同矩陣堆棧有不同的深度,可通過glGetIntegerv()獲取

參數 深度 簡介
GL_MAX_MODELVIEW_STACK_DEPTH 32 模型視圖矩陣堆棧的深度
GL_MAX_PROJECTION_STACK_DEPTH 10 投影矩陣堆棧的深度
GL_MAX_TEXTURE_STACK_DEPTH 10 紋理矩陣堆棧的深度
GL_MAX_ATTRIB_STACK_DEPTH 16 屬性矩陣堆棧的深度

獲取模型視圖矩陣深度示例:

  1. GLint params[1];
  2. glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH,params);

OpenGL之旋轉

OpenGL之旋轉

旋轉glRotatef()使模形圍繞軸向量進行旋轉.先設定旋轉矩陣後繪畫模型.

旋轉 簡介
void glRotatef (

GLfloat angle,

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

angle:旋轉角度

逆時針旋轉:角度為正

順時針旋轉:角度為負

xyz:旋轉軸向量

void glRotated (

GLdouble angle,

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

函式示例分別對XYZ進行旋轉:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 繞X軸旋轉glRotatef(angleX,1,0,0);
  4. 繞Y軸旋轉glRotatef(angleY,0,1,0);
  5. 繞Z軸旋轉glRotatef(angleZ,0,0,1);
  6. 繪畫立方體Draw();
旋轉示例 簡介
glRotatef(45.0f,1.0f,0.0f,0.0f); 繞X軸以逆時針方向旋轉45度
glRotatef(-90.0f,0.0f,1.0f,0.0f); 繞Y軸以順時針方向旋轉45度
glRotatef(135.0f,0.0f,0.0f,1.0f); 繞Z軸以逆時針方向旋轉135度

旋轉演示程式如上圖:下載

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

OpenGL之縮放

OpenGL之縮放

縮放glScalef()可在XYZ三軸指定不同縮放系數,放大或縮小模型或坐標系統的大小.

放大: 縮放系數大於(>1),若設為2放大一倍

縮小: 縮放系數為(1.0~0.0),若設為0.5側縮小一倍

函式示例:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 縮放glScalef(x,y,z);參數xyz為縮放系數,若縮放系數为1侧不缩放.縮放操作就是乘以縮放系數.
  4. 繪畫立方體Draw();
縮放 簡介
void glScalef(

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

對模型放大一倍:

1.    縮放glScalef(2,2,2)

2.    後再繪畫Draw()

void glScaled(

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

縮放演示程式如上圖:下載

  1. 按UP/DOWN鍵對XYZ三軸進行模型縮放
  2. 按LEFT/RIGHT鍵繞Y軸旋轉
  3. 按F1鍵打開幫助
  4. 按ESC鍵模型縮放重置

OpenGL之平移

OpenGL之平移

平移Translate可將模型在3D世界中移動,先設定平移矩陣後繪畫模型:

函式示例:

  1. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  2. 載入單位矩陣glLoadIdentity();
  3. 移動3D坐標glTranslatef(x,y,z);參數xyz為3D世界坐標的偏移量
  4. 繪畫立方體Draw();
平移 簡介
void glTranslatef(

GLfloat x,

GLfloat y,

GLfloat z);

單精度版本

如在3D世界(6,6,6)繪畫模型:

1.     先平移glTranslatef(6,6,6)

2.     後在繪畫Draw()

void glTranslated(

GLdouble x,

GLdouble y,

GLdouble z);

雙精度版本

平移演示程式如上圖:下載

  1. 按LEFT/RIGHT鍵模型在X軸中移動
  2. 按UP/DOWN鍵模型在Z軸中移動
  3. 按F1鍵打開幫助
  4. 按ESC鍵模型歸位

OpenGL之投影變換

OpenGL之投影變換

投影變換是指設定視口面積和剪切平面,它在模型變換與視圖變換之後執行,用於確定那些多邊型模型位於視口之內. OpenGL支持兩類投影

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

glFrustum()

gluPerspective()

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

glOrtho()

gluOrtho2D()

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

 

透視投影 簡介
void gluPerspective (

GLdouble fovy,

GLdouble aspect,

GLdouble zNear,

GLdouble zFar);

直接指定視角和屏幕寬高比從而計算觀察截體.
Fovy 可視角度一般設為45度至90度
Aspect 屏幕的寬高比(Width/Height)
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

透視投影 簡介
void glFrustum (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top,

GLdouble zNear,

GLdouble zFar);

觀察截體的計算由近端剪切面與遠端剪切面確定
Left right bottom top 近端剪切面的範圍
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

正交投影 簡介
Void glOrtho (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top,

GLdouble zNear,

GLdouble zFar);

相同的模型不管與攝影機距離的遠近,其呈現的相同大小
left right bottom top 剪切面的範圍
zNear 近端剪切面距離
zFar 遠端剪切面距離

 

正交投影 簡介
void gluOrtho2D (

GLdouble left,

GLdouble right,

GLdouble bottom,

GLdouble top);

相當於glOrtho(left,right,bottom,top,-1,1);
left right bottom top 剪切面的範圍

投影示例

  1. 選擇投影矩陣堆棧glMatrixMode(GL_PROJECTION);
  2. 載入單位矩陣glLoadIdentity()
  3. 設定透視投影或正交投影

投影函式

void Set_Projection_OpenGL(bool Is3D)

{

::glViewport(0,0,OpenGL_Width,OpenGL_Height); // 重置視區尺寸

::glMatrixMode(GL_PROJECTION); // 設定投影矩陣

::glLoadIdentity();// 載入單位矩陣

if(Is3D == true) // 3D投影計算窗口尺寸比例

gluPerspective(54.0f,(GLfloat)OpenGL_Width/(GLfloat)OpenGL_Height,1.0f,1000.0f);

else  // 設為2D投影

gluOrtho2D(0, OpenGL_Width, 0, OpenGL_Height);

::glMatrixMode(GL_MODELVIEW);  // 設定模型視圖矩陣

::glLoadIdentity();// 載入單位矩陣

}

投影演示程式如上圖:下載

  1. 按P鍵在正交投影與透視投影之間切換
  2. 按S鍵切換抗鋸齒功能
  3. 按1鍵切換為黃色
  4. 按2鍵切換為綠色
  5. 按3鍵切換為紅色
  6. 按F1鍵打開幫助
  7. 按ESC鍵旋轉角度清零
  8. 按+鍵加大直線寬度
  9. 按-鍵減小直線寬度

OpenGL之繪畫多邊形

OpenGL之繪畫多邊形

OpenGL多邊形的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫多邊形,繪畫時頂點的走向為逆時針多邊形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換多邊形點畫模式
  6. 按C鍵切換多邊形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵切換為白色
  11. 按5鍵切換為黃色
  12. 按6鍵切換為紅色
  13. 按F1鍵打開幫助
  14. 按ESC鍵清空畫面

繪畫多邊形,頂點不能小於3個

  1. glBegin(GL_POLYGON);準備繪畫多邊形
  2. for (int i = 0; i < count; ++i)
  3. glVertex3f(v[i].x,v[i].y,v[i].z);繪畫多邊形頂點
  4. glEnd();結束繪畫

多邊形其它設定請參考三角形

OpenGL之繪畫四邊形

OpenGL之繪畫四邊形

OpenGL四邊形的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫四邊形,繪畫時頂點的走向為逆時針四邊形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換四邊形點畫模式
  6. 按C鍵切換四邊形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵每四個頂點組成四邊形
  11. 按5鍵頂點相連的四邊形

繪畫四邊形

  1. glBegin(GL_TRIANGLES);準備繪畫四邊形
  2. for (int i = 0; i < count; ++i)
  3. glVertex3f(v[i].x,v[i].y,v[i].z);繪畫四邊形頂點
  4. glEnd();結束繪畫
glBegin()繪畫四邊形參數 簡介
GL_QUADS 每四個頂點組成四邊形
GL_QUAD_STRIP 頂點相連的四邊形,需要把第三第四個頂點的渲染順序交換.

四邊形也屬於多邊形其它設定請參考三角形

 

OpenGL之繪畫三角形

OpenGL之繪畫三角形

OpenGL三角形屬於多邊形.演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫三角形,繪畫時頂點的走向為逆時針三角形為正面,否則為背面.
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換抗鋸齒功能
  5. 按.鍵切換三角形點畫模式
  6. 按C鍵切換三角形隱面裁剪
  7. 按1鍵填充模式
  8. 按2鍵線框模式
  9. 按3鍵頂點模式
  10. 按4鍵每三個頂點組成三角形
  11. 按5鍵頂點相連的三角形
  12. 按6鍵第一個頂點作為三角形的共同頂點

繪畫三角形

  1. glBegin(GL_TRIANGLES);準備繪畫三角形
  2. glVertex3f(x1,y1,z1);繪畫三角形頂點1
  3. glVertex3f(x2,y2,z2);繪畫三角形頂點2
  4. glVertex3f(x3,y3,z3);繪畫三角形頂點3
  5. glEnd();結束繪畫
glBegin()繪畫直線參數 簡介
GL_TRIANGLES 每三個頂點組成三角形
GL_TRIANGLE_STRIP 頂點相連的三角形
GL_TRIANGLE_FAN 第一個頂點作為三角形的共同頂點

因屏幕由像素組成,三角形邊緣會產生鋸齒,啟用抗鋸齒算法後會變得平滑,並修改邊緣像素的顏色:

  1. glEnable(GL_POLYGON_SMOOTH);啟用多邊形的平滑模式(抗鋸齒功能)
  2. glEnable(GL_BLEND);啟用混合

多邊形模式(正面默認為填充模式)

void glPolygonMode(GLenum face,GLenum mode);

多邊形面(face) 簡介
GL_FRONT 多邊形正面:頂點的走向為逆時針(默認)
GL_BACK 多邊形背面:頂點的走向為順時針
GL_FRONT_AND_BACK 正面與背面

 

多邊形模式(mode) 簡介
GL_FILL 填充模式:對多邊形內部進行顏色填充(默認)
GL_LINE 線框模式:多邊形只繪畫直先不填充
GL_POINT 頂點模式:只繪畫多邊形頂點

設置多邊形隱面裁剪

3D圖形渲染的工作量非常大,把不可見的面剔除則可節減大量變換和渲染時間.

  1. glEnable(GL_CULL_FACE);啟用隱面裁剪
  2. glCullFace(GL_BACK);設背面為隱面
  3. glFrontFace(GL_CCW);多邊形正面使用逆時針
正面模式(MODE) 簡介
GL_CCW 多邊形正面使用逆時針
GL_CW 多邊形反面使用順時針

多邊形點畫模式可用於簡單的填充(不太常用)

void glPolygonStipple(GLushort * mask);

mask:掩碼大小寬8byte*高16byte=128(byte)=1024(bit),1填充像素,0不填充

  1. glEnable(GL_POLYGON_STIPPLE);啟用點畫模式
  2. glPolygonStipple(mask);設置掩碼

 

OpenGL之繪畫直線

OpenGL之繪畫直線

OpenGL支持基本幾何直線繪畫,使用glVertex()生成繪畫相連直線的演示程式如上圖:下載

  1. 按鼠標左鍵點擊繪畫相連直線
  2. 按+鍵加大直線寬度
  3. 按-鍵減小直線寬度
  4. 按S鍵切換直線抗鋸齒功能
  5. 按.鍵切換直線點畫模式(虛線)
  6. 按1鍵切換为白色
  7. 按2鍵切換为黄色
  8. 按3鍵切換为红色
  9. 按4鍵每兩個頂點組成的直線
  10. 按5鍵由多個頂點組成的相連直線
  11. 按6鍵由多個頂點組成相連的閉合直線

繪畫直線

  1. glLineWidth(width);設置直線寬度
  2. glBegin(GL_LINE_STRIP);準備繪畫連續直線
  3. glVertex3f(x1,y1,z1);繪畫直線頂點1
  4. glVertex3f(x2,y2,z2);繪畫直線頂點2
  5. glEnd();結束繪畫
glBegin()繪畫直線參數 簡介
GL_LINES 由兩個頂點組成的直線
GL_LINE_STRIP 由多個頂點組成的相連直線
GL_LINE_LOOP 由多個頂點組成相連的閉合直線,第一個與最後一個頂點自動相連

因屏幕由像素組成,直線邊緣會產生鋸齒,OpenGL有抗鋸齒算法,啟用後直線會變得平滑,並修改邊緣像素的顏色:

  1. glEnable(GL_LINE_SMOOTH);啟用直線的平滑模式(抗鋸齒功能)
  2. glEnable(GL_BLEND);啟用混合

點畫模式通常用繪畫虛線

void glLineStipple(GLint factor,GLushort pattern);

factor:模板每BIT對應像素量

pattern:由2個Btye組成點畫模板

  1. glEnable(GL_LINE_STIPPLE);設置點畫模式(虛線)
  2. glLineStipple(5,0xfafa);設置模板

開啟直線抗鋸齒算法後,直線寬度範圍受到限制,若輸入不受支持直線寬度,會改為最接近的支持數值:

  1. GLfloat widths[2];浮點數數組
  2. glGetFloatv(GL_LINE_WIDTH_RANGE, widths);提取直線寬度的範圍
  3. GLfloat min = widths[0];最小
  4. GLfloat max = widths[1];最大
  5. GLfloat granularity;
  6. glGetFloatv(GL_LINE_WIDTH_GRANULARITY,&granularity);提取直線寬度的粒度
  7. GLfloat width;
  8. glGetFloatv(GL_LINE_WIDTH,&width);獲取當前直線寬度
  9. width = width + granularity;加大
  10. width = width – granularity;減小
  11. glPointSize(width);設置當前直線寬度,但不能在glBegin()與glEnd()之間調用

OpenGL之繪畫頂點

OpenGL之繪畫頂點

OpenGL支持基本幾何頂點繪畫,使用glVertex()生成畫點的演示程式如上圖:下載

  1. 按鼠標左鍵繪畫頂點
  2. 按+鍵加大頂點尺寸
  3. 按-鍵減小頂點尺寸
  4. 按S鍵切換抗鋸齒功能
  5. 按1鍵切換為白色
  6. 按2鍵切換為黃色
  7. 按3鍵切換為紅色

繪畫單個頂點

  1. glPointSize(size);設置頂點的大小
  2. glBegin(GL_POINTS); 準備繪畫
  3. glVertex3f(x,y,z); 繪畫頂點(浮點數版)
  4. glVertex3i(x,y,z); 繪畫頂點(整數版)
  5. glEnd(); 結束繪畫

因屏幕由像素組成,縮放頂點時邊緣會產生鋸齒,OpenGL有其抗鋸齒算法,啟用後頂定會由方變圓,並修改邊緣像素的顏色:

if (glIsEnabled(GL_POINT_SMOOTH) == false)// 判斷抗鋸齒是否已啟用

{

glEnable(GL_POINT_SMOOTH); // 啟用頂點的平滑模式(抗鋸齒功能)

glEnable(GL_BLEND);// 需啟用混合

}

開啟抗鋸齒算法後,頂點尺寸範圍受到限制,若輸入不受支持頂點的尺寸,會改為最接近的支持數值:

  1. GLfloat sizes[2];浮點數數組
  2. glGetFloatv(GL_POINT_SIZE_RANGE,sizes);提取頂點尺寸的範圍
  3. GLfloat min = sizes[0];最小
  4. GLfloat max = sizes[1];最大
  5. GLfloat granularity;
  6. glGetFloatv(GL_POINT_SIZE_GRANULARITY,&granularity);提取頂點尺寸的粒度
  7. GLfloat size;
  8. glGetFloatv(GL_POINT_SIZE,&size);獲取當前頂點尺寸
  9. size = size + granularity;加大
  • size = size – granularity;減小
  • glPointSize(size);設置當前頂點的大小,但不能在glBegin()與glEnd()之間調用

OpenGL之速度與質量

OpenGL之速度與質量

因顯卡性能各異,所以OpenGL可給用戶在速度與質量之間作出選擇,參數在下表給出.並給出示例代碼:

Void glHint(GLenum target, GLenum hint);

HINT 簡介
GL_FASTEST 使用最快速度和效率,但畫面質量有所下降.
GL_NICEST 使用最高畫面質量,但運行速度有所下降
GL_DONT_CARE 由顯卡的OpenGL驅動在速度和質量之間作出選擇

 

TARGET 簡介
GL_POINT_SMOOTH_HINT 指定在進行反鋸齒的操作中,點、線、多邊形的抽樣質量
GL_LINE_SMOOTH_HINT
GL_POLYGON_SMOOTH_HINT
GL_FOG_HINT 若hint設為GL_NICEST,煙霧的計算將以每像素的形式執行

若hint設為GL_FASTEST,煙霧的計算將以每頂點的形式執行

GL_PERSPECTIVE_CORRECTION_HINT 指定顏色和紋理坐標的插值品質

設置OpenGL性能

hint:建議性能

GL_FASTEST:速度優先

GL_NICEST:最高畫面質量

GL_DONT_CARE:由顯卡驅動決定

void Set_Hint_OpenGL(GLenum hint)

{

glHint(GL_POINT_SMOOTH_HINT,          hint);// 點

glHint(GL_LINE_SMOOTH_HINT,           hint);// 線

glHint(GL_POLYGON_SMOOTH_HINT,        hint);// 多邊形

glHint(GL_FOG_HINT,                   hint);// 煙霧

glHint(GL_PERSPECTIVE_CORRECTION_HINT,hint);//紋理坐標

}

OpenGL之錯誤碼

OpenGL之錯誤碼

OpenGL內部有ERROR錯誤標記,若向OpenGL的函式傳遞不正確的參數,函式會設置錯誤碼並返回.錯誤代碼一但產生就不會修改,直到調用

GLenum error = glGetError();

它將返回下表的錯誤代碼,並把標記重設為GL_NO_ERROR:

錯誤碼 簡介
GL_NO_ERROR 無錯誤
GL_INVALID_ENUM 傳遞不被支持枚舉型(enum)數值時產生此錯誤
GL_INVALID_VALUE 傳遞超出可接受範圍的數值時產生此錯誤
GL_INVALID_OPERATION 傳遞參數未能運行或當前設置未能運行,這錯誤碼較上兩者更難以追查錯誤
GL_STACK_OVERFLOW 堆盞溢出
GL_STACK_UNDERFLOW 堆盞不平衡
GL_OUT_OF_MEMORY 內存耗盡或內存洩漏
GL_TABLE_TOO_LARCE 過多使用TABLE而產生

 

OpenGL版本

OpenGL之查詢版本

調用glGetString()可以很方便提取顯卡的OpenGL信息,但需在wglMakeCurrent()之後調用,否則返回NULL.我使用此函式製作讀取OpenGL版本程式:下載

函式原型:

const GLubyte * glGetString(GLenum name);

name參數 簡介
GL_VENDOR 顯卡的製造商名稱
GL_RENDERER 顯卡型號和CPU的信息
GL_VERSION 顯卡驅動主輔版本號
GL_EXTENSIONS OpenGL擴展支持列表,以空格進行分割

 

OpenGL之全屏

OpenGL之全屏

從DOS,街機到手機遊戲都是以全屏出現,全屏顯示只需加入小量代碼

  1. 填充DEVMODE數據結構
  2. 設定屏幕寬度dmPelsWidth
  3. 設定屏幕高度dmPelsHeight
  4. 設定屏幕像素BIT數dmBitsPerPel
  5. 設定有效字dmFields
  6. 調用ChangeDisplaySettings(&devmode,CDS_FULLSCREEN)進入全屏模式,成功設定返回DISP_CHANGE_SUCCESSFUL
  7. 創建窗口CreateWindowEx()
  8. 擴展樣式設為全屏窗口WS_EX_APPWINDOW
  9. 窗口樣式樣式設為無邊框窗口WS_POPUP
  10. 窗口寬高需等於屏幕寬高
  11. 隱藏鼠標ShowCursor(false);

設定為全屏需在CreateWindow之前調用,下面是完整的代碼

bool Set_FullScreen_OpenGL(int screenWidth,int screenHeight,int screenBpp )

{

DEVMODE devmode;

memset(&devmode,0,sizeof(devmode));// 清零

devmode.dmSize = sizeof(DEVMODE);// 填充DEVMODE

devmode.dmPelsWidth  = screenWidth;// 屏幕寬度

devmode.dmPelsHeight = screenHeight;// 屏幕高度

devmode.dmBitsPerPel = screenBpp;// 屏幕像素BIT數

devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;// 設定有效字段

// 設為全屏

if(ChangeDisplaySettings(&devmode,CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)

OpenGL_FullScreen = true;

else

OpenGL_FullScreen = false;

return OpenGL_FullScreen;

}

退出程序時恢復為窗口模式

bool Set_Window_OpenGL()

{ // 設為窗口模式

if(ChangeDisplaySettings(NULL,0) == DISP_CHANGE_SUCCESSFUL)

{

OpenGL_FullScreen = false;

ShowCursor(true);// 顯示鼠標

}

return OpenGL_FullScreen;

}

OpenGL之重設窗口大小

OpenGL之重設窗口大小

當OpenGL窗口的大小發生改變時,OpenGL窗口會變形需要重新設定以適應新的窗口大小.

  1. 收到WM_SIZE消息後獲取窗口大小,高度為HIWORD(lParam),寬度為LOWORD(lparam)
  2. 重置視區尺寸glViewport(0,0,width,height);
  3. 設定投影矩陣glMatrixMode(GL_PROJECTION);
  4. 載入單位矩陣glLoadIdentity();
  5. 計算窗口尺寸比例gluPerspective();
  6. 設定模型視圖矩陣glMatrixMode(GL_MODELVIEW);
  7. 載入單位矩陣glLoadIdentity();

給出重設窗口大小完整代碼

void Set_WindowSize_OpenGL(int width,int height)

{

if(height == 0)

height = 1;// 确保分母不为0

// 重置视区尺寸

::glViewport(0,0,width,height);

// 设定投影矩阵

::glMatrixMode(GL_PROJECTION);

// 载入单位矩阵

::glLoadIdentity();

// 计算窗口尺寸比例

gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

// 设定模型视图矩阵

::glMatrixMode(GL_MODELVIEW);

// 载入单位矩阵

::glLoadIdentity();

}

OpenGL之繪製環境

OpenGL之繪製環境

繪製環境Context用於記錄OpenGL的設置和命令,但繪製環境必需在像素格式設置完成後調用.下麵是簡介和源碼

繪製環境 簡介
HGLRC 繪製環境的句柄
HGLRC wglCreateContext(HDC hDC); 創建繪製環境,並返回繪製環境句柄, 在WM_CREATE消息下調用
BOOL wglDeleteContext(HDC hDC,HGLRC hRC); 刪除繪製環境, 在WM_CLOSE消息下調用
BOOL wglMakeCurrent(HDC hDC,HGLRC hRC); 設置當前繪製環境,若HGLRC設為NULL則取消當前設定的繪製環境

創建繪製環境

void Create_Context_OpenGL(HDC hDC)

{ //創建繪製環境

hGLRC = ::wglCreateContext(hDC);

// 設置為繪製環境

::wglMakeCurrent(hDC,hGLRC);

}

刪除繪製環境

void Delete_Context_OpenGL(HDC hDC)

{ // 取消設定的為繪製環境

::wglMakeCurrent(hDC,NULL);

// 刪除繪製環境

::wglDeleteContext(hGLRC);

}

OpenGL之像素格式

OpenGL之像素格式

在OpenGL工作之前需要設定當前環境設備(顯卡)像素格式,只需三步:

設定像素格式 簡介
PIXELFORMATDESCRIPTOR 填充像素格式
ChoosePixelFormat() 獲取顯卡支持的像素格式,返回索引
SetPixelFormat() 設置當前環境設備(顯卡)的像素格式

PIXELFORMATDESCRIPTOR需要填補的數值較多

字段 填充數值 像素格式簡介
iPixelType sizeof(PIXELFORMATDESCRIPTOR) 結構的大小
nVersion 1 版本號填1
dwFlags PFD_DRAW_TO_WINDOW 支持在窗口繪畫
PFD_DRAW_TO_BITMAP 支持在位圖繪畫
PFD_SUPPORT_GDI 緩存支持GUI繪畫
PFD_SUPPORT_OPENGL 緩存支持OPENGL繪畫
PFD_GENERIC_ACCELERATED
PFD_GENERIC_FORMAT
PFD_NEED_PALETTE
PFD_NEED_SYSTEM_PALETTE
PFD_DOUBLEBUFFER 支持雙緩存
PFD_STEREO
PFD_SWAP_LAYER_BUFFERS 支持交換Layer緩存
PFD_DEPTH_DONTCARE 支持Z緩存
PFD_DOUBLEBUFFER_DONTCARE
PFD_STEREO_DONTCARE
iPixelType PFD_TYPE_RGBA RGBA像素
PFD_TYPE_COLORINDEX 256色使用調色板索引
cColorBits 32、24、16、8 每像素所占字節數
cRedBits 0 紅色所占Bit數
cRedShift 0 紅色偏移Bit量
cGreenBits 0 綠色所占Bit數
cGreenShift 0 綠色偏移Bit量
cBlueBits 0 藍色所占Bit數
cBlueShift 0 藍色偏移Bit量
cAlphaBits 0 Alpha所占Bit數
cAlphaShift 0 Alpha偏移Bit量
cAccumBits 0 累加緩存Bit數
cAccumRedBits 0 紅色累加緩存Bit數
cAccumGreenBits 0 綠色累加緩存Bit數
cAccumBlueBits 0 藍色累加緩存Bit數
cAccumAlphaBits 0 Alpha累加緩存Bit數
cDepthBits 16 z-buffer(Z緩存)大小
cStencilBits 0 模板緩存Bit數
cAuxBuffers 0 輔助緩存Bit數
iLayerType 0 繪製平面
bReserved 0 保留字段
dwLayerMask 0 不在使用
dwVisibleMask 0 透明色掩碼索引
dwDamageMask 0 不在使用

 

最後給出完整代碼

void Setup_PixelFormat_OpenGL(HDC hDC)

{

PIXELFORMATDESCRIPTOR pfd;

int index;

pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);// 結構的大小

pfd.nVersion = 1;//版本號填1

pfd.dwFlags  = PFD_DRAW_TO_WINDOW |//  支持窗口

PFD_SUPPORT_OPENGL |// 支持OPENGL

PFD_DOUBLEBUFFER   ;// 支持雙緩存

pfd.iPixelType = PFD_TYPE_RGBA;// 像素數據類型RGBA

pfd.cColorBits = 16;// 16bit每像素所占字節數

pfd.cRedBits   = 0;// 紅色所占Bit數

pfd.cRedShift  = 0;// 紅色偏移Bit量

pfd.cGreenBits   = 0;// 綠色所占Bit數

pfd.cGreenShift  = 0;// 綠色偏移Bit量

pfd.cBlueBits   = 0;// 藍色所占Bit數

pfd.cBlueShift  = 0;// 藍色偏移Bit量

pfd.cAlphaBits  = 0;// Alpha所占Bit數

pfd.cAlphaShift  = 0;// Alpha偏移Bit量

pfd.cAccumBits      = 0;// 累加緩存Bit數

pfd.cAccumRedBits   = 0;// 紅色累加緩存Bit數

pfd.cAccumGreenBits = 0;// 綠色累加緩存Bit數

pfd.cAccumBlueBits  = 0;// 藍色累加緩存Bit數

pfd.cAccumAlphaBits = 0;// Alpha累加緩存Bit數

pfd.cDepthBits      = 16;// 16bit z-buffer(Z緩存)大小

pfd.cStencilBits    = 0;// 模板緩存Bit數

pfd.cAuxBuffers     = 0;// 輔助緩存Bit數

pfd.iLayerType      = 0;// 無繪製平面

pfd.bReserved       = 0;// 保留字段

pfd.dwLayerMask     = 0;// 不在使用

pfd.dwVisibleMask   = 0;// 透明色掩碼索引

pfd.dwDamageMask    = 0;// 不再使用了

// 獲取當前環境設備(顯卡)支持的像素格式,返回索引

index = ::ChoosePixelFormat(hDC,&pfd);

// 設置當前環境設備(顯卡)的像素格式

::SetPixelFormat(hDC,index,&pfd);

}

OpenGL簡介

OpenGL簡介

在DOS時代因為當時硬件品類小,程序直接控制硬件,但當硬件品類不斷增加,要對所有硬件進行支持變得不現實.所以便有OpenGL的出現,把硬件的支持交還給硬件開發商.

最初OpenGL由Silicon Graphics,Inc(SGI)開發的一個可以跨平臺使用的圖形編程接口, GL就是Graphics library的縮寫,最初用於UNIX工作站.

1992年OpenGL Architecture Review Board(ARB)委員會創建,由ATI,Compaq,Evans&Sutherland,Hewlett-packard,IBM,Intel,Intergraph,Nvidia,Microsoft,Silicon Graphics組成

1995年微軟在遊戲廠商進逼下不得已在WinNT中支持OpenGL

程式庫 簡介 下載點
OpenGL 標準OpenGL 下載1下載2
GLU (實用庫)OpenGL的補充

 

GLUT (OpenGL Utility Toolkit)應用工具包,與系統無關且便於移於移植.作為AUX庫的的替代品.

 

下載

 

下載並解壓後,更據文檔的擴展名拷貝到各自對應的VC目錄

文件 文檔類形 目錄
include files .h文檔 C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
Library files .lib文檔 C:\Program Files\Microsoft Visual Studio\VC98\Lib
Executable files .dll文檔 C:\Program Files\Microsoft Visual Studio\VC98\Bin

 

程式頭文檔 程式庫文檔 程式二進制文檔 簡介
gl.h Opengl32.lib OPENGL32.DLL 標準OpenGL頭文件
glu.h Glu32.lib GLU32.DLL OpenGL實用工具庫
glaux.h GLAUX.LIB OpenGL輔助函數庫
glut.h glut.lib glut.dll OpenGL應用工具包
glut32.lib glut32.dll