#include "stdafx.h"
#include <GL/glut.h>
#include <iostream>
using namespace std;
void Init(void)
{
GLfloat mat_ambient[] = { 0.2, 0.2, 0.2, 1.0 };//光源环境光
GLfloat mat_diffuse[] = { 0.0, 0.0, 0.0, 1.0 };//散射光
GLfloat mat_emission[] = { 0.1, 0.1, 0.1, 1.0 };//镜面光
GLfloat mat_specular[] = { 0.3, 0.3, 0.3, 1.0 };//物体自发光
GLfloat mat_shininess[] = { 2.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 1.0 };//点光源(位置性光源)
GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0};
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[] ={1.0, 1.0, 1.0, 1.0};
GLfloat lmodel_ambient[] = { 0.5, 0.5, 0.5, 1.0};
glClearColor (0.0, 0.0, 0.0, 0.0);
//GL_FLAT时,绘制的三角形上的所有点都是最后一个点的颜色,而用GL_SMOOTH会线性插值
glShadeModel (GL_SMOOTH /*GL_FLAT*/);
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_EMISSION, mat_emission);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);//点光源相对视点的位置始终不变,此处是(1,1,1)
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);//环境光
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void Display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef( 0.0f, 0.0f, -2.0f);
glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 0.0f, 1.0f);
//glColor3f( 1, 0, 0);//如此有glEnable(GL_LIGHTING);,则此处glColor3f()设置的颜色无效.
glVertex3f( -1.0, 0.0, 0.0f);
glVertex3f( 1.0, 0.0, 0.0f);
glVertex3f( 1.0, 1.0, 0.0f);
glEnd();
glutSwapBuffers(); //双缓冲
}
void Reshape(int w,int h)
{
//透视投影或者正交投影都可以
/*glViewport(0,0 ,(GLsizei)w ,(GLsizei)h );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90.0f, (GLfloat)w/ (GLfloat)h, 0.1f, 1000.0f );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();*/
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();
}
void OnTimer( int iTimerIndex)
{
//更新
glutPostRedisplay();//刷新显示
glutTimerFunc( 50, OnTimer, 0);
}
void Keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 'w': //前
break;
case 's': //后
break;
case 'a': //左
break;
case 'd': //右
break;
case 'q': //上
break;
case 27:
exit(0);
break;
}
}
void MouseEvent(int button, int state, int x, int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
cout<<"GLUT_LEFT_BUTTON"<<endl;
break;
case GLUT_RIGHT_BUTTON:
cout<<"GLUT_RIGHT_BUTTON"<<endl;
break;
case GLUT_MIDDLE_BUTTON:
cout<<"GLUT_MIDDLE_BUTTON"<<endl;
break;
}
}
void MotionMove(int x,int y)
{
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(450,450);
glutInitWindowPosition(200,200);
glutCreateWindow("Hello");
Init();
glutDisplayFunc( Display);
glutReshapeFunc( Reshape);
//定时器
//glutTimerFunc( 50, OnTimer, 0 );
glutKeyboardFunc( Keyboard);
glutMouseFunc( MouseEvent);
glutMotionFunc( MotionMove);
glutMainLoop();
return 0;
}
以上代码可以产生一个三角形,经计算验证,书上的光照计算方法是正确的.
程序运行后,可用QQ截图获取某个点的像素值(该程序中左顶点的像素是(130,130,130),因为本程序中每个像素的R,G,B都是一样的):
由于没有用gluLookAt()来改变视点,所以视点坐标依然不变,为世界坐标系原点E(0,0,0,),光源位
(偷了下懒).
总的计算过程是C=(0.1, 0.1, 0.1)+( 0.5, 0.5, 0.5)*( 0.2, 0.2, 0.2)+[( 0.2, 0.2, 0.2)*( 0.2, 0.2, 0.2)+ 3/ *(1.0, 1.0, 1.0)*( 0.0, 0.0, 0.0)+ (s*n)平方*(1.0, 1.0, 1.0)*( 0.3, 0.3, 0.3)],然后再把C*255即可得到实际像素值(130),可以证明光照方程是正确的.
注意:s中的2个向量都必须先单位化后,再相加成为s,然后s还要单位化.我在计算时,由于粗心,没有把L单位化,导致一直得不到正确结果,后来找王辉问时,才突然发现s的2个向量一定要单位化.以后一定要细心,而且一般遇到问题,不要抱怨,以为是编译器错了,而事实上往往是由于自己的疏忽和不小心,应仔细debug,切记!