光照

来源:互联网 发布:光伏app软件 编辑:程序博客网 时间:2024/06/11 20:43
光照处理过程:
为所有顶点设置法线向量----
进行光照计算,面法线长度必须为1, 为确保面法线为1,需要使用参数GL_NORMALIZE(通用,计算量相对较大),GL_RESCAL_NORMAL(等比例放大缩小,使用有限制)调用glEnable();
设置光源----设置位置----
glLight();
启用光源----
glEnable(GL_LIGHT*);
可设置8个或8个以上光源,默认为黑色,增加光源增加系统负担。
选择光照模型----
glLightModel*();
指定物体材质属性----
glMaterialfv()
可以指定材质的环境颜色,散射颜色,光洁度
1.创建光源
glLight{if}[v](GLenum light, GLenum pname, TYPE (*)param)
GL_AMBIENT    (0.0, 0.0, 0.0, 1.0)    环境光颜色
GL_DIFFUSE    (1.0,1.0,1.0,1.0)或(0.0,0.0,0.0,1.0)  散射光颜色(LIGHT0默认为白色,其余为黑色)
GL_SPECULAR    (1.0,1.0,1.0,1.0)或(0.0,0.0,0.0,1.0)  镜面反射光颜色(LIGHT0默认为白色,其余为黑色)
GL_POSITION    (0.0,0.0,1.0,0.0)     光源位置
GL_SPOT_DIRECTION   (0.0,0.0,-1.0)     聚光灯方向
GL_SPOT_EXPONENT   (0.0)      聚光指数
GL_SPOT_CUTOFF   180.0      聚光截至角
GL_CONSTANT_ATTENUATION  1.0      固定衰减因子
GL_LINEAR_ATTENUATION  0.0      线性衰减因子
GL_QUADRATIC_ATTENUATION  0.0      二次衰减因子
颜色
GL_DIFFUSE与看见的颜色关系最密切
位置和衰减
GL_POSITION 的 param (x, y, z, w),  当w为0时为从无穷远照射,(x, y, z)为光照射方向
     当w不为0时为定点光源,(x, y, z )表示在其次坐标中的位置
