真实感图形绘制是计算机图形学的一个重要组成部分,它综合利用数学、物理学、计算机科学和其它科学知识在计算机图形设备上生成象彩色照片那样的具有真实感的图形。一般说来,用计算机在图形设备上生成真实感图形必须完成以下四个步骤:一是用建模,即用一定的数学方法建立所需三维场景的几何描述,场景的几何描述直接影响图形的复杂性和图形绘制的计算耗费;二是将三维几何模型经过一定变换转为二维平面透视投影图;三是确定场景中所有可见面,运用隐藏面消隐算法将视域外或被遮挡住的不可见面消去;四是计算场景中可见面的颜色,即根据基于光学物理的光照模型计算可见面投射到观察者眼中的光亮度大小和颜色分量,并将它转换成适合图形设备的颜色值,从而确定投影画面上每一象素的颜色,最终生成图形。
  由于真实感图形是通过景物表面的颜色和明暗色调来表现景物的几何形状、空间位置以及表面材料的,而一个物体表面所呈现的颜色是由表面向视线方向辐射的光能决定的。在计算机图形学中,常采用一个既能表示光能大小又能表示其颜色组成的物理量即光亮度(luminance)或光强(intensity of light)来描述物体表面朝某方向辐射光能的颜色。采用这个物理量可以正确描述光在物体表面的反射、透射和吸收现象,因而可以正确计算处物体表面在空间给定方向上的光能颜色。
  物体表面向空间给定方向辐射的光强可应用光照模型进行计算。简单的光照模型通常假定物体表面是光滑的且由理想材料构成,因此只考虑光源照射在物体表面产生的反射光,所生成的图形可以模拟处不透明物体表面的明暗过渡,具有一定的真实感效果。复杂的光照模型除了考虑上述因素外,还要考虑周围环境的光对物体表面的影响。如光亮平滑的物体表面会将环境中其它物体映像在表面上,而通过透明物体也可看到其后的环境景象。这类光照模型称为整体光照模型,它能模拟出镜面映像、透明等较精致的光照效果。为了更真实的绘制图形,还要考虑物体表面的细节纹理,这通常使用一种称为“纹理映射”(texture mapping)的技术把已有的平面花纹图案映射到物体表面上,并在应用光照模型时将这些花纹的颜色考虑进去,物体表面细节的模拟使绘制的图形更接近自然景物。
  以上内容中,真实感图形绘制的四大步骤前两步在前面的章节已经详细介绍过,这里不再重复,第三步OpenGL将自动完成所有消隐过程,第四步下面几节详述。另外,部分复杂光照模型应用将在后续章节里介绍。

