OGL光照

基本概念

光照影响整个场景的氛围,缺少光照还会缺乏三维的感觉。光照主要集中在光源的类型位置方向等参数,光照物体的材质(狭隘的指光照属性)和纹理,采用的光照模型。 
    OGL镜面高光颜色GL_SEPARATE_SPECULAR_COLOR在纹理处理Fragment 纹理映射后进行, 目的是减少纹理颜色对镜面光颜色的影响。其它类型的光照都是在纹理映射前进行。现在光照都要求在Shader中计算,所以是混合在其中可以自己控制的。
   深度缓存区和颜色缓存区,stencil缓存区一样在一帧开始时候需要清理掉,后面 每个draw call会利用当前缓存中的内容决定一些事情,然后更新对应缓存中的数据

物体表面法线向量计算

变换为什么不同于顶点?

计算光照前需要对法向量进行单位化。

1).如果一开始就是单位向量,后面只是进行平移和旋转物体,那么法向量不需要重新计算,也不需要重新规范化(因为法向量值是相对于物体表面网格的,而不是世界坐标系)。

2).glEnable(GL_RESCALE_NORMAL) 对于单位化了的法线向量(例如3ds max中导出的法线贴图),其中进行了均匀缩放物体,那么需用GL_RESCALE_NORMAL重新规范化法向量(法线向量中的每个成分和同一个由模型视图变换决定的值相乘),会比GL_NORMALIZE更快.

3).glEnable(GL_NORMALIZE) 对于开始没有规范化的法向量,或者网格进行了非均匀缩放,那么需要重新程序员手动计算法向量的值(不要轻易非均匀缩放),且要进行GL_NORMALIZE规范化法向量,会重新除以长度规范化。

光源的位置和方向是存放在视图坐标系中的,物体的法向量应该是基于物体坐标系的,如果自己计算法向量在视图坐标系中的值,那么进行模型视图变换即可(先变换到世界坐标系,然后乘以视点变换的逆)。

光源类型光照颜色属性/表面法向量材质颜色/观察者

光源类型:
1)点光源
2)聚光灯
3)平行光
4)环境光

反射类型:
1)镜面反射
2)漫反射
3)环境光反射
4)自发光

物体才是上的颜色是它反射的颜色,而不是它吸收的颜色
物体被光照的外观相关的因素:
1)光源的类型和方向
2) 物体的表面材质属性
3)物体三角形面法向量朝向
4)观察者的方向

光照模型(光照颜色计算方程)

光照的标准方程,各种光照的合成:
Clit = Cspec + Cdiff + Camb
物体表面的光照值等于镜面反射颜色 + 漫反射颜色 + 环境光反射颜色。

一、设置光源(类型位置方向,镜面反射,漫反射,环境光颜色),材质(光泽度,镜面反射,漫反射,环境光颜色),距离
总结:一般光照在图形API硬件中计算,那么只需要我们做的事情:
1)开启光照开关
2)设置光源的类型,光源的位置和方向(如果是平行光则不需要位置),光源的镜面反射Sspec和漫反射的颜色Sdiff,或者全局光照的颜色Gamb.
3)设置物体顶点的光泽度Mgls,物体顶点的镜面反射颜色Mspec;物体顶点的漫反射颜色Mdiff;一般物体的Mamb =Mdiff;如果是自发光还有发射颜色.
4)光线衰弱的参数dmin, dmax.

总结:一般需要雾化在图形API硬件中计算,那么只需要我们做的事情:
1)开启雾化开关
2)设置雾的颜色Gfog
3)设置雾化的距离dmin和dmax


