首页 > 代码库 > 【狼】openGL 光照的学习

【狼】openGL 光照的学习

小狼学习原创,欢迎批评指正

先上代码

#include "stdafx.h"#include <windows.h>#include "iostream"#include "GL/glut.h"#include "math.h"#define windowsWidth  500#define windowsHeight 500using namespace std;int preX,preY;        bool leftState=false;bool rightState=false;float angleX=0.0;float angleY=0.0;float angleY1=0.0;float angleY2=0.0;float angleX1=0.0;float angleX2=0.0;void init(){    GLfloat mat_diffuse[4] = {0.5,0.5,0.5,1};    GLfloat mat_specular[] = {1,1,1,1};    GLfloat mat_ambient[] = {1,1,1,1};    GLfloat light_position[] = {1,1,1,0};    glClearColor(0,0,0,0);    glShadeModel(GL_SMOOTH);    glEnable(GL_DEPTH_TEST);    glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);//环境光(全局环境光)    glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);//散射光(很微弱的光,感觉像是从各种的物体反射的光)    glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);//反射光(像高光)    glMaterialf(GL_FRONT,GL_SHININESS,25.0);    glLightfv(GL_LIGHT0,GL_POSITION,light_position);    glEnable(GL_LIGHTING);    glEnable(GL_LIGHT0);    glColorMaterial(GL_FRONT,GL_DIFFUSE);    glEnable(GL_COLOR_MATERIAL);    glClear(GL_COLOR_BUFFER_BIT);    glRotatef(angleX1,0.0,1.0,0.0);    glRotatef(angleY1,-1.0,0.0,0.0);    glBegin(GL_DIFFUSE);    glColor3f(0.0f,0.0f,1.0f);        glutSolidTeapot(0.6f);     cout<<"init"<<endl;}void KeyPressFunc(int key, int x, int y){    if(key==GLUT_KEY_UP)    {        angleY1 = 1;        angleX1 = 0;        glutPostRedisplay();//重绘图像    }    else if(key==GLUT_KEY_DOWN)    {        angleY1 = -1;            angleX1 = 0;        glutPostRedisplay();    }    else if(key==GLUT_KEY_RIGHT)    {        angleX1 = 1;        angleY1 = 0;        glutPostRedisplay();    }    else if(key==GLUT_KEY_LEFT)    {        angleX1 =- 1;            angleY1 = 0;        glutPostRedisplay();    }}void randerScene(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    init();     glFlush();    //ERROR    cout<<"shuaxin"<<endl;}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)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-10,10);    }     else    {        glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,-10,10);    }    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    randerScene();}void IdleFunc(){    angleY1 = 0;    angleX1 = 0.1;    glutPostRedisplay();//重绘图像}void setupRc(){    glClearColor(0.5f,0.5f,0.5f,1.0f);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );    glShadeModel (GL_FLAT);//光滑着色}int main(int argc, char *argv[]){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH | GLUT_STENCIL );    glutInitWindowPosition(100, 100);    glutInitWindowSize(400, 400);    glutCreateWindow("teapot");    init();    glutDisplayFunc(randerScene);    setupRc();    glutSpecialFunc(KeyPressFunc);//  glutIdleFunc(IdleFunc);//空闲状态执行函数(取消注释茶壶自行旋转)    glutReshapeFunc(&reshape);    glutMainLoop();    return 0;}        

这是一个受很多光照着Front(前面)的蓝色小茶壶,

分析下代码,从init(初始化)开始,

glShadeModel();这个是选择着色方式的函数,

如果里面的参数是GL_SMOOTH,那就是光滑着色,有渐变的效果,

如果参数是GL_FLAT,那就是平面着色,没有渐变效果,都是一个颜色,

而这只有在定点颜色不同时才有区别,

 

作为光滑smooth模式,右图为flat平面模式

应用光滑处理模式时,多边形所有点的法向是由内插生成的,具有一定的连续性,因此每个点的颜色也相应内插,故呈现不同色。这种模式下,插值方法采用的是双线性插值法

通常算法为:先用多边形顶点的光强线性插值出当前扫描线与多边形边交点处的光强,然后再用交点的光强线插值处扫描线位于多边形内区段上每一象素处的光强值。

图中显示出一条扫描线与多边形相交,交线的端点是A点和B点,P点是扫描线上位于多边形内的任一点,多边形三个顶点的光强分别为I1、I2和I3.

取A点的光强Ia为I1和I2的线性插值,B点的光强Ib为I1和I3的线性插值,P点的光强Ip则为Ia和Ib的线性插值。

处理后可以使用多边形表示的曲面光强连续,而且计算量很小。这种算法还可以以增量的形式改进,且能用硬件直接实现算法,从而广泛用于计算机实时图形生成

 

 

 

 

接下来是光照部分的重点函数,glMaterial(),

他有glMaterialf, glMateriali, glMaterialfv, glMaterialiv。这四种形式,

 

 

如果是

void glMaterialf(GLenum face,                 GLenum pname,                 GLfloat para)void glMateriali(GLenum face,                 GLenum pname,                 GLint para)

这两个函数pname只能是GL_SHININESS(镜面指数)的属性,因为只有镜面指数是一个值(para)控制的

face
哪一面被刷新. 是 GL_FRONT, GL_BACK, 或GL_FRONT_AND_BACK中的一个
pname
什么光照属性,这里只能是是 GL_SHININESS.
param
 GL_SHININESS 的属性值.
如果是
void glMaterialfv(GLenum face,                  GLenum pname,                  const GLfloat *params)void glMaterialiv(GLenum face,                  GLenum pname,                  const GLint *params)

因为函数后缀是v(vectors向量),所以要预先设置glfloat数组的值

 

face
哪一面被刷新. 是 GL_FRONT, GL_BACK, 或GL_FRONT_AND_BACK中的一个
pname
什么光照属性,这里可以是 GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_SHININESS, GL_AMBIENT_AND_DIFFUSE, 或 GL_COLOR_INDEXES的其中之一
param
属性值(数组)
GL_AMBIENT  环境光的颜色
GL_DIFFUSE  散射光的颜色
GL_SPECULAR  镜面反射光(高光)的颜色
GL_EMISSION  发射颜色(自发光的颜色)
GL_SHININESS  镜面指数(取值范围为[0.0, 128.0],数值越大,高光越小,亮度越高)
GL_AMBIENT_AND_DIFFUSE  环境光和散射光的颜色
GL_COLOR_INDEXES  环境光,散射光,镜面光的颜色索引(index)

这些设置的都是GL_LIGHTn的属性(GL_LIGHT0,GL_LIGHT1,GL_LIGHT2。。。。一个又一个的光源),

GL_LIGHT0属性的默认值与其他不同,需要注意

p.s.只有