10.2、光照模型

  10.2.1 简单光照模型
  当光照射到一个物体表面上时,会出现三种情形。首先,光可以通过物体表面向空间反射,产生反射光。其次,对于透明体,光可以穿透该物体并从另一端射出,产生透射光。最后,部分光将被物体表面吸收而转换成热。在上述三部分光中,仅仅是透射光和反射光能够进入人眼产生视觉效果。这里介绍的简单光照模型只考虑被照明物体表面的反射光影响,假定物体表面光滑不透明且由理想材料构成,环境假设为由白光照明。
  一般来说,反射光可以分成三个分量,即环境反射、漫反射和镜面反射。环境反射分量假定入射光均匀地从周围环境入射至景物表面并等量地向各个方向反射出去,通常物体表面还会受到从周围环境来的反射光(如来自地面、天空、墙壁等的反射光)的照射,这些光常统称为环境光(Ambient Light);漫反射分量表示特定光源在景物表面的反射光中那些向空间各方向均匀反射出去的光,这些光常称为漫射光(Diffuse Light);镜面反射光为朝一定方向的反射光,如一个点光源照射一个金属球时会在球面上形成一块特别亮的区域,呈现所谓“高光(Highlight)”,它是光源在金属球面上产生的镜面反射光(Specular Light)。对于较光滑物体,其镜面反射光的高光区域小而亮;相反,粗糙表面的镜面反射光呈发散状态,其高光区域大而不亮。下面先看一个简单的光照例程。

  例10-1 简单光照例程(light0.c)

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);
  void CALLBACK display(void);

  void myinit(void)
  {
    GLfloat light_position[] = { 1.0, 1.0, 1.0,0.0 };

    glLightfv(GL_LIGHT0, GL_POSITION,light_position);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
  }

  void CALLBACK display(void)
  {
    glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
    auxSolidSphere(1.0);
    glFlush();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, 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 main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow ("SimpleLighting");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

  以上程序运行结果是显示一个具有灰色光影的球。其中函数myinit()中包含了关键的设定光源位置、启动光照等几句,而其它程序语言几乎与以前的没有多大区别,但效果却完全不一样。下面几个小节将详细介绍有关函数的用法。

<!--[if gte vml 1]> <![endif]-->

图10-1 带光影的灰色球体

  10.2.2 OpenGL光组成
  在OpenGL简单光照模型中的几种光分为:辐射光(Emitted Light)、环境光(Ambient Light)、漫射光(Diffuse Light)、镜面光(Specular Light)。
  辐射光是最简单的一种光,它直接从物体发出并且不受任何光源影响。
  环境光是由光源发出经环境多次散射而无法确定其方向的光,即似乎来自所有方向。一般说来,房间里的环境光成分要多些,户外的相反要少得多,因为大部分光按相同方向照射,而且在户外很少有其他物体反射的光。当环境光照到曲面上时,它在各个方向上均等地发散(类似于无影灯光)。
  漫射光来自一个方向,它垂直于物体时比倾斜时更明亮。一旦它照射到物体上,则在各个方向上均匀地发散出去。于是,无论视点在哪里它都一样亮。来自特定位置和特定方向的任何光,都可能有散射成分。
  镜面光来自特定方向并沿另一方向反射出去,一个平行激光束在高质量的镜面上产生100%的镜面反射。光亮的金属和塑料具有很高非反射成分,而象粉笔和地毯等几乎没有反射成分。因此,三某种意义上讲,物体的反射程度等同于其上的光强(或光亮度)。

  10.2.3 创建光源(Light Source)
  光源有许多特性,如颜色、位置、方向等。选择不同的特性值,则对应的光源作用在物体上的效果也不一样,这在以后的章节中会逐步介绍的。下面详细讲述定义光源特性的函数glLight*():

  void glLight{if}[v](GLenum light , GLenumpname, TYPE param)

  创建具有某种特性的光源。其中第一个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7。第二个参数pname指定光源特性,这个参数的辅助信息见表10-1所示。最后一个参数设置相应的光源特性值。

pname 参数名

缺省值

说明

GL_AMBIENT

(0.0, 0.0, 0.0, 1.0)

RGBA模式下环境光

GL_DIFFUSE

(1.0, 1.0, 1.0, 1.0)

RGBA模式下漫反射光

GL_SPECULAR

(1.0,1.0,1.0,1.0)

RGBA模式下镜面光

GL_POSITION

(0.0,0.0,1.0,0.0)

光源位置齐次坐标(x,y,z,w)

GL_SPOT_DIRECTION

(0.0,0.0,-1.0)

点光源聚光方向矢量(x,y,z)

GL_SPOT_EXPONENT

0.0

点光源聚光指数

GL_SPOT_CUTOFF

180.0

点光源聚光截止角

GL_CONSTANT_ATTENUATION

1.0

常数衰减因子

GL_LINER_ATTENUATION

0.0

线性衰减因子

GL_QUADRATIC_ATTENUATION

0.0

平方衰减因子

表10-1 函数glLight*()参数pname说明

  ?注意:以上列出的GL_DIFFUSE和GL_SPECULAR的缺省值只能用于GL_LIGHT0,其他几个光源的GL_DIFFUSE和GL_SPECULAR缺省值为(0.0,0.0,0.0,1.0)。另外,表中后六个参数的应用放在下一篇中介绍。在上面例程中,光源的创建为:

  GLfloat light_position[] = { 1.0, 1.0, 1.0,0.0 };
  glLightfv(GL_LIGHT0, GL_POSITION,light_position);

  其中light_position是一个指针,指向定义的光源位置齐次坐标数组。其它几个光源特性都为缺省值。同样,我们也可用类似的方式定义光源的其他几个特性值,例如:

  GLfloat light_ambient [] = { 0.0, 0.0, 0.0,1.0 };
  GLfloat light_diffuse [] = { 1.0, 1.0, 1.0,1.0 };
  GLfloat light_specular[] = { 1.0, 1.0, 1.0,1.0 };
  glLightfv(GL_LIGHT0, GL_AMBIENT ,light_ambient );
  glLightfv(GL_LIGHT0, GL_DIFFUSE ,light_diffuse );
  glLightfv(GL_LIGHT0, GL_SPECULAR,light_specular);

  10.2.4 启动光照
  在OpenGL中,必须明确指出光照是否有效或无效。如果光照无效,则只是简单地将当前颜色映射到当前顶点上去,不进行法向、光源、材质等复杂计算,那么显示的图形就没有真实感,如前几章例程运行结果显示。要使光照有效,首先得启动光照,即:

  glEnable(GL_LIGHTING);

  若使光照无效,则调用gDisable(GL_LIGHTING)可关闭当前光照。然后,必须使所定义的每个光源有效,例light0.c中只用了一个光源,即:

  glEnable(GL_LIGHT0);

  其它光源类似,只是光源号不同而已。

10.3、明暗处理
  在计算机图形学中,光滑的曲面表面常用多边形予以逼近和表示,而每个小多边形轮廓(或内部)就用单一的颜色或许多不同的颜色来勾画(或填充),这种处理方式就称为明暗处理。在OpenGL中,用单一颜色处理的称为平面明暗处理(Flat Shading),用许多不同颜色处理的称为光滑明暗处理(Smooth Shading),也称为Gourand明暗处理(Gourand Shading)。设置明暗处理模式的函数为:

  void glShadeModel(GLenum mode);

  函数参数为GL_FLAT或GL_SMOOTH,分别表示平面明暗处理和光滑明暗处理。
  应用平面明暗处理模式时,多边形内每个点的法向一致,且颜色也一致;应用光滑明暗处理模式时,多边形所有点的法向是由内插生成的,具有一定的连续性,因此每个点的颜色也相应内插,故呈现不同色。这种模式下,插值方法采用的是双线性插值法,如图10-2所示。

<!--[if gte vml 1]> <![endif]-->

图10-2 Gouraud明暗处理

  Gouraud明暗处理通常算法为:先用多边形顶点的光强线性插值出当前扫描线与多边形边交点处的光强,然后再用交点的光强线插值处扫描线位于多边形内区段上每一象素处的光强值。图中显示出一条扫描线与多边形相交,交线的端点是A点和B点,P点是扫描线上位于多边形内的任一点,多边形三个顶点的光强分别为I1、I2和I3.取A点的光强Ia为I1和I2的线性插值,B点的光强Ib为I1和I3的线性插值,P点的光强Ip则为Ia和Ib的线性插值。采用Gouraud明暗处理不但可以使用多边形表示的曲面光强连续,而且计算量很小。这种算法还可以以增量的形式改进,且能用硬件直接实现算法,从而广泛用于计算机实时图形生成。请看下面光滑明暗处理的例程:

  例10-2 明暗处理例程(Shading.c)

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glaux.h>

  void myinit(void);
  void object(void);
  void CALLBACK display(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);

  /* GL_SMOOTH is actually the defaultshading model. */
  void myinit (void)
  {
    glShadeModel (GL_SMOOTH);
  }

  void object(void)
  {
    glBegin (GL_POLYGON);
      glColor3f (1.0, 0.0, 0.0);
        glVertex2f (4.0, 4.0);
      glColor3f(1.0,1.0,1.0);
        glVertex2f (12.0, 4.0);
      glColor3f(0.0,0.0,1.0);
        glVertex2f (12.0, 12.0);
      glColor3f(0.0,1.0,0.0);
        glVertex2f (4.0, 12.0);
    glEnd ();
  }

  void CALLBACK display(void)
  {
    glClear (GL_COLOR_BUFFER_BIT);
    object ();
    glFlush ();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
      gluOrtho2D (0.0, 16.0, 0.0, 16.0 *(GLfloat) h/(GLfloat) w);
    else
      gluOrtho2D (0.0, 16.0 * (GLfloat)w/(GLfloat) h, 0.0, 16.0);
    glMatrixMode(GL_MODELVIEW);
  }

  void main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow ("Smooth Shading");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

  以上程序运行结果是在屏幕上显示一个色彩连续变化的三角形。这个程序是用的RGBA显示模式,若改用颜色表模式,则颜色内插实际上是颜色表的内插,因此呈现的颜色可能不连续。网友不妨自己试试。
  另外,若在light0.c程序中加上一句定义GL_FLAT明暗处理模式,则又会出现怎样的情形呢?读者可以仔细比较一下。

<!--[if gte vml 1]> <![endif]-->

图10-3 高氏明暗处理的正方形

10.4、材质

  10.4.1 材质颜色
  OpenGL用材料对光的红、绿、蓝三原色的反射率来近似定义材料的颜色。象光源一样,材料颜色也分成环境、漫反射和镜面反射成分,它们决定了材料对环境光、漫反射光和镜面反射光的反射程度。在进行光照计算时,材料对环境光的反射率与每个进入光源的环境光结合,对漫反射光的反射率与每个进入光源的漫反射光结合,对镜面光的反射率与每个进入光源的镜面反射光结合。对环境光与漫反射光的反射程度决定了材料的颜色,并且它们很相似。对镜面反射光的反射率通常是白色或灰色(即对镜面反射光中红、绿、蓝的反射率相同)。镜面反射高光最亮的地方将变成具有光源镜面光强度的颜色。例如一个光亮的红色塑料球,球的大部分表现为红色,光亮的高光将是白色的。

  10.4.2 材质定义
  材质的定义与光源的定义类似。其函数为:

  void glMaterial{if}[v](GLenum face,GLenumpname,TYPE param);

  定义光照计算中用到的当前材质。face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,它表明当前材质应该应用到物体的哪一个面上;pname说明一个特定的材质;param是材质的具体数值,若函数为向量形式,则param是一组值的指针,反之为参数值本身。非向量形式仅用于设置GL_SHINESS。pname参数值具体内容见表10-1。另外,参数GL_AMBIENT_AND_DIFFUSE表示可以用相同的RGB值设置环境光颜色和漫反射光颜色。

参数名

缺省值

说明

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_SHINESS

0.0

镜面指数(光亮度)

GL_EMISSION

(0.0, 0.0, 0.0, 1.0)

材料的辐射光颜色

GL_COLOR_INDEXES

(0, 1, 1)

材料的环境光、漫反射光和镜面光颜色

表10-2 函数glMaterial*()参数pname的缺省值

  例10-3 材质定义例程(light1.c)

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);

  void CALLBACK display(void); voidmyinit(void)
  {
    /* 设置材质的各种光的颜色成分反射比率 */
    GLfloat mat_ambient[]={0.8,0.8,0.8,1.0};
    GLfloat mat_diffuse[]={0.8,0.0,0.8,1.0};     /*紫色 */
    GLfloat mat_specular[] = { 1.0, 0.0, 1.0,1.0 }; /*亮紫色 */
    GLfloat mat_shininess[] = { 50.0 };

    GLfloat light_position[] = { 1.0, 1.0, 1.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,mat_shininess);

    glLightfv(GL_LIGHT0, GL_POSITION,light_position);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
  }

  void CALLBACK display(void)
  {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    auxSolidSphere(1.0);
    glFlush();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, 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 main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA |AUX_DEPTH16);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow ("Lighting_1 ");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

  以上程序运行结果是一个紫色的球。在函数myinit()中定义了球的材质颜色,光源的定义仍延用light0.c中的,而light.c物体的光源定义为缺省形式。从例子中明显地看出,物体的材质颜色定义与光源颜色定义几乎一样,物体反射到眼中的颜色与二者都有关系,具体关系请看下一小节。

  10.4.3 材质RGB值和光源RGB值的关系
  材质的颜色与光源的颜色有些不同。对于光源,R、G、B值等于R、G、B对其最大强度的百分比。若光源颜色的R、G、B值都是1.0,则是最强的白光;若值变为0.5,颜色仍为白色,但强度为原来的一半,于是表现为灰色;若R=G=1.0,B=0.0,则光源为黄色。对于材质,R、G、B值为材质对光的R、G、B成分的反射率。比如,一种材质的R=1.0、G=0.5、B=0.0,则材质反射全部的红色成分,一半的绿色成分,不反射蓝色成分。也就是说,若OpenGL的光源颜色为(LR、LG、LB),材质颜色为(MR、MG、MB),那么,在忽略所有其他反射效果的情况下,最终到达眼睛的光的颜色为(LR*MR、LG*MG、LB*MB)。
  同样,如果有两束光,相应的值分别为(R1、G1、B1)和(R2、G2、B2),则OpenGL将各个颜色成分相加,得到(R1+R2、G1+G2、B1+B2),若任一成分的和值大于1(超出了设备所能显示的亮度)则约简到1.0。下面一例程就说明了二者之间的关系。

  例10-4 材质与光源的RGB关系例程(light2.c)

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);
  void CALLBACK display(void);

  void myinit(void)
  {
    GLfloat mat_ambient[]= { 0.8, 0.8, 0.8, 1.0};
    GLfloat mat_diffuse[]= { 0.8, 0.0, 0.8, 1.0}; /*紫色 */
    GLfloat mat_specular[] = { 1.0, 0.0, 1.0,1.0 };
    GLfloat mat_shininess[] = { 50.0 };

    GLfloat light_diffuse[]= { 0.0, 0.0, 1.0,1.0}; /*蓝色 */
    GLfloat light_position[] = { 1.0, 1.0, 1.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,mat_shininess);

    glLightfv(GL_LIGHT0, GL_DIFFUSE,light_diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION,light_position);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
  }

  void CALLBACK display(void)
  {
    glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
    auxSolidSphere(1.0);
    glFlush();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, 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 main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA |AUX_DEPTH16);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow ("Lighting_2 ");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

  以上程序运行结果是一个蓝色的球,其中高光部分仍为上一例的亮紫色。从上可看出,球漫反射光的结果是mat_diffuse[]与light_diffuse[]中的三个颜色分量值相乘,即(0.0*1.0,0.0*1.0,0.8*1.0,1.0*1.0)=(0.0,0.0,0.8,1.0),所以球大部分呈现蓝色。