对于定点光源可以设置衰减
衰减系数 = 1/(kc+kl*d+kq*d*d)
聚光灯
GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF分别设置聚光灯的方向、聚光指数、聚光灯、光锥半顶角。
还需要设置光源的位置。
光源位置和方向
1.光源位置固定
指定模型视点矩阵后设置光源位置,之后不进行更改
例程light:
#include<windows.h>
#include<GL/glut.h>
void display()
{
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glutSolidSphere(1.0, 20, 16);
     glFlush();
}
void init()
{
     GLfloat mat_specular[] = {1.0, 1.0,0.0, 1.0};
     GLfloat mat_shininess[] = {5.0};
     GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
     GLfloat white_light[] = {1.0, 1.0, 1.0, 1.0};
     GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 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, lmodel_ambient);
    
     glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
     glEnable(GL_DEPTH_TEST);
    
}
void reshape(int w, int h)
{
     glViewport(0.0, 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 grac, char** agrv)
{
    glutInit(&grac, agrv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100,100);
    glutCreateWindow("Light");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
}

2.独立的移动光源
设置模型视点矩阵后对光源位置进行修改
例程:moveLight
#include<windows.h>
#include<GL/glut.h>
static int spin = 0;
void display()
{
     GLfloat position[] = {0.0, 0.0, 1.5, 1.0};
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
     glPushMatrix();
     glTranslatef(0.0, 0.0, -5.0);
    
     glPushMatrix();
     glRotated((GLdouble)spin, 1.0, 0.0, 0.0);
     glLightfv(GL_LIGHT0, GL_POSITION, position);
    
     glTranslated(0.0, 0.0, 1.5);
     glDisable(GL_LIGHTING);
     glColor3f(0.0, 1.0, 1.0);
     glutWireCube(0.1);
     glEnable(GL_LIGHTING);
     glPopMatrix();
    
     glutSolidTorus(0.275, 0.85, 8, 15);
     glPopMatrix();
    
     glFlush();
}
void init()
{
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glShadeModel(GL_SMOOTH);
     glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
     glEnable(GL_DEPTH_TEST);
}
void reshape(int w, int h)
{
     glViewport(0.0, 0.0,(GLsizei)w, (GLsizei)h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(40.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);
     glMatrixMode(GL_MODELVIEW);
     glFlush();
}
void mouse(int button, int state, int x, int y)
{
     switch(button)
     {
                   case GLUT_LEFT_BUTTON:
                        if(state == GLUT_DOWN)
                        {
                                 spin = (spin + 30)%360;
                                 glutPostRedisplay();
                        }
                        break;
                   default:
                           break;
     }
}
int main(int grac, char** agrv)
{
    glutInit(&grac, agrv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100,100);
    glutCreateWindow("moveLight");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMainLoop();
    return 0;
}

3.随视点移动光源
先设置光源在设置视点变化矩阵,光源相对观察点的位置不变。
例程:moveLight2
#include<windows.h>
#include<GL/glut.h>
static int spin = 0;
void display()
{
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     //光源位置
     glPushMatrix();
     glDisable(GL_LIGHTING);
     glTranslatef(0.0, 0.0, -4.0);
     glColor3f(0.0, 1.0, 1.0);
     glutWireCube(0.1);
     glEnable(GL_LIGHTING);
     glPopMatrix();
    
     glPushMatrix();
     //视口位置
     glTranslatef(0.0, 0.0, -5.0);
     glRotated((GLdouble)spin, 1.0, 0.0, 0.0);
    
     //物体
     glutSolidTorus(0.275, 0.85, 8, 15);
     glPopMatrix();
    
     glFlush();
}
void init()
{
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glShadeModel(GL_SMOOTH);
     glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
     glEnable(GL_DEPTH_TEST);
}
void reshape(int w, int h)
{
     GLfloat position[] = {0.0, 0.0, 0.0, -4.0};
     glViewport(0.0, 0.0,(GLsizei)w, (GLsizei)h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(40.0, (GLfloat)w/(GLfloat)h, 1.0, 20.0);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glLightfv(GL_LIGHT0, GL_POSITION, position);
    
}
void mouse(int button, int state, int x, int y)
{
     switch(button)
     {
                   case GLUT_LEFT_BUTTON:
                        if(state == GLUT_DOWN)
                        {
                                 spin = (spin + 30)%360;
                                 glutPostRedisplay();
                        }
                        break;
                   default:
                           break;
     }
}
int main(int grac, char** agrv)
{
    glutInit(&grac, agrv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100,100);
    glutCreateWindow("moveLight");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMainLoop();
    return 0;
}
2.选择光照模型
glLightModel{if}(GLenum pname, TYPE param);
GL_LIGHT_MODEL_AMBIENT   (0.2, 0.2, 0.2, 1.0)  环境光的RGBA值
GL_LIGHT_MODEL_LOCAL_VIEWER  0.0或GL_FALSE   如何计算镜面反射角
GL_LIGHT_MODEL_TWO_SIDE   0.0或GL_FALSE   单面或双面光照
GL_LIGHT_MODEL_COLOR_CONTROL  GL_SINGLE_GCOLOR  镜面反射颜色计算是否独立于环境颜色、散射颜色,在纹理之后计算
 
3.设置材质属性
glMaterial{if}(GLenum face, GLenum pname, TYPE param)
glMaterial{if}v(GLenum face, GLenum pname, TYPE* param)
face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK.
当pname为GL_SHININESS才能使用非向量函数
pname
GL_AMBIENT    (0.2, 0.2, 0.2, 1.0)  材质的环境颜色
GL_DIFFUSE    (0.8, 0.8, 0.8, 1.0)  材质的散射颜色
GL_AMBIENT_AND_DIFFUSE      材质的环境颜色和散射颜色
GL_SPECULAR    (0.0, 0.0, 0.0, 1.0)  材质的镜面反射颜色
GL_SHININESS    0.0    镜面反射指数、光泽度
GL_EMISSION    (0.0, 0.0, 0.1, 1.0)  材质的发光颜色
GL_COLOR_INDEXES   (0, 1, 1)    环境颜色索引、散射索引、镜面反射索引
 
4.颜色材质模式
glColorMaterial(GLenum face, GLenum mode);
设置face表面的材质属性mode总是为当前颜色。
用glColor修改当前颜色后,材质的相应属性会发生改变。
face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK
mode可以是GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR、GL_AMBIENT_AND_DIFFUSE、GL_EMISSION

修改场景中大部分顶点的同一种材质属性是,应使用glColorMaterial()
需要修改多种材质时要用glMaterial*();
原创粉丝点击