OpenGL 光照和材料屬性

首先是光照的設置,光照分爲三類環境光 散射光 鏡面光,根據此時的理解,記錄下今天所掌握的知識,先設置3個數組後面會用到
GLfloat amb[] = {0.3f,0.3f,0.3f,1.0f};//環境光成分
GLfloat dif[] = {0.7f,0.7f,0.7f,1.0f};//散射光成分
GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};//鏡面光成分
環境光是從物體的各個方向照射物體的,他產生的效果和關閉光照效果幾乎相同,由於在關閉光照效果的時候,物體老是可見的並均勻着色,與他們的旋轉和觀察角度無關,若打開光照效果glEnable(GL_LIGHTING)而不指定環境光,這時默認的環境光是(0.2,0.2,0.2,1.0),這是很是微弱的光,畫面上的物體會很是的暗淡,這時咱們指定一個本身的第一個光源light0,先給他設置環境光glLightfv(GL_LIGHT0,GL_AMBIENT,amb),amb是開始定義的表示環境光成分的數組
散射光是一種有特定方向的光,在物體表面是均勻的反射的,也能夠理解成漫反射光,和下面學習的經面光有些類似,若以散射光照射一個球體做爲例子,正對着散射光方向的表面是亮的,背對着光線方向的表面是暗淡的,在光線掠過的側面的亮度是介於二者之間的,這和在一個黑屋子裏用手電筒照射一個籃球的效果很類似,這時給上面的光源light0指定一種散射光glLightfv(GL_LIGHT0,GL_DIFFUSE,dif),dif是開始定義的表示散射光成分的數組
最後是鏡面光,這種光比較好理解,和上面的散射光同樣,他也是有必定的方向,但在物體表面的反射是很強烈的,能夠理解爲鏡面反射光,他會在物體邊面造成一個亮點(光斑),在生活中強光照射在比較平整的表面就是這種效果,如在陽光照射下表面無鏽跡的鐵球,再給上面的光源light0加上鏡面光成分,flLightfv(GL_LIGHT0,GL_SPECULAR,spe),spe是開始定義的表示鏡面光成分的數組
在特定的光源設置好之後這時就能夠啓用這用個光源,glEnable(GL_LIGHT0);
如下就是設置並啓用自定義光源的代碼
glEnable(GL_LIGHTING);//啓動光照效果
GLfloat amb[] = {0.3f,0.3f,0.3f,1.0f};//環境光成分
GLfloat dif[] = {0.7f,0.7f,0.7f,1.0f};//散射光成分
GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};//鏡面光成分數組

glLightfv(GL_LIGHT0,GL_AMBIENT,amb); //添加環境光成分
glLightfv(GL_LIGHT0,GL_DIFFUSE,dif); //添加散射光成分
glLightfv(GL_LIGHT0,GL_SPECULAR,spe);//給自定義光源light0添加鏡面光成分函數

glEnable(GL_LIGHT0);     //啓用自定義的光源oop

光照定義完成後,還要定義物體的表面的材料屬性,材料的屬性對最後的效果影響也是巨大的,由於最終在屏幕上顯示的效果是光源發出的光通過材料反射後才能最終肯定的,材料的屬性設置和光源的設置有些相似,用到的函數glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,amb)第一個參數指定了是哪一個表面須要被渲染,第二個參數是哪一個材料屬性將要被設置,第三個參數是指定哪一種顏色的光會被反射(用了上面的一個數組),通常狀況下材料對環境光和對散射光的反射率是相同的,因此上面的參數用了GL_AMBIENT_AND_DIFFUSE。
上面的光源設置中用到了鏡面光,若此時在材料屬性中不設置鏡面反射效果,則上面的鏡面光也就沒什麼做用,鏡面反射的設置和光源的鏡面光設置相似glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe),若繪製的物體想要有光澤那麼這個設置是必須的(例如光滑的大理石表面),若繪製的物體的表面沒有光澤那麼這個屬性就不用設置(例如粗糙的石板表面),在鏡面反射設置後還有一個問題須要解決,那就是高強度的鏡面光和強烈的鏡面反射效果會致使物體將以幾乎接近白色的效果出現,如若想要在物體表面造成一個亮斑,還須要一個函數glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,45);中間的一個參數是鏡面指數,他指定了鏡面反射加亮的大小和集中性,若是最後一個參數設置爲0那表示不聚焦,也就是整個表面均勻加亮,若設置爲128表示最大程度的聚焦,也就是光斑點最小的狀況。
一下是材料屬性設置的代碼
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,amb);//材料對環境光的反射狀況
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif);//散射光的反射狀況
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);//鏡面光的反射狀況
glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,45);//鏡面光的聚焦狀況學習