<!--[if gte vml 1]> <![endif]-->

图10-4 光照蓝色球高光为红色

  10.4.4 材质改变
  在实际应用的许多情况下,不同的物体或同一物体的不同部分都有可能设置不同的材质,OpenGL函数库提供了两种方式实现这种要求。下面一例程采用的是设置矩阵堆栈来保存不同物体的材质信息:

  例10-5 矩阵堆栈改变材质例程(chgmat1.c)

  #include "glos.h"
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK display(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);

  /* 初始化z-buffer、光源和光照模型,在此不具体定义材质。*/
  void myinit(void)
  {
    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat specular[] = { 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 };

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION,position);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glClearColor(0.0, 0.1, 0.1, 0.0);
  }

  void CALLBACK 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);

    /* 第一行第一列绘制的球仅有漫反射光而无环境光和镜面光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第一行第二列绘制的球有漫反射光和镜面光,并有低高光,而无环境光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第一行第三列绘制的球有漫反射光和镜面光,并有很亮的高光,而无环境光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第一行第四列绘制的球有漫反射光和辐射光,而无环境和镜面反射光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第二行第一列绘制的球有漫反射光和环境光,而镜面反射光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第二行第二列绘制的球有漫反射光、环境光和镜面光,且有低高光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第二行第三列绘制的球有漫反射光、环境光和镜面光,且有很亮的高光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第二行第四列绘制的球有漫反射光、环境光和辐射光,而无镜面光。*/
    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);
    auxSolidSphere(1.0); glPopMatrix();

    /* 第三行第一列绘制的球有漫反射光和有颜色的环境光,而无镜面光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第三行第二列绘制的球有漫反射光和有颜色的环境光以及镜面光,且有低高光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第三行第三列绘制的球有漫反射光和有颜色的环境光以及镜面光,且有很亮的高光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    /* 第三行第四列绘制的球有漫反射光和有颜色的环境光以及辐射光,而无镜面光。*/
    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);
    auxSolidSphere(1.0);
    glPopMatrix();

    glFlush();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= (h * 2))
      glOrtho (-6.0, 6.0,-3.0*((GLfloat)h*2)/(GLfloat)w,
        3.0*((GLfloat)h*2)/(GLfloat)w, -10.0,10.0);
    else
      glOrtho (-6.0*(GLfloat)w/((GLfloat)h*2),
        6.0*(GLfloat)w/((GLfloat)h*2), -3.0, 3.0,-10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
  }

  void main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 600, 450);
    auxInitWindow ("Material");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

