利用VC+OpenGL實現融合,霧化,反走樣

 作者: 中國電波傳播研究所青島分所郎銳   出處: 天極網 責任編輯:方舟
  引言

  融合(blending)、霧化(fog)與反走樣(antialiasing)是OpenGL中的三種特殊效果處理方法。融合提供了一種透明或半透明顯示的技術;霧化處理則根據物體距離視點的遠近對其進行恰當的模糊處理;反走樣則可減少在繪製離散化的圖形時所產生的誤差走樣。

  實現融合特效

  融合可將兩種顏色的R、G、B分量按一定比例混在一起形成一種新的顏色,RGBA顏色模式中的A即表示Alpha值,對應於顏色的混合比例。由於只有在RGBA模式中才能對A值進行說明,因此融合不能在顏色索引模式下使用。融合操作可通過源因子(Sr、Sg、Sb、Sa)與目的因子(Dr、Dg、Db、Da)計算鍀出,融合結果爲(Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)每個元素值都在範圍[0, 1]內。可以看出,融合處理的關鍵就是對融合因子(Sr,Sg,Sb,Sa)和(Dr,Dg,Db,Da)的設定。在OpenGL中,源因子和目的因子通過glBlendFunc()函數產生,其函數形式爲:

void glBlendFunc(GLenum sfactor,GLenum dfactor)
  
  通過指定參數sfactor和dfactor來分別指出計算源因子和目的因子的方式。具體取值可參見下表。在產生了融合因子值後,還需調用glEnable(GL_BLEND)和glDisable(GL_BLEND)來啓用、關閉融合處理。

常數 相關因子 融合因子結果
GL_ZERO 源因子或目的因子 (0,0,0,0)
GL_ONE 源因子或目的因子 (1,1,1,1)
GL_DST_COLOR 源因子 (Rd,Gd,Bd,Ad)
GL_SRC_COLOR 目的因子 (Rs,Gs,Bs,As)
GL_ONE_MINUS_DST_COLOR 源因子 (1,1,1,1)-(Rd,Gd,Bd,Ad)
GL_ONE_MINUS_SRC_COLOR 目的因子 (1,1,1,1)-(Rs,Gs,Bs,As)
GL_SRC_ALPHA 源因子或目的因子 (As,As,As,As)
GL_ONE_MINUS_SRC_ALPHA 源因子或目的因子 (1,1,1,1)-(As,As,As,As)
GL_DST_ALPHA 源因子或目的因子 (Ad,Ad,Ad,Ad)
GL_ONE_MINUS_DST_ALPHA 源因子或目的因子 (1,1,1,1)-(Ad,Ad,Ad,Ad)
GL_SRC_ALPHA_SATURATE 源因子 (f,f,f,1); f=min(As,1-Ad)

  下面是應用了融合技術的一個簡單例子,通過圖1的繪製結果可以看出在啓用了融合處理後在兩個具有不同顏色方塊的交疊部分顏色發生了變化,該區域即爲融合所產生的結果:

void CALLBACK Display()
{
 glClear(GL_COLOR_BUFFER_BIT); // 清屏
 glColor4f(0.0, 1.0, 0.0, 0.5); // 繪製矩形
 glRectf(0.1, 0.1, 0.6, 0.6);
 glColor4f(1.0, 1.0, 0.0, 0.7); // 繪製矩形
 glRectf(0.4, 0.3, 0.9, 0.8);
 glFlush(); // 強制繪圖完成
}
void Init()
{
 glEnable (GL_BLEND); // 啓用融合
 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 產生融合因子
 glShadeModel (GL_FLAT); // 設置平面明暗處理
 glClearColor (0.0, 0.0, 0.0, 0.0); // 清屏
}
霧化特效

  霧化是一種模擬自然界中霧氣對場景物體視覺效果產生影響的圖形繪製技術。此技術從視點到物體逐漸將物體的繪製顏色淡化,直至背景色。通過霧化處理可較好的表現出物體到視點的距離感。雖然霧化的具體計算非常複雜,但在OpenGL中的使用卻非常簡單。首先調用glEnable(GL_FOG)以啓用霧化處理,啓用後離視點較遠的物體開始淡化成霧的顏色。然後可通過glFog*()函數來選擇控制霧的濃度和顏色的方程,具體形式爲:

void glFog{if}[v](GLenum pname,TYPE param);
  
  該函數設置了霧化參數和函數,在pname爲GL_FOG MODE時,參數param可以爲GL_EXP(指數)、GL_EXP2(指數平方)和GL_LINEAR(線性);如果參數pname爲GL_FOG_DENSITY、GL_FOG_START或GL_FOG_END,參數param將分別指定在不同霧化數學模型下的不同計算公式參量;在參數pname爲GL_FOG_COLOR時,param將爲一個指向顏色向量的指針。最後,如果有必要,還可以調用函數glHint(GL_FOG_HINT)進一步指定霧化效果。下面給出實現霧化效果的部分具體示例代碼及其繪製結果(圖2):


