随感而发

杂七杂八

导航

<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

随笔分类(62)

随笔档案(67)

统计

留言簿(13)

阅读排行榜

评论排行榜

OpenGL学习笔记【10】——移动光源,光照小结

今天学习了移动光源,奉上源代码:
#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-11};    //光源聚光灯方向
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, 
010);    //光源的旋转
    glTranslatef(light_change[0],light_change[1],light_change[2]);    //光源的位置
    glTranslatef(light_position[0], light_position[1],light_position[2]);    //光源位置
    
    glutSolidSphere(
0.14,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(130,30);//利用库函数绘制一个半径为1的球体。
    glPopMatrix();            //弹出矩阵。

    glutSwapBuffers();            
//交换缓冲区。显示图形
}


//初始化
void init (void
{
    
//srand(0);    随机种子
    glClearColor (0.50.50.50.0);    //清理颜色,为黑色,(也可认为是背景颜色)
    
    GLfloat light_param[] 
= 1111.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, 01000);    //设置投影矩阵
    
//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 (
800600);            //窗口大小
    glutInitWindowPosition (100100);        //窗口位置
    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既逆时针为正面。所以在绘制茶壶和球的时候会出问题,在绘制一个矩形的时候也要注意这个问题。

posted on 2009-05-03 14:57 shongbee2 阅读(7239) 评论(4)  编辑 收藏 引用 所属分类: OpenGL

评论

# re: OpenGL学习笔记【10】——移动光源,光照小结 2009-05-05 19:46 yanjun

还是读一下红宝书好些
会让你忽然开朗  回复  更多评论   

# re: OpenGL学习笔记【10】——移动光源,光照小结 2009-05-05 19:54 yanjun

.聚光灯
首先点光源下才计算的,position[]={x,y,z,w>0};
其次GL_SPOT_CUTOFF!=180,
再次GL_SPOT_CUTOFF<90(聚光)
90~180我把它说成用一个板挡着一个spot_point
红宝书上面讲的很明白  回复  更多评论   

# re: OpenGL学习笔记【10】——移动光源,光照小结 2009-05-08 23:57 shongbee2

@yanjun
哦,谢谢推荐。呵呵,,我也是马上打算看这本书。不过还没有找到呵呵。
  回复  更多评论   

# re: OpenGL学习笔记【10】——移动光源,光照小结 2011-11-15 09:08 cghy2011

不错  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理