今天学习了移动光源,奉上源代码:
#pragma comment(lib, "glaux.lib")
#include "gl\glaux.h"
#include <gl\glut.h>
float yRot = 0;
unsigned int nPre = 0;
GLfloat light_position[4] = {0,0,0,1}; //光位置
GLfloat light_diffuse[4] = {1,0,1,1}; //光的漫反色
GLfloat light_direction[4] = {-1, -2, -1, 1}; //光源聚光灯方向
GLfloat light_change[3] = {3,3,-1}; //光源移动位置。
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)
glColor3f(1.0,1.0,1.0);
glLoadIdentity(); //初始变换矩阵为单位矩阵
glTranslated(0,-1,-5); //平移0,0,-5向Z负方向平移5个单位
glPushMatrix(); //压缩矩阵,设定光源的位置
glDisable(GL_LIGHTING);
glRotatef(yRot, 0, 1, 0); //光源的旋转
glTranslatef(light_change[0],light_change[1],light_change[2]); //光源的位置
glTranslatef(light_position[0], light_position[1],light_position[2]); //光源位置
glutSolidSphere(0.1, 4,4);//利用库函数绘制一个半径为1的球体。表示光源在这里
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPopMatrix();
light_direction[0] = -light_change[0];
light_direction[1] = -light_change[1];
light_direction[2] = -light_change[2];
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glPopMatrix(); //光源设置完毕
glPushMatrix(); //要入矩阵,绘制地面
glBegin(GL_QUADS);
glVertex3f(-3,0,3);
glVertex3f(3,0,3);
glVertex3f(3,0,-3);
glVertex3f(-3,0,-3);
glEnd();
glPopMatrix(); //地面绘制完毕
glPushMatrix(); //压入变换矩阵那
glutSolidSphere(1, 30,30);//利用库函数绘制一个半径为1的球体。
glPopMatrix(); //弹出矩阵。
glutSwapBuffers(); //交换缓冲区。显示图形
}
//初始化
void init (void)
{
//srand(0); 随机种子
glClearColor (0.5, 0.5, 0.5, 0.0); //清理颜色,为黑色,(也可认为是背景颜色)
GLfloat light_param[] = { 1, 1, 1, 1.0 }; //初始化光参数。
//glLightfv(GL_LIGHT0, GL_AMBIENT, light_param); //设置光为环境光。
//glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); //设置聚光的范围为45度。
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,2.0); //设置聚光灯的聚光强度。
glMaterialfv(GL_FRONT, GL_SPECULAR, light_param); //设置材质的漫反射属性
//glMaterialfv(GL_FRONT, GL_AMBIENT, light_param); //设置材质的环境属性
glMaterialf(GL_FRONT, GL_SHININESS, 64); //设置材质的高光属性
glEnable(GL_LIGHTING); //启动光照
glEnable(GL_LIGHT0); //启动GL_LIGHTO光
glCullFace(GL_BACK); //剔除背面
glEnable(GL_CULL_FACE); //启动剔除
glDepthFunc(GL_LEQUAL); //深度检测为小于等于
glEnable(GL_DEPTH_TEST); //启动深度检测
glFrontFace(GL_CCW); //定义逆时针为正面
}
//当窗口大小改变时,会调用这个函数
void reshape(GLsizei w,GLsizei h)
{
//这里小说明一下:矩阵模式是不同的,他们各自有一个矩阵。投影相关
//只能用投影矩阵。(只是目前情况下哦,等我学多了可能就知道为什么了。)
glViewport(0,0,w,h); //设置视口
glMatrixMode(GL_PROJECTION); //设置矩阵模式为投影变换矩阵,
glLoadIdentity(); //变为单位矩阵
gluPerspective(60, (GLfloat)w / h, 0, 1000); //设置投影矩阵
//glOrtho(-6.0, 6.0, -6.0 * h / w, 6.0* h / w, -10, 10); //为了不变形,则要长和宽成比例
glMatrixMode(GL_MODELVIEW); //设置矩阵模式为视图矩阵(模型)
glLoadIdentity(); //变为单位矩阵
}
void Keyboard(unsigned char key, int x, int y)
{
}
//闲置函数,当主循环空闲时就会调用这个函数
void MyIdle(void)
{
unsigned int nNow = ::GetTickCount();
float delt = nNow - nPre;
if (delt > 100)
{
nPre = nNow;
yRot += 0.1 * delt; //旋转角度
/**//*light_diffuse[0] = (rand() % 255) / 255.0;//太花不用了。
light_diffuse[1] = (rand() % 255) / 255.0;
light_diffuse[2] = (rand() % 255) / 255.0;*/
glutPostRedisplay();
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); //Opnegl初始化
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA); //设置显示模式为双缓冲,RGEBA
glutInitWindowSize (800, 600); //窗口大小
glutInitWindowPosition (100, 100); //窗口位置
glutCreateWindow ("hello"); //创建一个标题为hello的窗口
init (); //初始化资源,这里一定要在创建窗口以后,不然会无效。
glutDisplayFunc(display); //窗口大小改变时的回调
glutReshapeFunc(reshape); //绘制图形时的回调
glutKeyboardFunc(Keyboard);
glutIdleFunc(MyIdle);
glutMainLoop(); //主循环。
return 0;
}
学习光源已经好几天,始终入不了门。不过这次学习移动光源之后,有一点点感觉。函数的功能就不能介绍了。书上有,再次分享一下这本书,下载链接为:
http://download.csdn.net/source/1247246主要心得:
1.每个光源GL_LIGHT0--7都有相应的环境光,点光源,聚光灯,漫射光等所有光的属性,我们设置的属性也只属于这个光源。当光源照射到物体上时,OpenGL的函数会用这些所有的属性与该物体做光照射的计算,实现光的效果。而没有照射到得物体就不会计算。例如设置了环境光为[0.5,0.5,0.5,1.0],漫反射光为[1,0,1,1];如果照射到物体上,他会分别计算环境光的效果和漫射光的效果,然后再叠加他们的效果。叠加方式为取分量的最大值。若物体没有被照射,则所有效果都不会被计算。也就是说会呈现黑色。我开始就没有理解这些属性关系,以为只要设置的环境光之后就能所有物体都能用了。其实不然,只有照射到得物体才会计算。如果想所有物体都有环境光,设置全局环境光才能达到这个效果。
2.什么时候计算光照,在物体绘制的时候光照效果会计算。他会把光照设置光源的属性通过矩阵变换到该物体坐标系中,然后在进行光照计算。也就是他会跟着物体变化。例如:设置了一个点光源在这个物体的前方。如果是通过矩阵变换来改变物体的位置。那么光源会一直在该物体的前方,因为他是以物体坐标系参照的。所以这里要注意,并不是说物体glTranslate(),glRotate()之后光照会发生变化。光的位置也会跟着变,使光照不变化。如果你想光源不随着变化的话,在设置光源位置的时候,就要反着变一下。在设置光源的时候,也可以用平移旋转的能矩阵运算。
3.两个物体之间光照是否有影响:两个物体光照不会有影响,也就是说不会出现一个物体遮住另一个物体的情况。因为他是在一个物体的物体坐标系中计算效果的,而且只对该物体计算效果。所以不会对其他物体产生影响,如果要真实,就得自己算出阴影在绘制。我还没有学会。呵呵。如果不想物体产生光照,就用glDisable(GL_LIGHTIING);就可以了。在绘制其他物体再启动他。
4.聚光灯:聚光灯我是没有弄懂的,特别是他的方向,很晕很晕。感觉是向量,有感觉不像向量。到底怎么回事还得努力学习,希望能碰到高手指点一下。
5.其他方面:
glFrontFace(GL_CW); 确定顺时针为front面,默认是GL_CCW既逆时针为正面。所以在绘制茶壶和球的时候会出问题,在绘制一个矩形的时候也要注意这个问题。