OPENGL的特殊效果,融合,霧化,反走樣(轉)

NO IMAGE

1 融合
前面從未接觸過透明或半透明的物體,因為我們從未啟用過融合處理 所謂融合就是假設在RGBA模式下,源色為(Rs,Gs,Bs,As),目標色為 (Rd,Gd,Bd,Ad),源因子為(Sr,Sg,Sb,Sa),目的因子為(Dr,Dg,Db,Da)
則融合的最終效果為:(Rs*Sr Rd*Dr,Gs*Sg Gd*Dg,Bs*Sb Bd*Db,As*Sa Ad*Da)
然後再歸一。公式挺複雜,不過仔細看看,跟平常的融合倒是定性一致。
關鍵就是如何設定融合因子(Sr,Sg,Sb,Sa)(Dr,Dg,Db,Da)來實現不同的融合效果
利用函式:
void glBlendFunc(GLenum sfactor,GLenum dfactor);
其中兩個引數可以取下面值:

取值 相關因子 計算後融合因子
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)-min(As,1-Ad)

還要利用glEnable(GL_BLEND) glDisable(gl_blend)來啟用、關閉融合處理。
////////////////////////////////////////////////
//sample.cpp
#include “glos.h”
#include
#include
#include “windows.h”
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);

void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow(“sample1”);
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

//設定融合效果並啟用
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// glDepthFunc(GL_LESS);
// glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
gluOrtho2D(0.0,1.0,0.0,1.0*(GLfloat)h/(GLfloat)w);
else
gluOrtho2D(0.0,1.0*(GLfloat)w/(GLfloat)h,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
}

void CALLBACK display(void)
{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//三個不同顏色和透明度的方塊重合,顏色融合的效果
glColor4f(1.0,0.0,0.0,0.7);
glRectf(0.25,0.4,0.75,0.9);

glColor4f(0.0,1.0,0.0,1.0);
glRectf(0.1,0.1,0.6,0.6);

glColor4f(0.0,0.0,1.0,0.3);
glRectf(0.4,0.1,0.9,0.6);

glFlush();

}
void main(void)
{
myinit();

auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
/////////////////////////////////////////////////////////
你可以試試調節引數大小,體會一下個引數的含義。

2 反走樣Anti-aliasing
由於計算機以離散點生成圖形,生成圖形必然與真實景物存在差距,這種差距表現為:直線或光滑曲面的鋸齒、花紋失去原有色彩形狀、細小物體在畫面的消失等。統統叫做走樣。反走樣可以減少這種情況。粗略設想一下,就是把原來邊界的地方鋸齒部分用低飽和度的點補上,這樣既不影響整體輪廓,又獲得較好的平滑效果。反走樣前提供“提示”採用函式:

void glHint(GLenum target,GLenum hint);
其中hint可以是:GL_FASTEST 給出最有效的選擇
GL_NICEST 給出最高質量的選擇
GL_DONT_CARE 沒有選擇

target 意義

GL_POINT_SMOOTH_HINT 指定點、
GL_LINE_SMOOTH_HINT 線、
GL_POLYGON_SMOOTH_HINT 多邊形的取樣質量

GL_FOG_HINT 指出霧化計算是按每個象素進行(GL_NICEST)
還是按每個頂點進行(GL_FASTEST)

GL_PERSPECTIVE_CORRECTION_HINT 指定顏色紋理插值的質量
其中GL_PERSPECTIVE_CORRECTION_HINT用以糾正單純線性插值帶來的觀察錯誤。

當然最主要的工作還是glEnable()來完成的。

先給出一個點、線反走樣的例子。需要說明的是這個工作最好在RGBA模式下進行,首先利用glEnable()(引數為GL_POINT_SMOOTH GL_LINE_SMOOTH或 GL_POLYGON_SMOOTH)啟用反走樣。在RGBA模式下啟用反走樣,必須啟用融合處理。
而且最常用的融合因子分別是:GL_SRC_ALPHA(源)和GL_ONE_MINUS_SRC_ALPHA
或GL_ONE(目的)。

比較採用反走樣後的結果,可以明顯看出多變形直線邊界出鋸齒得到了平滑。

3 霧化
最後來介紹霧化,霧化不但可以使景物更加真實,而且大大減少計算量,開過F22的玩家不會忘記霧化的遠近直接影響遊戲的速度吧。一般的霧化模型是考慮把物體實際顏色和霧化顏色向融合。具體霧化的濃淡有定義的數學模型來決定包括線性變化、指數變化和指數平方變化等。定義霧化也很簡單,只要遵循下面步驟:
一 啟用霧化 glEnable(GL_FOG);
二 控制霧化 glFog*()
void glFog{if}[v](GLenum,TYPE param);

當GLenum是GL_FOG MODE時,param可以是GL_EXP(指數)
GL_EXP2(指數平方)
GL_LINEAR(線性)

當GLenum是GL_FOG_DENSITY GL_FOG_START GL_FOG_END時,param分別指定不同
霧化數學模型下不同計算公式的參量,具體可以參閱連機手冊。

當GLenum時GL_FOG_COLOR時,param是指向顏色向量的指標
三 必要時可以用glHint(GL_FOG_HINT,XX)指定霧化效果
下面給出例子:
///////////////////////////////////////////////////////////////////
//sample.cpp
#include “glos.h”
#include
#include
#include “windows.h”
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);

void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow(“sample1”);
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

GLfloat mat_ambient[]={0.0,0.1,0.8,1.0};
GLfloat mat_diffuse[]={0.0,0.3,0.6,1.0};
GLfloat mat_specular[]={1.0,0.0,1.0,1.0};
GLfloat mat_shininess[]={15.0};
GLfloat position[]={5.0,5.0,5.0,0.0};
GLfloat fogColor[4]={0.6,0.6,0.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);
glLightfv(GL_LIGHT0,GL_POSITION,position);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glFrontFace(GL_CW);
// glEnable(GL_POLYGON_SMOOTH);
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA,GL_ONE);

glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);

//啟用霧化處理
glEnable(GL_FOG);
{
//採用線性變化的霧化效果
glFogi(GL_FOG_MODE,GL_LINEAR);
//指定霧化顏色(黃色)
glFogfv(GL_FOG_COLOR,fogColor);
//指定按線性變化時計算公式的參量
glFogf(GL_FOG_START,3.0);
glFogf(GL_FOG_END,15.0);
//規定霧化效果的質量
glHint(GL_FOG_HINT,GL_DONT_CARE);
}
// glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{

glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if(w<=h*3)
glOrtho(-6.0,6.0,-2.0*(GLfloat)h*3/(GLfloat)w,
2.0*(GLfloat)h*3/(GLfloat)w,0.0,10.0);
else
glOrtho(-6.0*(GLfloat)h/(GLfloat)w,
6.0*(GLfloat)h/(GLfloat)w,-2.0,2.0,0.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void CALLBACK display(void)
{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

//在不同遠近(Z方向)繪製同樣大小、顏色的環,顯示霧化的效果
glPushMatrix();
glTranslatef(-3.0,-1.5,-3.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glPushMatrix();
glTranslatef(-0.5,-0.5,-6.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glPushMatrix();
glTranslatef(2.0,0.5,-8.0);
auxSolidTorus(0.6,1.5);
glPopMatrix();

glFlush();

}
void main(void)
{
myinit();

auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
////////////////////////////////////////////////////////////////////