颜色可以像向量一样计算:
.是向量点乘,(x1,y1).(x2,y2)= x1*x2 + y1*y2 = [x1y1距离|*[x2y2距离|*cos theta.
标量乘以颜色没有符合就是直接乘法。
光照颜色相加,是各个分量相加。
颜色相乘是按位乘就是RGBA X RGBA = (rxr,gxg,bxb, axa)。
光照颜色的最终alpha值是等于材料散射的alpha值。
光照后的顶点颜色 = 顶点处的发射颜色 + 全局环境光相乘颜色 + 衰减因子(平行光不会衰减)*聚光灯效果(点光源没有聚光灯衰减效果为1,平行光也为1)* 光照颜色(光源的环境+散射+镜面光成分)。
计算后颜色的值不在[0,1]之间则截取使得在之间。
OGL光照并不考虑其中一个物体挡住其它物体的可能性,因此它不会自动创建阴影,且被光照的物体不会向其它物体发射光线(要更高级的光照计算模型才行)。

光照镜面反射方程,漫反射方程,环境光方程, 光照的衰减方程,雾化增强方程,光照和雾化合成方程见:

OGL中实例

光源类型和光照模型

#include <GL/glut.h>
#include <stdlib.h>

/*  Initialize material property, light source, lighting model,
 *  and depth buffer.
 */
void InitLight1();
void init(void) 
{
   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat mat_shininess[] = { 50.0 };

   GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
   GLfloat white_light[] = { 1.0, 0.0, 1.0, 1.0 };
   GLfloat black_light[] = { 1.0, 0.0, .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);
   // 1. 材质设置,材质也是一种状态,后面的物体光照着色都会采用这种材质,除非变换了。
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); // 镜面反射颜色
   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // 光泽度,GL_SHININESS
   glMaterialfv(GL_FRONT, GL_DIFFUSE, white_light); // 漫反射颜色
   GLfloat mat_emission[] = { 0.3, 0.2, 0.2, 0.0 };
   glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); // 发射光

   // 2.光源设置,一般支持8个光源
   // 光源类型和位置,GL_POSITION属性传入的向量如果w等于0则是平行光(没有衰减),非0则是点光源,如果设置了spot属性就是聚光灯。
   // 光源的方向,平行光由物体表面到光源的位置决定。点光源的方向是360度的,聚光灯的方向由GL_SPOT_DIRECTION来指定。
   // 光源的位置和方向,都会被用模型视图矩阵转换,存储在视图坐标系中; 
   // 通过控制光源位置或方向的移动可以移动它,变换模型视图矩阵也可以变换它,投影矩阵对光源位置和方向没有影响。

   // 光源的衰减:
   // f = 1 / (Kc + Kl*d + Kd * d * d); 默认情况下Kc为1, Kl, Kd都为0。
   // 环境关, 镜面光,漫射光都会进行衰减;发射光和全局环境光却不会进行衰减,因此使用点光源或聚光灯会消耗更多性能。
   // 设置衰减:
   /* glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, .5);*/

   // 聚光灯:可以额外的设置聚光灯锥形顶角的半角大小,默认是180度,所以全角是360度就是点光源。
   // 可以设置方向,是确定光锥的轴。还可以设置距离衰减,设置中心到外围的衰减指数(cos theta ^n),n越高光越集中。
   // 聚光灯设置:
   //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);// 默认角度是180度
   //GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };
   //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);// 默认方向是(0,0,-1);
   //glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 1.0);// 默认不清楚
   // 光源的设置:
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
   // GL_LIGHT0的GL_SPECULAR,GL_DIFFUSE默认值是白色,其它灯光默认是黑色
   glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); 
   glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
   // GL_AMBIENT默认是黑色,默认都不开启环境光
   glLightfv(GL_LIGHT0, GL_AMBIENT, black_light);

   // 3.光照模型设置
//#define GL_LIGHT_MODEL_LOCAL_VIEWER       0x0B51 // 观察点位置,指定镜面反射角度是如何计算的
//#define GL_LIGHT_MODEL_TWO_SIDE           0x0B52 // 指定单面还是双面光照
//#define GL_LIGHT_MODEL_AMBIENT            0x0B53 // 环境光的RGBA强度
//#define GL_SHADE_MODEL                    0x0B54
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
   // 可以设置观察者无限远,还是本地位置,默认无限远处观察可以有效提高性能(只计算一次观察夹角h.n = v.l.n)。
   // 可以设置单面光照计算(正面),还是双面光照计算(正面和背面),默认是单面(正面光照计算)。
   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); // 观察点是本地的
   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);// 默认是无穷远处的观察点
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // 多边形双面光照,多边形的背面是正面法向量的反向向量
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);// 默认是关闭双面光照的
   // 镜面光在Fragment shader纹理贴图后;应该是最终光照颜色和纹理贴图采样颜色是乘法混合,后面镜面光照是加法混合
  /* glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
   glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);*/// 镜面光,漫射光,环境光,发射光 一起。

   // 4.开启光照,指定所有的光照功能
   glEnable(GL_LIGHTING);
   // 开启指定的光源,光照和光源都是状态,在开启的情况下渲染的物体都要进行和光源的光照计算
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);//深度检测要启用,否则光照颜色会被后面写入浅的颜色覆盖

   InitLight1();
}