圖2 霧化效果

void CALLBACK Display()
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清屏
 glPushMatrix(); // 繪製近視點景物
 glTranslatef(-3.0, -1.5, -2.0);
 auxSolidTorus(0.6, 1.5);
 glPopMatrix();
 glPushMatrix(); // 繪製遠視點景物
 glTranslatef(2.0, 0.8, -10.0);
 auxSolidTorus(0.6, 1.5);
 glPopMatrix();
 glFlush(); // 強制繪圖完成
}
void Init()
{
 GLfloat mat_ambient[] = {0.7, 0.6, 0.0, 1.0}; // 設置光照模型
 GLfloat mat_diffuse[] = {0.7, 0.6, 0.0, 1.0};
 GLfloat mat_specular[] = {1.0, 0.0, 1.0, 1.0};
 GLfloat mat_shininess[] = {50.0};
 GLfloat position[] = {5.0, 5.0, 5.0, 1.0};
 glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LESS);
 glLightfv(GL_LIGHT0, GL_POSITION, position);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glFrontFace(GL_CW);
 glEnable(GL_FOG); // 啓用霧化處理
 {
  glFogi(GL_FOG_MODE, GL_LINEAR); // 採用線性變化的霧化效果
  GLfloat fogColor[] = {0.3, 0.3, 0.3, 1.0}; // 指定霧化顏色
  glFogfv(GL_FOG_COLOR, fogColor);
  glFogf(GL_FOG_START, 3.0); // 指定按線性變化時計算公式的參量
  glFogf(GL_FOG_END, 15.0);
  glHint(GL_FOG_HINT, GL_DONT_CARE); //規定霧化效果的質量
 }
}

實現繪圖反走樣

  由於在圖形繪製到屏幕時,數字化的圖像通過離散的象素點來表達,因此所繪製的圖元將會在光滑的曲線上產生鋸齒,這種鋸齒即爲走樣。反走樣也叫做反混淆,它將根據圖元的象素區域來確定象素的顏色值,通過這種處理可在一定程度上消除鋸齒的影響。在OpenGL中,可通過函數glHint()來對圖像質量和繪製速度之間的權衡作一些控制,其函數形式爲:

void glHint(GLenum target,GLenum hint);

  參數target說明控制什麼行爲,具體的,GL_POINT_SMOOTH_HINT、GL_LINE_SMOOTH_HINT和GL_POLYGON_SMOOTH_HINT分別指定點、線和多邊形的採樣質量;GL_FOG_HINT指出霧化是按象素進行(GL_NICEST)還是按頂點進行(GL_FASTEST);GL_PERSPECTIVE_CORRECTION_HINT指定了顏色紋理插值的質量並可糾正由單純線性插值所帶來的一些視覺錯誤。參數hint可以是:GL_FASTEST(給出最有效的選擇)、GL_NICEST(給出最高質量的選擇)、GL_DONT_CARE(沒有選擇)。

  雖然在OpenGL的顏色索引模式下也可以實現反走樣,但仍建議在RGBA模式下進行。對圖元進行反走樣時也要先調用glEnable()函數啓動反走樣(其參數爲GL_POINT、GL_LINE_SMOOTH或GL_POLYGON_SMOOTH)。如果是在RGBA模式下進行反走樣,還必須與融合配合使用,通常使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA分別作爲源和目的因子。下面給出一段在RGBA模式下啓用反走樣繪製多面體的示例代碼,從繪製結果(圖3)可以明顯看出在多邊形的直線邊界出現的鋸齒得到了較好的平滑:

void CALLBACK Display()
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清屏
 auxWireDodecahedron(1.0); // 繪製二十面體
 glFlush(); // 強制繪圖完成
}
void Init()
{
 glEnable(GL_LINE_SMOOTH); // 啓用反走樣
 glEnable(GL_BLEND); // 啓動融合
 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 產生融合因子
 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);// 權衡圖像質量與繪製速度
 glLineWidth(2.0); // 線寬
 glShadeModel(GL_FLAT); // 平面明暗處理
 glClearColor(0.0, 0.0, 0.0, 0.0); // 清屏
 glDepthFunc(GL_LESS); // 激活深度比較
 glEnable(GL_DEPTH_TEST);
}


圖3 反走樣多面體
發佈了58 篇原創文章 · 獲贊 5 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章