<!--[if gte vml 1]> <![endif]-->

图10-5 多种光和材质的变化效果

  以上程序运行结果是绘制12个球(3行4列)。第一行的球材质都没有环境反射光,第二行的都有一定的环境反射光,第三行的都有某种颜色的环境光。而第一列的球材质仅有蓝色的漫反射光;第二列的不仅有蓝漫反射光,而且还有镜面反射光,较低的高光;第三列的不仅有蓝漫反射光,而且还有镜面反射光,很亮的高光;第四列的还包括辐射光,但无镜面光。
  这个程序运用矩阵堆栈多次调用glMaterialfv()来设置每个球的材质,也就是改变同一场景中的不同物体的颜色。但由于这个函数的应用有个性能开销,因此建议最好尽可能少的改变材质,以减少改变材质时所带来的性能开销,可采用另一种方式即改变材质颜色,相应函数为glColorMaterial(),说明如下:

  void glColorMaterial(GLenum face,GLenummode);

  函数参数face指定面,值有GL_FRONT、GL_BACK或GL_FRONT_AND_BACK(缺省值)。mode指定材质成分,值有GL_AMBIENT、GL_DIFFUSE、GL_AMBIENT_AND_DIFFUSE(缺省值)、GL_SPECULAR或GLEMISSION。
  注意:这个函数说明了两个独立的值,第一个参数说明哪一个面和哪些面被修改,而第二个参数说明这些面的哪一个或哪些材质成分要被修改。OpenGL并不为每一种face保持独立的mode变量。在调用glColorMterial()以后,首先需要用GL_COLOR_MATERIAL作为参数调用glEnable()来启动颜色材质,然后在绘图时调用glColor*()来改变当前颜色,或用glMaterial()来改变材质成分。当不用这种方式来改变材质时,可调用glDisable(GL_COLOR_MATERIAL)来关闭取消。如下面一段代码:

  glColorMaterial(GL_FRONT,GL_DIFFUSE);
  glEnable(GL_COLOR_MATERIAL);
  glColor3f(0.3,0.5,0.7);
  /* draw some objects here. */
  glcolor3f(0.0,1.0,0.0);
  /* draw other objects here.*/
  glDisable(GL_COLOR_MATERIAL);

  当需要改变场景中大部分方面的单个材质时,最好调用glColorMaterial();当需要修改不止一个材质参数时,最好调用glMaterial*()。注意,当不需要颜色材质时一定要关闭它,以避免相应的开销。下面来看一个颜色材质的具体应用例子:

  例10-6 颜色定义改变材质例程(chgmat2.c)

  #include "glos.h"?
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glaux.h>

  void myinit(void);
  void CALLBACK myReshape(GLsizei w, GLsizeih);
  void CALLBACK display(void);

  void myinit(void)
  {
    GLfloat light_position[] = { 1.0, 1.0, 1.0,0.0 };

    glLightfv(GL_LIGHT0, GL_POSITION,light_position);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);

    glColorMaterial(GL_FRONT, GL_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);
  }

  void CALLBACK display(void)
  {
    glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);

    /* draw one yellow ball */
    glLoadIdentity();
    glTranslatef(-0.7,0.0,0.0);
    glColor3f(1.0,1.0,0.0);
    auxSolidSphere(0.5);

    /* draw one red cone */
    glLoadIdentity();
    glRotatef(-65.0,1.0,0.0,0.0);
    glTranslatef(0.7,0.0,0.0);
    glColor3f(1.0,0.0,0.0);
    auxSolidCone(0.4,0.6);

    glFlush();
  }

  void CALLBACK myReshape(GLsizei w, GLsizeih)
  {
    glViewport(0, 0, w, 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 main(void)
  {
    auxInitDisplayMode (AUX_SINGLE | AUX_RGB |AUX_DEPTH16);
    auxInitPosition (0, 0, 500, 500);
    auxInitWindow ("ColorMaterialMode");
    myinit();
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
  }

  以上程序改变的是漫反射颜色。场景中显示了一个黄色的球和一个红色的锥体。




1.光源

事实上光源才是所有光照效果的基础,没有光源一切都无从谈起。OpenGL中我们可以设置8个光源,其编号分别为GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7。就相当于现实生活中有8个太阳,但每个太阳的位置、方向及它发出的光线可以完全不同。因此,OpenGL中我们设置光源时,主要就是设置其颜色、位置、方向等性质。另外,OpenGL中任何一个光源都可以发出不同强度的环境光、散射光、镜面反射光,这几个方面综合起来就决定了光源的颜色。

我们通过glLightfv(光源编号,光源特性,参数数据)来设置光源。其中,光源编号可取GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7共8个值。光源特性主要可取GL_AMBIENT(设置光源的环境光属性,默认值(0,0,0,1))、GL_DIFFUSE(设置光源的散射光属性,默认值(1,1,1,1))、GL_SPECULAR(设置光源的镜面反射光属性,默认值(1,1,1,1))、GL_POSITION(设置光源的位置,默认值(0,0,1,0))。参数数据格式要求为数组形式,即数学上的向量形式。

下面一段代码,我们将一个光源的性质进行完整设置:

  1. GLfloat Va[]={0.4,0.4,0.4,1};           //光源环境光强度数组
  2. GLfloat Vd[]={0.6,0.6,0.6,1};           //光源散射光强度数组
  3. GLfloat Vs[]={0.6,0.6,0.6,1};           //光源镜面反射光强度数组
  4. GLfloat Vp[]={1,1,1,1};             //光源位置数组
  5. glLightfv(GL_LIGHT0,GL_AMBIENT,Va); //设置0号光源的环境光属性
  6. glLightfv(GL_LIGHT0,GL_DIFFUSE,Vd); //设置0号光源的散射光属性
  7. glLightfv(GL_LIGHT0,GL_SPECULAR,Vs);    //设置0号光源的镜面反射光属性
  8. glLightfv(GL_LIGHT0,GL_POSITION,Vp);    //设置0号光源的位置属性

光源的性质设置完毕,还要调用glEnable(GL_LIGHT0)来打开光源。就相当于你买回手电筒、装好电池(设置光源),但如果不打开开关(打开电源),手电筒是不起作用的。

另外,对于GL_POSITION,其位置数组(x,y,z,w)定义了光源在空间中的位置。但三维空间为什么需要4个量呢?事实上这里采用的是齐次坐标,当w≠0时,它表示光源处于空间中(x,y,z)处,这时的光源称为定点光源;当w=0时,根据齐次坐标的性质,它表示光源位于无穷远处,此时光源称为定向光源,其所有光线几乎是相互平等的,如太阳。其光线方向由点(x,y,z)指向(0,0,0)。

将第2章中的正方体的例子做以下修改。修改后的void __fastcall TForm1::OpenGL1 GLPaint(TObject *Sender)处的代码如下(其余位置不变):

  1. void __fastcall TForm1::OpenGL1GLPaint(TObject *Sender)
  2. {
  3. glEnable(GL_DEPTH_TEST);          //隐藏表面消除
  4. glClear(GL_DEPTH_BUFFER_BIT); //清除窗口颜色
  5. const GLfloat glfLightAmbient1[4] = {0.1, 0.1, 0.1, 1.0};
  6. const GLfloat glfLightAmbient2[4] = {0.4, 0.4, 0.4, 1.0};
  7. const GLfloat glfLightDiffuse1[4] = {0, 0.8, 0.8, 1.0};
  8. const GLfloat glfLightDiffuse2[4] = {0.8, 0.8, 0.8, 1.0};
  9. const GLfloat glfLightSpecular1[4] = {0, 0.8, 0.8, 1.0};
  10. const GLfloat glfLightSpecular2[4] = {0.8, 0.8, 0.8, 1.0};
  11. const GLfloat glPosition1[4]={0,0,1,0};
  12. const GLfloat glPosition2[4]={0.6,0.6,-0.6,1};
  13. glLightfv(GL_LIGHT0, GL_AMBIENT,  glfLightAmbient1);
  14. glLightfv(GL_LIGHT0, GL_DIFFUSE,  glfLightDiffuse1);
  15. glLightfv(GL_LIGHT0, GL_SPECULAR, glfLightSpecular1);
  16. glLightfv(GL_LIGHT0,GL_POSITION,glPosition1);
  17. glLightfv(GL_LIGHT1, GL_AMBIENT,  glfLightAmbient2);
  18. glLightfv(GL_LIGHT1, GL_DIFFUSE,  glfLightDiffuse2);
  19. glLightfv(GL_LIGHT1, GL_SPECULAR, glfLightSpecular2);
  20. glLightfv(GL_LIGHT1,GL_POSITION,glPosition2);
  21. glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);//两面照亮
  22. glEnable(GL_LIGHTING);//启用光照
  23. glEnable(GL_LIGHT0);
  24. glEnable(GL_LIGHT1);//打开光源
  25. glEnable(GL_COLOR_MATERIAL);//启用颜色追踪
  26. glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
  27. //物体正面的材料环境颜色和散射颜色,追踪glColor所设置的颜色(比较拗口, 事实上就是让OpenGL根据glColor所设置的颜色自动设置物体的反射强度)
  28. glShadeModel(GL_FLAT);//设置颜色填充模式
  29. glBegin(GL_QUAD_STRIP) ;
  30. glVertex3f(i,-i,i);
  31. glVertex3f(i,-i,-i);
  32. glColor3f(1,0,0);
  33. glVertex3f(-i,-i,i);
  34. glVertex3f(-i,-i,-i);
  35. glColor3f(0,1,0);
  36. glVertex3f(-i,i,i);
  37. glVertex3f(-i,i,-i);
  38. glColor3f(0,0,1);
  39. glVertex3f(i,i,i);
  40. glVertex3f(i,i,-i);
  41. glColor3f(1,1,0);
  42. glVertex3f(i,-i,i);
  43. glVertex3f(i,-i,-i);
  44. glEnd();
  45. glBegin(GL_QUADS);
  46. glVertex3f(i,-i,i);
  47. glVertex3f(-i,-i,i);
  48. glVertex3f(-i,i,i);
  49. glColor3f(1,0,1);
  50. glVertex3f(i,i,i);
  51. glVertex3f(i,-i,-i);
  52. glVertex3f(-i,-i,-i);
  53. glVertex3f(-i,i,-i);
  54. glColor3f(0,1,1);
  55. glVertex3f(i,i,-i);
  56. glEnd();
  57. glDisable(GL_LIGHTING);//关闭光照
  58. glDisable(GL_LIGHT0);//关闭0号光源
  59. glDisable(GL_LIGHT1); //关闭1号光源
  60. }

2.材料

一句话glColorMaterial的作用是用来在绘图的过程中实时的设置材质。通常情况下设置一个物体的材质需要以下这么5个属性需要设置。

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);
除了采用glMaterialfv()设置材质外,还可以使用glColorMaterial()设置材质属性。