void InitLight1()
{
    GLfloat light1_ambient[] = { 0.0, 1.0, 0.0, 1.0 };
    GLfloat light1_diffuse[] = { 0.0, 1.0, .0, 1.0 };
    GLfloat light1_specular[] = { .0, 1.0, .0, 1.0 };

    GLfloat light1_position[] = { -2, 2, 1, 1 };
    GLfloat light1_direction[] = { -1, -1, 0, 0 };

    glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
    // GL_LIGHT0的GL_SPECULAR,GL_DIFFUSE默认值是白色,其它灯光默认是黑色
    glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
    // GL_AMBIENT默认是黑色,默认都不开启环境光
    glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);

    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.5);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, .5);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, .2);

    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);// 默认角度是180度
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light1_direction);// 默认方向是(0,0,-1);
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);// 默认不清楚

    glEnable(GL_LIGHT1);
}
void display(void)
{
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_LIGHTING);
   glutSolidSphere (1.0, 40, 32);
   // 关闭光照,提高性能
   glDisable(GL_LIGHTING);

   glFlush ();
}

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)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 keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);//GLUT_RGB
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition(100, 100);
   glutCreateWindow(argv[0]);
   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}

 光源的移动效果,观察点的位置

#include <GL/glut.h>
#include <stdlib.h>

static int spin = 0;
typedef struct SPoint{
    float x;
    float y;
} CPoint;
CPoint mousePoint;
/*  Initialize material property, light source, lighting model,
 *  and depth buffer.
 */
void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);

  /* glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0);
   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0);
   glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, .5);*/
}

/*  Here is where the light position is reset after the modeling
 *  transformation (glRotated) is called.  This places the
 *  light at a new position in world coordinates.  The cube
 *  represents the position of the light.
 */
void display(void)
{
   GLfloat position[] = { 0.0, 0.0, 1.5, 1.0 };

   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glPushMatrix ();
   // 在视图变换之前,设置光源的位置,那么不需要每次都设置光源位置(此时光源位置和视图位置是相对的)
   // 改变视图变换(观察点位置),绘制物体,那么观察点位置将和光源相对位置固定。
   // 可以实现人物头顶照明灯,或手上火把,蜡烛效果。见:OGL BOOK Page 137.

   // 设置视图变换
   gluLookAt (0.0, 0.0, 20.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0);

   // 保存视图变换,在视图变换上进行光照位置和方向变换
   glPushMatrix ();
   // 旋转后,列式矩阵乘以位置实现光源位置的变换
   //glRotated ((GLdouble) spin, 1.0, 0.0, 0.0);
   glTranslated(mousePoint.x, mousePoint.y, 1.5);
   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, 18, 35);
   glPopMatrix ();
   glFlush ();
}

void reshape (int w, int h)
{
   glViewport (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();
}

void mouse(int button, int state, int x, int y)
{
   switch (button) {
      case GLUT_LEFT_BUTTON:
         if (state == GLUT_DOWN) {
            //spin = (spin + 30) % 360;
            spin = (spin + 1) % 5;
            mousePoint.x = x * 0.01;
            mousePoint.y = y * 0.01;
            glutPostRedisplay();
         }
         break;
      default:
         break;
   }
}

光照模型(光照颜色计算方程)

材质属性,物体表面法向量,光照计算模型:

材质设置,材质也是一种状态,后面的物体光照着色都会采用这种材质,除非变换了。
1.用glMaterialfv(face, lightAttt, value)批量的改变物体材质的光照属性颜色
include <stdlib.h>
#include <GL/glut.h>

/*  Initialize z-buffer, projection matrix, light source, 
 *  and lighting model.  Do not specify a material property here.
 */
void init(void)
{
   GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
   GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat position[] = { 0.0, 3.0, 2.0, 0.0 };
   GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
   GLfloat local_view[] = { 0.0 };

   glClearColor(0.0, 0.1, 0.1, 0.0);
   glEnable(GL_DEPTH_TEST);
   glShadeModel(GL_SMOOTH);

   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
   glLightfv(GL_LIGHT0, GL_POSITION, position); // 平行光
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);//环境光的强度
   glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);//GL_FALSE无穷远的光

   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
}