這樣就能夠渲染出比原來更爲真實的三位物體,但還有一點不足 ,就是當物體的顏色常常發生變化時,那麼必須每次進行材料反射屬性的更改,將調用一次glMaterialfv(),那將是件很麻煩的工做,這裏能夠用到一個方法,也是之後最經常使用到的方法,叫作顏色追蹤。若使用了這種方法,能夠在之後的渲染中經過調用glColor來設置材料的屬性,方法以下
glEnable(GL_COLOR_MATERIAL);         //啓用顏色追蹤
glColorMaterial(GL_FRONT_AND_BACK,FL_AMBIENT_AND_DIFFUSE); //正面和反面,環境光和散射光
設置好後,之後就能夠經過調用glColor來設置材料的反射屬性了。
如下是今天程序的完整代碼和makefilespa


//文件名ball_light.c
//2008/2/14
//made by hsw
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glut.h>orm

GLfloat position_x = -25.0f;
GLfloat position_y = 25.0f;
GLfloat change_x = 0.1f;
GLfloat change_y = 0.1f;
GLfloat Height = 100.0f;
GLfloat Width = 100.0f;it

GLfloat temp = 1.0f ;
void TimeFunction(void)
{
glutPostRedisplay();
glutTimerFunc(33,TimeFunction,1);io

}
void RenderScene(void)
{
static GLint angle_x = 0;
static GLint angle_y = 0;
static GLint angle_z = 0;
GLint temp_i,temp_j;
angle_x += 1;
angle_y += 2;
angle_z += 4;
 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 glColor3f(0.0f,0.95f,0.24f);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();gcc


glPushMatrix();
 glTranslatef(0.0f,0.0f,-50.0f);
 glRotatef(angle_x++,0.0f,1.0f,0.0f);
 glutSolidTorus(1,8,30,40);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
glPopMatrix();渲染

glPushMatrix();
 glTranslatef(0.0f,0.0f,-50.0f);
    glPushMatrix();
 glTranslatef(-30.0f,10.0f,0.0f);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
    glPopMatrix();

    glPushMatrix();
 glTranslatef(-30.0f,25.0f,0.0f);
 glColor3f(1.0f,0.0f,0.0f);
 glutSolidSphere(3.5f,40,40);
    glPopMatrix();

glPopMatrix();
glPushMatrix();
 glColor3f(1.0f,1.0f,0.0f);
 glTranslatef(30.0f,0.0f,-50.0f);
 glutSolidSphere(5.0f,40,40);
glPopMatrix();
 //glutSolidSphere(12.0f,40,40);
 //glutSolidTeapot(12.0f);
//如下是地面的繪製
//底色

glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_TRIANGLE_FAN);
    glVertex3f(-1500.0f,-30.5f,0.0f);
    glVertex3f(-1500.0f,-30.5f,-2500.0f);
    glVertex3f(1500.0f,-30.5f,-2500.0f);
    glVertex3f(1500.0f,-30.5f,0.0f);
glEnd();

 glutSwapBuffers();
}
void SetupRC(void)
{
 GLfloat amb[] = {0.4f,0.4f,0.4f,1.0f};
 GLfloat dif[] = {6.0f,6.0f,6.0f,1.0f};
 GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};
 GLfloat pos[] = {-50.0f,50.0f,100.0f,1.0f};
 glClearColor(0.0f,0.0f,0.0f,1.0f);
 glEnable(GL_DEPTH_TEST);
 //glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
 glEnable(GL_LIGHTING);
 glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
 //glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);
 glLightfv(GL_LIGHT0,GL_SPECULAR,spe);
 glLightfv(GL_LIGHT0,GL_POSITION,pos);
//glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);
 glEnable(GL_LIGHT0);

 glEnable(GL_COLOR_MATERIAL);
 glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);
 glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);
}

void ChangeSize(GLsizei w,GLsizei h)
{
GLfloat aspectRatio;
if(h == 0)
 h = 1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
temp = aspectRatio = (GLfloat)w/(GLfloat)h;
    if(w <= h)
 //glOrtho(-100.0,100.0,-100/aspectRatio,100.0/aspectRatio,0.0,100.0);
 gluPerspective(60,temp,0.1f,1000.0f);
    else
 //glOrtho(-100.0*aspectRatio,100.0*aspectRatio,-100.0,100.0,0.0,100.0);
 gluPerspective(60,temp,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int main(int argc ,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

glutCreateWindow("Color Material");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutTimerFunc(33,TimeFunction,1);
SetupRC();
glutMainLoop();

return 0;
}
//代碼結束
//////////////////////////////////////////////////////////////////////
如下是makefile

ball_light:ball_light.o gcc -o ball_light ball_light.o -lGL -lGLU -lglut -lmball_light.o:ball_light.c gcc -c ball_light.c

相關文章
相關標籤/搜索