第十講 特殊效果操作

ingenuus發表於2007-11-12
每個物體在不同的環境在會有不同的視覺效果。為了使效果更加真實需要增加特殊效果。

  例8:繪製三個互相重疊的矩形,這三個矩形從左到右分別為綠、紅、藍。其中紅色、藍色矩形的透明度分別為50%的透明度,即alpha值為0.5,如圖九所示。

#include <stdlib.h>
#include <GL/glut.h>
void myInit(void)
{
 glClearColor(0.2,0.8,0.8,0.0);//將背景設定為湖藍色
 glEnable(GL_BLEND);//啟用GL_BLEND
 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//指定畫素的數學演算法
 glEnable(GL_FLAT);
}

void myDisplay(void)
{
 glClear(GL_COLOR_BUFFER_BIT);

 /*繪製一個綠色的矩形 alpha = 1.0*/
 glColor4f(0.0,1.0,0.0,1.0);

 glBegin(GL_POLYGON);
 glVertex3f(-0.75,0.5,0.0);
 glVertex3f(-0.75,-0.75,0.0);
 glVertex3f(0.5,-0.75,0.0);
 glVertex3f(0.5,0.5,0.0);
 glEnd();

 /*繪製一個紅色的矩形 alpha = 0.5*/
 glColor4f(1.0,0.0,0.0,0.5);

 glBegin(GL_POLYGON);
 glVertex3f(-0.25,1.0,0.0);
 glVertex3f(-0.25,-0.25,0.0);
 glVertex3f(1.0,-0.25,0.0);
 glVertex3f(1.0,1.0,0.0);
 glEnd();

 /*繪製一個藍色的矩形 alpha = 0.5*/
 glColor4f(0.0,0.0,1.0,0.5);

 glBegin(GL_POLYGON);
 glVertex3f(0.25,1.5,0.0);
 glVertex3f(0.25,0.25,0.0);
 glVertex3f(1.5,0.25,0.0);
 glVertex3f(1.5,1.5,0.0);
 glEnd();

 glFlush();
}

void myReshape(int w,int h)
{
 glViewport(0,0,w,h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();

 if(w<h)
  glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5);
 else
  glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,-1.5,1.5);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glTranslatef(-0.4,0.0,0.0);
}

int main(int argc,char ** argv)
{
 /*初始化*/
 glutInit(&argc,argv);
 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
 glutInitWindowSize(300,400);
 glutInitWindowPosition(200,200);

 /*建立視窗*/
 glutCreateWindow("BLEND POLYGON");

 /*繪製與顯示*/
 myInit();
 glutReshapeFunc(myReshape);
 glutDisplayFunc(myDisplay);

 /*進入GLUT事件處理迴圈*/
 glutMainLoop();
 return(0);
}


圖九:三個互相重疊的矩形

  ·glBlendFunc(GLenum sfactor,GLenum dfactor) 指定畫素演算法。sfactor指定紅,綠,藍及alpha源混合因素是如何計算的。dfactor指定紅,綠,藍及alpha目標混合因素是如何計算的。

  例9:繪製一個被霧化的圓錐體,如圖十所示,為了觀察不同的霧化引數,程式中加入了鍵盤操作。"shift+1"," shift+2"鍵分別增加和減弱霧化濃度,"shift+3"設定霧化的起始點和終止點,"shift+4"和"shift+5"鍵改變霧化方程,"shift+6"將霧化顏色由白改為綠色,如圖十一所示。

#include <stdlib.h>
#include <GL/glut.h>

GLfloat light_ambient[] = {0.1,0.1,0.1,0.0};
GLfloat light_diffuse[] = {1.0,1.0,1.0,0.0};
GLfloat light_specular[] = {1.0,1.0,1.0,0.0};
GLfloat light_position[] = {-10.0,0.0,5.0,0.0};

GLfloat material_ambient[] = {0.1745,0.01175,0.01175};
GLfloat material_diffuse[] = {0.61424,0.04136,0.04136};
GLfloat material_specular[] = {0.727811,0.626959,0.62659};

GLfloat fogColorWhite[] = {1.0,1.0,1.0,1.0};
GLfloat fogColorGreen[] = {0.0,1.0,0.0,1.0};
float fogDensity = 0.02;


