CG實驗6 簡單光照與材質

1.實驗目的:

  • 通過示範代碼1,理解簡單光照明模型的基本原理與實現;
  • 通過示範代碼2和太陽系示範代碼,學習與掌握OpenGL光照與材質設置與使用方法。

2.實驗內容:

在示範代碼1基礎上,按以下要求修改:

(1) 閱讀和修改示範代碼中的有關參數,產生不同光照效果,觀察顯示效果。挑選兩張修改的效果圖保存爲圖1-2,與對應修改的代碼一起保存至word實驗文檔中(15分鐘);

(2) 將代碼中的球面改爲圓錐面,將圓錐面的光照效果圖存爲圖3,與對應修改的代碼一起保存至word實驗文檔中(25分鐘);

在示範代碼2的基礎上,按以下要求完成任務:

(3) 閱讀和修改示範代碼2中的有關參數,產生不同光照效果,觀察顯示效果。挑選兩張修改的效果圖保存爲圖4-5,與對應修改的代碼一起保存至word實驗文檔中(15分鐘);

(4)參考太陽系示範代碼,該代碼顯示一個簡單的太陽系模型,嘗試爲其增加光照與材質效果,挑選兩張修改的效果圖保存爲圖6-7,與對應修改的代碼一起保存至word實驗文檔中(25分鐘);

(5) 整理word實驗文檔,將其命名爲“序號-姓名-Prj6.doc”,電子版提交至雨課堂,A4打印稿下一次課前或實驗課前提交。

3.實驗原理:

Phong光照明模型是由物體表面上一點P反射到視點的光強I爲環境光的反射光強Ie、理想漫反射光強Id、和鏡面反射光Is的總和,即
I=Iaka+IpKd(LN)+IpKs(RV)n I = I_a k_a + I_p K_d(LN) + I_p K_s(RV)^n
其中R,V,N爲單位矢量;IpI_p爲點光源發出的入射光強;IaI_a爲環境光的漫反射光強;KaK_a環境光的漫反射係數;KdK_d漫反射係數( )取決於表面的材料;KsK_s鏡面反射係數( );n冪次,用以模擬反射光的空間分佈,表面越光滑,n越大。
在用Phong模型進行真實感圖形計算時,對物體表面上的每個點P,均需計算光線的反射方向R,再由V計算 。爲減少計算量,我們可以作如下假設:a)光源在無窮遠處,即光線方向L爲常數;b)視點在無窮遠處,即視線方向V爲常數;c)用 近似 。這裏H爲L和V的角平分向量, 。在這種簡化下,由於對所有的點總共只需計算一次H的值,節省了計算時間。結合RGB顏色模型,Phong光照明模型的最終形式詳見教材公式(8.21)。

示範代碼1中,光源在無窮遠處,光線方向爲單位向量L(0.5, 0.5, 0.707),視點在無窮遠處,視線方向V爲(0, 0, 1)。

4.示範代碼:

(1) 示範代碼1-球面簡單光照模型效果圖

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

struct Vector
{
	float fx, fy, fz;
};

struct Color
{
	float Ir, Ig, Ib;
};

float KaIa;//環境光強度
float Kd, n;
Vector H,light;
Color mLight, mColor;//mLight表示漫反射光與鏡面反射光強度
GLboolean bLight = false;

void CirclePt(int x0, int y0, int x, int y, Color mColor)
{
	glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);
	glBegin(GL_POINTS);
	glVertex2i ( x+x0, y+y0);//x,y
	glVertex2i ( -x+x0, y+y0);//-x,y
	glVertex2i ( x+x0, -y+y0);//x, -y
	glVertex2i ( -x+x0, -y+y0);//-x, -y

	glVertex2i ( y+x0, x+y0);//y, x
	glVertex2i ( y+x0, -x+y0);//y, -x
	glVertex2i ( -y+x0, x+y0);//-y, x
	glVertex2i ( -y+x0,-x+y0);//-y, -x
	glEnd();
}

//中點圓生成算法
void MidCircle(int x0, int y0, int r, Color mColor)
{
	int x,y,deltax,deltay,d;
	x = 0;
	y = r;
	deltax = 3;
	deltay = 5-r-r;
	d = 1-r;

	CirclePt( x0, y0, x, y, mColor);
	while(x<y)
	{
		if(d<0)
		{
			d += deltax;
			deltax += 2;
			deltay += 2;
			x++;
		}
		else
		{
			d += deltay;
			deltax += 2;
			deltay += 4;
			x++;
			y--;
		}

		CirclePt( x0, y0, x, y, mColor);
	}
}

//填充圓域爲圓餅
void FlatCircle(int x0, int y0, int r, Color mColor)
{
	int x,y,deltax,deltay,d;
	x = 0;
	y = r;
	deltax = 3;
	deltay = 5-r-r;
	d = 1-r;

	glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);
	glBegin(GL_POINTS);
	{
		for(int i=-x;i<=x;i++)
		{
			glVertex2i (i+x0,y+y0);
			glVertex2i (i+x0,-y+y0);
		}
		for(int i=-y;i<=y;i++)
		{
			glVertex2i (i+x0,x+y0);
			glVertex2i (i+x0,-x+y0);
		}

		while(x<y)
		{
			if(d<0)
			{
				d += deltax;
				deltax += 2;
				deltay += 2;
				x++;
			}
			else
			{
				d += deltay;
				deltax += 2;
				deltay += 4;
				x++;
				y--;
			}

			for(int i=-x;i<=x;i++)
			{
				glVertex2i (i+x0,y+y0);
				glVertex2i (i+x0,-y+y0);
			}
			for(int i=-y;i<=y;i++)
			{
				glVertex2i (i+x0,x+y0);
				glVertex2i (i+x0,-x+y0);
			}
		}
	}
	glEnd();
}