/*  Draw twelve spheres in 3 rows with 4 columns.  
 *  The spheres in the first row have materials with no ambient reflection.
 *  The second row has materials with significant ambient reflection.
 *  The third row has materials with colored ambient reflection.
 *
 *  The first column has materials with blue, diffuse reflection only.
 *  The second column has blue diffuse reflection, as well as specular
 *  reflection with a low shininess exponent.
 *  The third column has blue diffuse reflection, as well as specular
 *  reflection with a high shininess exponent (a more concentrated highlight).
 *  The fourth column has materials which also include an emissive component.
 *
 *  glTranslatef() is used to move spheres to their appropriate locations.
 */

void display(void)
{
   GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
   GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
   GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 };
   GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };
   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

   GLfloat no_shininess[] = { 0.0 };
   GLfloat low_shininess[] = { 5.0 };
   GLfloat high_shininess[] = { 100.0 };
   GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/*  draw sphere in first row, first column
 *  diffuse reflection only; no ambient or specular  
 */
   // 所有的材质,横轴是漫反射,低光泽度镜面反射,高光泽度镜面反射,自发光效果
   // 纵轴是没有环境光,有一般环境光,亮环境光的效果。
   glPushMatrix();
   glTranslatef (-3.75, 3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in first row, second column
 *  diffuse and specular reflection; low shininess; no ambient
 */
   glPushMatrix();
   glTranslatef (-1.25, 3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); // 镜面光,小光泽度大而平滑的光斑
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); // 发射光
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in first row, third column
 *  diffuse and specular reflection; high shininess; no ambient
 */
   glPushMatrix();
   glTranslatef (1.25, 3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); // 镜面光,大光泽度小而亮的光斑
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in first row, fourth column
 *  diffuse reflection; emission; no ambient or specular reflection
 */
   glPushMatrix();
   glTranslatef(3.75, 3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

   glPushMatrix();
   glTranslatef (6.25, 3.0, 0.0);
   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_SHININESS, high_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();


/*  draw sphere in second row, first column
 *  ambient and diffuse reflection; no specular  
 */
   glPushMatrix();
   glTranslatef (-3.75, 0.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in second row, second column
 *  ambient, diffuse and specular reflection; low shininess
 */
   glPushMatrix();
   glTranslatef (-1.25, 0.0, 0.0);
   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_SHININESS, low_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in second row, third column
 *  ambient, diffuse and specular reflection; high shininess
 */
   glPushMatrix();
   glTranslatef (1.25, 0.0, 0.0);
   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_SHININESS, high_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in second row, fourth column
 *  ambient and diffuse reflection; emission; no specular
 */
   glPushMatrix();
   glTranslatef (3.75, 0.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in third row, first column
 *  colored ambient and diffuse reflection; no specular  
 */
   glPushMatrix();
   glTranslatef (-3.75, -3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in third row, second column
 *  colored ambient, diffuse and specular reflection; low shininess
 */
   glPushMatrix();
   glTranslatef (-1.25, -3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in third row, third column
 *  colored ambient, diffuse and specular reflection; high shininess
 */
   glPushMatrix();
   glTranslatef (1.25, -3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

/*  draw sphere in third row, fourth column
 *  colored ambient and diffuse reflection; emission; no specular
 */
   glPushMatrix();
   glTranslatef (3.75, -3.0, 0.0);
   glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
   glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
   glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
   glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
   glutSolidSphere(1.0, 32, 32);
   glPopMatrix();

   glFlush();
}

void reshape(int w, int h)
{
   glViewport(0, 0, w, h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   float fScale = 1.3f;
   if (w <= (h * 2))
       glOrtho(fScale*-6.0, fScale*6.0, fScale*-3.0*((GLfloat)h * 2) / (GLfloat)w,
       fScale*3.0*((GLfloat)h * 2) / (GLfloat)w, -10.0, 10.0);
   else
       glOrtho(fScale*-6.0*(GLfloat)w / ((GLfloat)h * 2),
       fScale*6.0*(GLfloat)w / ((GLfloat)h * 2), fScale*-3.0, fScale*3.0, -10.0, 10.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (600, 450);
   glutCreateWindow(argv[0]);
   init();
   glutReshapeFunc(reshape);
   glutDisplayFunc(display);
   glutKeyboardFunc (keyboard);
   glutMainLoop();
   return 0; 
}

光照模型(光照颜色计算方程)
2.用glColorMaterial(face, lightAttr), glColor*单独的改变物体当前激活的光照属性颜色
可以减少频繁调用glMaterialfv设置材质的开销,用 glColorMaterial效率会更高,不能用于颜色索引模式

光照模型(光照颜色计算方程)
// 需要启用
 glEnable(GL_COLOR_MATERIAL); 
   glColorMaterial(GL_FRONT, GL_DIFFUSE);
   // 改变了GL_DIFFUSE物体材质的颜色
   glColor3f(0.2, 0.5, 0.8);
   // 绘制物体
   glDrawElements();
   glColorMaterial(GL_FRONT, GL_SPECULAR);
   // 改变的是GL_SPECULAR的颜色,而不会改变GL_DIFFUSE的材质颜色,因为当前只有一个是激活的。
   glColor3f(0.9, 0.0, 0.2);
   // 绘制物体
   glDrawElements();
#include <GL/glut.h>
#include <stdlib.h>

GLfloat diffuseMaterial[4] = { 0.5, 0.5, 0.5, 1.0 };

/*  Initialize material property, light source, lighting model,
 *  and depth buffer.
 */
void init(void) 
{
   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);
   glEnable(GL_DEPTH_TEST);

   glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseMaterial);
   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可以灵活的改变一个材质的颜色
   glColorMaterial(GL_FRONT, GL_DIFFUSE);
   // 需要启用
   glEnable(GL_COLOR_MATERIAL);
}

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glutSolidSphere(1.0, 40, 32);
   glFlush ();
}

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)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 mouse(int button, int state, int x, int y)
{
   switch (button) {
      case GLUT_LEFT_BUTTON:
         if (state == GLUT_DOWN) {
            diffuseMaterial[0] += 0.1;
            if (diffuseMaterial[0] > 1.0)
               diffuseMaterial[0] = 0.0;
            glColor4fv(diffuseMaterial);
            glutPostRedisplay();
         }
         break;
      case GLUT_MIDDLE_BUTTON:
         if (state == GLUT_DOWN) {
            diffuseMaterial[1] += 0.1;
            if (diffuseMaterial[1] > 1.0)
               diffuseMaterial[1] = 0.0;
            glColor4fv(diffuseMaterial);
            glutPostRedisplay();
         }
         break;
      case GLUT_RIGHT_BUTTON:
         if (state == GLUT_DOWN) {
            diffuseMaterial[2] += 0.1;
            if (diffuseMaterial[2] > 1.0)
               diffuseMaterial[2] = 0.0;
            glColor4fv(diffuseMaterial);
            glutPostRedisplay();
         }
         break;
      default:
         break;
   }
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutMouseFunc(mouse);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}


光照模型(光照颜色计算方程)

颜色索引模式只能用于局部环境光,漫反射,镜面反射,不能用于全局环境光和发射光。且要创建渐变的颜色表,不能控制材料的颜色,只能用0.3*Rl + 0.59*Gl + 0.11*Bl;Rl是光源的红色分量,其它类似,材料的颜色不能参与进来,所以无论是实时光照还是烘焙光照都不采用颜色索引模式来计算光照。


光照模型(光照颜色计算方程)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值