void myInit(void)
{
 /*設定背景色*/
 glClearColor(0.5,0.5,0.5,1.0);

 /*設定光照*/
 glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
 glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
 glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
 glLightfv(GL_LIGHT0,GL_POSITION,light_position);

 /*設定材質*/
 glMaterialfv(GL_FRONT,GL_AMBIENT,material_ambient);
 glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse);
 glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular);
 glMaterialf(GL_FRONT,GL_SHININESS,0.6*128);

 glShadeModel(GL_SMOOTH);

 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LESS);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0);
 glEnable(GL_AUTO_NORMAL);
 glEnable(GL_NORMALIZE);
 glFrontFace(GL_CW);

 /*設定霧化*/
 glEnable(GL_FOG);
 glFogi(GL_FOG_MODE,GL_LINEAR);
 glFogfv(GL_FOG_COLOR,fogColorWhite);
 glFogf(GL_FOG_DENSITY,fogDensity);
 glFogf(GL_FOG_START,0.0);
 glFogf(GL_FOG_END,15.0);

 glHint(GL_FOG_HINT,GL_DONT_CARE);
}

/*根據不同的鍵值設定不同的霧化效果*/
static void myKey(unsigned char key,int x,int y)
{
 switch(key)
 {
  case 33: //shift+1
   fogDensity *= 1.10;
   glFogi(GL_FOG_MODE,GL_EXP);
   glFogf(GL_FOG_DENSITY,fogDensity);
   glutPostRedisplay();
   break;

  case 64: //shift+2
   fogDensity /= 1.10;
   glFogi(GL_FOG_MODE,GL_EXP);
   glFogf(GL_FOG_DENSITY,fogDensity);
   glutPostRedisplay();
   break;

  case 35: //shift+3
   glFogi(GL_FOG_START,0.0);
   glFogi(GL_FOG_END,8.0);
   glutPostRedisplay();
   break;

  case 36: //shift+4
   glFogi(GL_FOG_MODE,GL_EXP2);
   glutPostRedisplay();
   break;

  case 37: //shift+5
   glFogi(GL_FOG_MODE,GL_LINEAR);
   glutPostRedisplay();
   break;

  case 94: //shift+6
   glFogfv(GL_FOG_COLOR,fogColorGreen);
   glutPostRedisplay();
   break;

  case 27: //Esc
   exit(0);

  default:
   break;
 }
}

/*繪製圓錐體*/
void myDisplay(void)
{
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 glPushMatrix();
 glTranslatef(-4.0,4.0,0.0);
 glRotatef(30.0,1.0,1.0,0.0);
 glutSolidCone(1.0,50.0,20.0,20.0);
 glPopMatrix();
 glutSwapBuffers();
}

void myReshape(int w,int h)
{
 glViewport(0,0,(GLsizei)w,(GLsizei)h);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(100.0,1.0,1.0,20.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glTranslatef(0.0,0.0,-15.5);
}

int main(int argc,char ** argv)
{
 /*初始化*/
 glutInit(&argc,argv);
 glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
 glutInitWindowSize(300,300);
 glutInitWindowPosition(100,100);

 /*建立視窗*/
 glutCreateWindow(" FOG ");

 /*繪製與顯示*/
 myInit();
 glutKeyboardFunc(myKey);
 glutReshapeFunc(myReshape);
 glutDisplayFunc(myDisplay);

 /*進入GLUT事件處理迴圈*/
 glutMainLoop();
 return 0;
}


圖十:被霧化的圓錐體

  ·glFog指定霧化引數。後面不同的字母表明引數的資料型別。f表示float,i表示integer,v表示vector,也就是表明一個指標。

  GL_FOG_MODE是一個單值整數或浮點數,該數值指定了用來計算霧化融合因子f的方程。

  GL_DENSITY 是一個單值整數或浮點數,該值指定霧化濃度。

  GL_FOG_START 是一個單值整數或浮點數,該值指定霧化的起始值。

  GL_FOG_END是一個單值整數或浮點數,該值指定霧化的終止值。

  GL_FOG_INDEX是一個單值整數或浮點數,該值指定霧化索引值if,預設的霧化索引值為0.0。

  GL_FOG_COLOR包含4個整數值或浮點數值,這些數值指定的是霧化顏色Cf,整數值進行線性對映。

  ·glHint指定實現的線索。本例中GL_FOG_HINT指定霧化計算精度。GL_DONT_CARE指對選項不做考慮。


圖十一:霧化為綠色的圓錐體

   本例中還涉及到鍵盤操作,glutKeyboardFun。此函式註冊當前視窗的鍵盤迴調函式。因為這不是本節的主要內容,我們只簡單提一下。此函式的 原形為void glutKeyboardFunc (void(*func)(unsigned char key,int x,int y))所以我們自己寫的回撥函式必須按照原形上規定的寫。 

相關文章