void glColorMaterial(GLenum face,GLenum mode)来实现。
face的取值: GL_FRONT GL_BACK GL_FRONT_AND_BACK
mode的取值: GL_AMBIENT GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE GL_SPECULAR GL_EMISSION
在想要使用这个函数时,要启用glEnable(GL_COLOR_MATERIAL)来是函数工作。
在绘图时使用glColor*()来实时改变材质颜色,或用glMaterial()来实时改变材质成分
使用完毕,要用glDisable(GL_COLOR_MATERIAL)来关闭这种材质模式。

例如:
glColorMaterial(GL_FRONT,GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);

glColor3f(0.3,0.5,0.7);
//画一些物体:
...

glColor3f(0.0,1.0,0.0);
//再画另一些物体:
...

glDisable(GL_COLOR_MATERIAL);

说明:
当需要改变场景中大部分方面的 单个材质时,最好调用glColorMaterial()
当修改不只一个材质参数,最好调用glMaterial*(),这是目前我体会到唯一的使用功能上的不同点吧。

openGL的光照与材料(一)相关推荐

  1. Android OpenGL添加光照和材料属性

    转载请注明出处:[huachao1001的专栏:http://blog.csdn.net/huachao1001] 在上一篇文章[ Android OpenGL显示任意3D模型文件 ]中,我们学习了如 ...

  2. OpenGL阴影添加学习材料及总结

    学习材料 PBR 基于物理的实时渲染 采用了更符合物理学规律的方式来模拟光线,通过模拟虚拟物体表面的粗糙程度,来计算出射该物体的光线呈现一个怎样的方式. PBR材料的三个主要参数称为:反照率.粗糙度. ...

  3. OpenGL Lightmap光照贴图的实例

    OpenGL Lightmap光照贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #include ...

  4. OpenGL 高级光照Advanced Lighting

    OpenGL高级光照Advanced Lighting 高级光照Advanced Lighting简介 Blinn-Phong 高级光照Advanced Lighting简介 在光照小节中,我们简单地 ...

  5. OpenGL 基础光照ColorsBasic Lighting

    OpenGL 基础光照ColorsBasic Lighting 基础光照ColorsBasic Lighting简介 环境光照 漫反射光照 法向量 计算漫反射光照 最后一件事 镜面光照 基础光照Col ...

  6. QT+OpenGL高级光照 Blinn-Phong和Gamma校正

    QT+OpenGL高级光照1 本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 Blinn-Phong 冯氏光照:视线与反射方向 ...

  7. 【OpenGL】光照太阳系

    一.要求 二.思路 0.效果图 1.实现基本的太阳系 采用局部变换的思路完成,实现太阳.地球.月亮及轨道的绘制 2.宇宙中加入一盏泛光(方向光) 加入思路: 1)设置好物体的法向 在这里可以不进行设置 ...

  8. OpenGL学习: 光照系列3-光源类型和使用多个光源

    写在前面  上一节光照中使用材质和lighting maps介绍了使用材质属性和lighting maps使物体的光照效果能反映物体的材料特性,看起来更逼真.在前面的章节中使用的实际上都是一个点光源, ...

  9. D3D 光照和材料 小样例

    1.实现一个旋转的圆柱体,体现d3d光照效果 2.程序实现 #pragma once#pragma comment(lib,"winmm.lib")#pragma comment( ...