//初始化設定
void Init()
{
	float mo;
	Vector eye;
	mLight.Ir = 0;
	mLight.Ig = 175;
	mLight.Ib = 0;
	KaIa=80;
	Kd = 1;
	n = 10;

	light.fx=0.50;light.fy=0.50;
	light.fz = sqrt(1-(light.fx*light.fx)-(light.fy*light.fy));
	eye.fx=0;eye.fy=0;eye.fz=1;
	H.fx=light.fx+eye.fx;
	H.fy=light.fy+eye.fy;
	H.fz=light.fz+eye.fz;
	mo=sqrt(H.fx*H.fx+H.fy*H.fy+H.fz*H.fz);
	H.fx=(H.fx/mo);H.fy=(H.fy/mo);H.fz=(H.fz/mo);
	H.fx=(H.fx/mo);H.fy=(H.fy/mo);H.fz=(H.fz/mo);

	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);
}

//根據Phong模型計算光強
Color Phong(int x0, int y0, int r, int x, int y)
{
	Vector N;
	float z,alpha,theta,Ks;
	Ks=1.0-Kd;
	z=sqrt((float)(r*r-(x-x0)*(x-x0)-(y-y0)*(y-y0)));
	N.fx=(x-x0)*1.0/r;
	N.fy=(y-y0)*1.0/r;
	N.fz = z*1.0/r;
	theta = N.fx * light.fx + N.fy * light.fy + N.fz * light.fz;
	if(theta<0)
		theta=0;
	alpha=H.fx*N.fx+H.fy*N.fy+H.fx*N.fz;
	if(alpha<0)
		alpha=0;
	mColor.Ir=KaIa+mLight.Ir*Kd*theta+mLight.Ir*Ks*pow(alpha,n);
	mColor.Ig=KaIa+mLight.Ig*Kd*theta+mLight.Ig*Ks*pow(alpha,n);
	mColor.Ib=KaIa+mLight.Ib*Kd*theta+mLight.Ib*Ks*pow(alpha,n);
	return mColor;
}

//根據計算的光強按球體的結果着色
void Sphere(int x0, int y0, int r)
{
	int x,y,deltax,deltay,d;
	x = 0;
	y = r;
	deltax = 3;
	deltay = 5-r-r;
	d = 1-r;

	glBegin(GL_POINTS);
	{
		for(int i=-x;i<=x;i++)
		{
			mColor=Phong(x0,y0,r,i+x0,y+y0);
			glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,y+y0);
			glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-y+y0);
		}
		for(int i=-y;i<=y;i++)
		{
			mColor=Phong(x0,y0,r,i+x0,x+y0);
			glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,x+y0);
			glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-x+y0);
		}

		while(x<y)
		{
			if(d<0)
			{
				d += deltax;
				deltax += 2;
				deltay += 2;
				x++;
			}
			else
			{
				d += deltay;
				deltax += 2;
				deltay += 4;
				x++;
				y--;
			}

			for(int i=-x;i<=x;i++)
			{
				mColor=Phong(x0,y0,r,i+x0,y+y0);
				glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,y+y0);
				glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-y+y0);
			}
			for(int i=-y;i<=y;i++)
			{
				mColor=Phong(x0,y0,r,i+x0,x+y0);
				glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,x+y0);
				glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-x+y0);
			}
		}
	}
	glEnd();
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f (1.0f, 1.0f, 1.0f); 
	Color clr;
	clr.Ir = 180, clr.Ig = 180, clr.Ib = 180;
	MidCircle(100, 200, 50, clr);
	FlatCircle(250, 200, 50, clr);
	Sphere(400, 200, 50);

	glFlush();
}

void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei) w,  (GLsizei) h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(500, 400);
	glutCreateWindow("Hello Light!");

	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;
}


程序運行結果:

圖1

(2) 示範代碼2-OpenGL光照與材質下球體效果圖

#include <GL/glut.h>

#include <stdlib.h>

// Initialize material property, light source, lighting model, and depth buffer.

void init(void)

{

	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

	GLfloat mat_shininess[] = { 50.0 };

	GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

	GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };

	GLfloat Light_Model_Ambient[] = { 0.2 , 0.2 , 0.2 , 1.0 }; //

	glClearColor(0.0, 0.0, 0.0, 0.0);

	glShadeModel(GL_SMOOTH);

	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

	glLightfv(GL_LIGHT0, GL_POSITION, light_position);

	glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);

	glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);

	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Light_Model_Ambient); //

	glEnable(GL_LIGHTING);

	glEnable(GL_LIGHT0);

	glEnable(GL_DEPTH_TEST);

}

void display(void)

{

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glutSolidSphere (0.5, 20, 16);

	//glutSolidTeapot(0.5);

	glFlush();

}

void reshape(int w, int h)

{

	glViewport(0, 0, (GLsizei)w, (GLsizei)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, -10.0, 10.0);

	else

		glOrtho(-1.5*(GLfloat)w / (GLfloat)h,

			1.5*(GLfloat)w / (GLfloat)h, -1.5, 1.5, -10.0, 10.0);

	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

}

int main(int argc, char** argv)

{

	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);

	glutInitWindowSize(500, 500);

	glutInitWindowPosition(100, 100);

	glutCreateWindow(argv[0]);

	init();

	glutDisplayFunc(display);

	glutReshapeFunc(reshape);

	glutMainLoop();

	return 0;

}

程序運行結果:

圖2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章