最新文章

  1. 博客重构 / Blog Refactoring
  2. 怎么改变github的用户名字,身份?
  3. 主流机器学习模型模板代码+经验分享[xgb, lgb, Keras, LR]
  4. CF1080F Katya and Segments Sets
  5. ios企业应用发布流程
  6. linux命令中cd / 和 cd ~
  7. python基础知识点整理(1)
  8. MySql中json类型的使用___mybatis存取mysql中的json
  9. Go 空结构体的 3 种使用场景
  10. 实验三:分别用for、while和do-while循环语句以及递归方法计算n!,并输出算式...
  11. 怎样学好python编程-3个月学好Python有多简单?
  12. MS SQL 日常维护管理常用脚本(二)
  13. 街头篮球上读取服务器维护,《街头篮球》九月新版引入超级服务器
  14. [ZT]调侃、反讥与诡辩
  15. java通过itext方法往pdf中插入图片(交互式pdf插入图片无法显示)
  16. 鸿蒙开发|呼吸训练实战项目(一)
  17. 极米和当贝投影仪应该怎样抉择?一文告诉你答案
  18. excel这几大数据处理技巧,高效率操作技能,今天免费交给你!
  19. git bash的安装和配置教程
  20. 网络营销推广实战宝典 2.3 软文推广

热门文章

  1. 《2周攻克期权策略》读书笔记
  2. linux firefox 配置文件,对linux下firefox个人配置文件夹(profile)的一些说明
  3. webapi输出炜json_web Api 返回json 的两种方式
  4. Linux下RabbitMq的安装以及后台管理页面的安装
  5. 推荐这几个华为、阿里、腾讯超级牛人的公众号
  6. 曲线平滑算法:三次Hermite曲线生成
  7. ES2015也就是ES6知识点持续更新
  8. python通过POST提交页面请求
  9. 电子计算机在会计中的应用简称为会计电算化,浅析会计电算化在企业中的应用...
  10. 手机Camera基础知识